[
  {
    "path": ".gitee/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--  Thanks for sending a pull request!  Here are some tips for you:\n\nIf this is your first time, please read our contributor guidelines: https://gitee.com/mindspore/mindspore/blob/master/CONTRIBUTING.md\n-->\n\n**What type of PR is this?**\n> Uncomment only one ` /kind <>` line, hit enter to put that in a new line, and remove leading whitespaces from that line:\n>\n> /kind bug\n> /kind task\n> /kind feature\n\n\n**What does this PR do / why do we need it**:\n\n\n**Which issue(s) this PR fixes**:\n<!-- \n*Automatically closes linked issue when PR is merged.\nUsage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.\n-->\nFixes #\n\n**Special notes for your reviewers**:\n\n\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/RFC.md",
    "content": "---\nname: RFC\nabout: Use this template for the new feature or enhancement\nlabels: kind/feature or kind/enhancement\n\n---\n\n## Background\n- Describe the status of the problem you wish to solve\n- Attach the relevant issue if have\n\n## Introduction\n- Describe the general solution, design and/or pseudo-code\n\n## Trail\n| No. | Task Description | Related Issue(URL) |\n| --- | ---------------- | ------------------ |\n| 1   |                  |                    |\n| 2   |                  |                    |\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.md",
    "content": "---\nname: Bug Report\nabout: Use this template for reporting a bug\nlabels: kind/bug\n\n---\n\n<!--  Thanks for sending an issue!  Here are some tips for you:\n\nIf this is your first time, please read our contributor guidelines: https://github.com/mindspore-ai/mindspore/blob/master/CONTRIBUTING.md\n-->\n\n## Environment\n### Hardware Environment(`Ascend`/`GPU`/`CPU`): \n> Uncomment only one ` /device <>` line, hit enter to put that in a new line, and remove leading whitespaces from that line:\n>\n> `/device ascend`</br>\n> `/device gpu`</br>\n> `/device cpu`</br>\n\n### Software Environment:\n- **MindSpore version (source or binary)**:\n- **Python version (e.g., Python 3.7.5)**:\n- **OS platform and distribution (e.g., Linux Ubuntu 16.04)**:\n- **GCC/Compiler version (if compiled from source)**: \n\n## Describe the current behavior\n\n\n## Describe the expected behavior\n\n\n## Steps to reproduce the issue\n1. \n2. \n3.\n\n## Related log / screenshot\n\n\n## Special notes for this issue\n\n\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/task-tracking.md",
    "content": "---\nname: Task\nabout: Use this template for task tracking\nlabels: kind/task\n\n---\n\n## Task Description\n\n\n## Task Goal\n\n\n## Sub Task\n| No. | Task Description | Issue ID |\n| --- | ---------------- | -------- |\n| 1   |                  |          |\n| 2   |                  |          |\n\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--  Thanks for sending a pull request!  Here are some tips for you:\n\nIf this is your first time, please read our contributor guidelines: https://github.com/mindspore-ai/mindspore/blob/master/CONTRIBUTING.md\n-->\n\n**What type of PR is this?**\n> Uncomment only one ` /kind <>` line, hit enter to put that in a new line, and remove leading whitespaces from that line:\n>\n> `/kind bug`</br>\n> `/kind task`</br>\n> `/kind feature`</br>\n\n**What does this PR do / why do we need it**:\n\n\n**Which issue(s) this PR fixes**:\n<!-- \n*Automatically closes linked issue when PR is merged.\nUsage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.\n-->\nFixes #\n\n**Special notes for your reviewers**:\n\n"
  },
  {
    "path": ".gitignore",
    "content": "*.dot\n*.ir\n*.dat\n*.pyc\n*.csv\n*.gz\n*.tar\n*.zip\n*.rar\n*.ipynb\n.idea/\nbuild/\ndist/\nlocal_script/\nexample/dataset/\nexample/mnist_demo/MNIST/\nexample/mnist_demo/trained_ckpt_file/\nexample/mnist_demo/model/\nexample/cifar_demo/model/\nexample/dog_cat_demo/model/\nmindarmour.egg-info/\n*model/\n*MNIST/\n*out.data/\n*defensed_model/\n*pre_trained_model/\n*__pycache__/\n*kernel_meta\n.DS_Store\n"
  },
  {
    "path": ".jenkins/check/config/filter_cppcheck.txt",
    "content": "# MindArmour\n"
  },
  {
    "path": ".jenkins/check/config/filter_cpplint.txt",
    "content": "# MindArmour\n"
  },
  {
    "path": ".jenkins/check/config/filter_pylint.txt",
    "content": "# MindArmour\n\"mindarmour/mindarmour/privacy/diff_privacy\"                                                        \"protected-access\"\n\"mindarmour/mindarmour/fuzz_testing/fuzzing.py\"                                                     \"missing-docstring\"\n\"mindarmour/mindarmour/fuzz_testing/fuzzing.py\"                                                     \"protected-access\"\n\"mindarmour/mindarmour/fuzz_testing/fuzzing.py\"                                                     \"consider-using-enumerate\"\n\"mindarmour/setup.py\"                                                                               \"missing-docstring\"\n\"mindarmour/setup.py\"                                                                               \"invalid-name\"\n\"mindarmour/mindarmour/reliability/model_fault_injection/fault_injection.py\"                        \"protected-access\"\n\"mindarmour/setup.py\"                                                                               \"unused-argument\"\n\n# Tests\n\"mindarmour/tests/st\"                                                                               \"missing-docstring\"\n\"mindarmour/tests/ut\"                                                                               \"missing-docstring\"\n\"mindarmour/tests/st/resnet50/resnet_cifar10.py\"                                                    \"unused-argument\"\n\"mindarmour/tests/ut/python/fuzzing/test_fuzzing.py\"                                                \"invalid-name\"\n\"mindarmour/tests/ut/python/attacks/test_lbfgs.py\"                                                  \"wrong-import-position\"\n\"mindarmour/tests/ut/python/attacks/black/test_nes.py\"                                              \"wrong-import-position\"\n\"mindarmour/tests/ut/python/attacks/black/test_nes.py\"                                              \"consider-using-enumerate\"\n\"mindarmour/tests/ut/python/attacks/black/test_hsja.py\"                                             \"wrong-import-position\"\n\"mindarmour/tests/ut/python/attacks/black/test_hsja.py\"                                             \"consider-using-enumerate\"\n\"mindarmour/tests/ut/python/attacks/black/test_salt_and_pepper_attack.py\"                           \"unused-variable\"\n\"mindarmour/tests/ut/python/attacks/black/test_pointwise_attack.py\"                                 \"wrong-import-position\"\n\"mindarmour/tests/ut/python/evaluations/test_radar_metric.py\"                                       \"bad-continuation\"\n\"mindarmour/tests/ut/python/diff_privacy/test_membership_inference.py\"                              \"wrong-import-position\"\n\n# Example\n\"mindarmour/examples/ai_fuzzer/lenet5_mnist_coverage.py\"                                            \"missing-docstring\"\n\"mindarmour/examples/ai_fuzzer/lenet5_mnist_fuzzing.py\"                                             \"missing-docstring\"\n\"mindarmour/examples/ai_fuzzer/fuzz_testing_and_model_enhense.py\"                                   \"missing-docstring\"\n\"mindarmour/examples/common/dataset/data_processing.py\"                                             \"missing-docstring\"\n\"mindarmour/examples/common/networks/lenet5/lenet5_net.py\"                                          \"missing-docstring\"\n\"mindarmour/examples/common/networks/lenet5/mnist_train.py\"                                         \"missing-docstring\"\n\"mindarmour/examples/model_security/model_attacks/black_box/mnist_attack_genetic.py\"                \"missing-docstring\"\n\"mindarmour/examples/model_security/model_attacks/black_box/mnist_attack_hsja.py\"                   \"missing-docstring\"\n\"mindarmour/examples/model_security/model_attacks/black_box/mnist_attack_nes.py\"                    \"missing-docstring\"\n\"mindarmour/examples/model_security/model_attacks/black_box/mnist_attack_pointwise.py\"              \"missing-docstring\"\n\"mindarmour/examples/model_security/model_attacks/black_box/mnist_attack_pso.py\"                    \"missing-docstring\"\n\"mindarmour/examples/model_security/model_attacks/black_box/mnist_attack_salt_and_pepper.py\"        \"missing-docstring\"\n\"mindarmour/examples/model_security/model_attacks/white_box/mnist_attack_cw.py\"                     \"missing-docstring\"\n\"mindarmour/examples/model_security/model_attacks/white_box/mnist_attack_deepfool.py\"               \"missing-docstring\"\n\"mindarmour/examples/model_security/model_attacks/white_box/mnist_attack_fgsm.py\"                   \"missing-docstring\"\n\"mindarmour/examples/model_security/model_attacks/white_box/mnist_attack_jsma.py\"                   \"missing-docstring\"\n\"mindarmour/examples/model_security/model_attacks/white_box/mnist_attack_lbfgs.py\"                  \"missing-docstring\"\n\"mindarmour/examples/model_security/model_attacks/white_box/mnist_attack_mdi2fgsm.py\"               \"missing-docstring\"\n\"mindarmour/examples/model_security/model_attacks/white_box/mnist_attack_pgd.py\"                    \"missing-docstring\"\n\"mindarmour/examples/model_security/model_attacks/white_box/mnist_attack_vmifgsm.py\"                \"missing-docstring\"\n\"mindarmour/examples/model_security/model_defenses/mnist_defense_nad.py\"                            \"missing-docstring\"\n\"mindarmour/examples/model_security/model_defenses/mnist_evaluation.py\"                             \"missing-docstring\"\n\"mindarmour/examples/model_security/model_defenses/mnist_similarity_detector.py\"                    \"missing-docstring\"\n\"mindarmour/examples/community/speech_adversarial_attack/src/deepspeech2.py\"                        \"invalid-name\"\n"
  },
  {
    "path": ".jenkins/check/config/whitelizard.txt",
    "content": "# Scene1: \n#    function_name1, function_name2\n# Scene2: \n#    file_path:function_name1, function_name2\n#\nmindarmour/examples/model_security/model_defenses/mnist_evaluation.py:test_defense_evaluation\n"
  },
  {
    "path": ".jenkins/test/config/dependent_packages.yaml",
    "content": "mindspore:\n  'https://repo.mindspore.cn/mindspore/mindspore/version/202404/20240425/r2.3_20240425165819_2c3402f4e9fffe15827411e9ae7e83095ce21a32/'\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n    \"esbonio.sphinx.confDir\": \"\"\n}"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "NOTICE",
    "content": "MindSpore MindArmour\nCopyright 2019-2020 Huawei Technologies Co., Ltd"
  },
  {
    "path": "OWNERS",
    "content": "approvers:\n- pkuliuliu\n- ZhidanLiu\n- jxlang910\n- liu-siming-hw\n- yyuse\n- ZhibinHan\n\nreviewers:\n- 张澍坤\n- emmmmtang\n"
  },
  {
    "path": "README.md",
    "content": "# MindArmour\n\n<!-- TOC -->\n\n- [MindArmour](#mindarmour)\n    - [What is MindArmour](#what-is-mindarmour)\n        - [Adversarial Robustness Module](#adversarial-robustness-module)\n        - [Fuzz Testing Module](#fuzz-testing-module)\n        - [Privacy Protection and Evaluation Module](#privacy-protection-and-evaluation-module)\n            - [Differential Privacy Training Module](#differential-privacy-training-module)\n            - [Privacy Leakage Evaluation Module](#privacy-leakage-evaluation-module)\n    - [Starting](#starting)\n        - [System Environment Information Confirmation](#system-environment-information-confirmation)\n        - [Installation](#installation)\n            - [Installation by Source Code](#installation-by-source-code)\n            - [Installation by pip](#installation-by-pip)\n        - [Installation Verification](#installation-verification)\n    - [Docs](#docs)\n    - [Community](#community)\n    - [Contributing](#contributing)\n    - [Release Notes](#release-notes)\n    - [License](#license)\n\n<!-- /TOC -->\n\n[查看中文](./README_CN.md)\n\n## What is MindArmour\n\nMindArmour focus on security and privacy of artificial intelligence. It is committed to enhancing the trustworthiness of models and protecting the privacy of training and inference data. The current version (v2.0) mainly includes three modules: Adversarial Robustness Module, Fuzz Testing Module, Privacy Protection and Evaluation Module.\n\n![mindarmour_roadmap](docs/roadmap_en.png)\n\n### Adversarial Robustness Module\n\nAdversarial robustness module is designed for evaluating the robustness of the model against adversarial examples, and provides model enhancement methods to enhance the model's ability to resist the adversarial attack and improve the model's robustness.\nThis module includes four submodule: Adversarial Examples Generation, Adversarial Examples Detection, Model Defense and Evaluation.\n\nThe architecture is shown as follow：\n\n![mindarmour_architecture](docs/adversarial_robustness_en.png)\n\n### Fuzz Testing Module\n\nFuzz Testing module is a security test for AI models. We introduce neuron coverage gain as a guide to fuzz testing according to the characteristics of neural networks.\nFuzz testing is guided to generate samples in the direction of increasing neuron coverage rate, so that the input can activate more neurons and neuron values have a wider distribution range to fully test neural networks and explore different types of model output results and wrong behaviors.\n\nThe architecture is shown as follow：\n\n![fuzzer_architecture](docs/fuzzer_architecture_en.png)\n\n### Privacy Protection and Evaluation Module\n\nPrivacy Protection and Evaluation Module includes two modules: Differential Privacy Training Module and Privacy Leakage Evaluation Module.\n\n#### Differential Privacy Training Module\n\nDifferential Privacy Training Module implements the differential privacy optimizer. Currently, `SGD`, `Momentum` and `Adam` are supported. They are differential privacy optimizers based on the Gaussian mechanism.\nThis mechanism supports both non-adaptive and adaptive policy. Rényi differential privacy (RDP) and Zero-Concentrated differential privacy（ZCDP） are provided to monitor differential privacy budgets.\n\nThe architecture is shown as follow：\n\n![dp_architecture](docs/differential_privacy_architecture_en.png)\n\n#### Privacy Leakage Evaluation Module\n\nPrivacy Leakage Evaluation Module is used to assess the risk of a model revealing user privacy. The privacy data security of the deep learning model is evaluated by using membership inference method to infer whether the sample belongs to training dataset.\n\nThe architecture is shown as follow：\n\n![privacy_leakage](docs/privacy_leakage_en.png)\n\n## Starting\n\n### System Environment Information Confirmation\n\n- The hardware platform should be Ascend, GPU or CPU.\n- See our [MindSpore Installation Guide](https://www.mindspore.cn/install) to install MindSpore.  \n    The versions of MindArmour and MindSpore must be consistent.\n- All other dependencies are included in [setup.py](https://gitee.com/mindspore/mindarmour/blob/master/setup.py).\n\n### Installation\n\n### Version dependency\n\nDue the dependency between MindArmour and MindSpore, please follow the table below and install the corresponding MindSpore verision from [MindSpore download page](https://www.mindspore.cn/versions/en).\n\n| MindArmour Version | Branch                                                    | MindSpore Version |\n| ------------------ | --------------------------------------------------------- | ----------------- |\n| 2.0.0              | [r2.0](https://gitee.com/mindspore/mindarmour/tree/r2.0/) | >=1.7.0           |\n| 1.9.0              | [r1.9](https://gitee.com/mindspore/mindarmour/tree/r1.9/) | >=1.7.0           |\n| 1.8.0              | [r1.8](https://gitee.com/mindspore/mindarmour/tree/r1.8/) | >=1.7.0           |\n| 1.7.0              | [r1.7](https://gitee.com/mindspore/mindarmour/tree/r1.7/) | r1.7              |\n\n#### Installation by Source Code\n\n1. Download source code from Gitee.\n\n    ```bash\n    git clone https://gitee.com/mindspore/mindarmour.git\n    ```\n\n2. Compile and install in MindArmour directory.\n\n    ```bash\n    cd mindarmour\n    python setup.py install\n    ```\n\n#### Installation by pip\n\n```bash\npip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/{version}/MindArmour/{arch}/mindarmour-{version}-cp37-cp37m-linux_{arch}.whl --trusted-host ms-release.obs.cn-north-4.myhuaweicloud.com -i https://pypi.tuna.tsinghua.edu.cn/simple\n```\n\n> - When the network is connected, dependency items are automatically downloaded during .whl package installation. (For details about other dependency items, see [setup.py](https://gitee.com/mindspore/mindarmour/blob/master/setup.py)). In other cases, you need to manually install dependency items.\n> - `{version}` denotes the version of MindArmour. For example, when you are downloading MindArmour 1.0.1, `{version}` should be 1.0.1.\n> - `{arch}` denotes the system architecture. For example, the Linux system you are using is x86 architecture 64-bit, `{arch}` should be `x86_64`. If the system is ARM architecture 64-bit, then it should be `aarch64`.\n\n### Installation Verification\n\nSuccessfully installed, if there is no error message such as `No module named 'mindarmour'` when execute the following command:\n\n```bash\npython -c 'import mindarmour'\n```\n\n## Docs\n\nGuidance on installation, tutorials, API, see our [User Documentation](https://gitee.com/mindspore/docs).\n\n## Community\n\n[MindSpore Slack](https://join.slack.com/t/mindspore/shared_invite/enQtOTcwMTIxMDI3NjM0LTNkMWM2MzI5NjIyZWU5ZWQ5M2EwMTQ5MWNiYzMxOGM4OWFhZjI4M2E5OGI2YTg3ODU1ODE2Njg1MThiNWI3YmQ) - Ask questions and find answers.\n\n## Contributing\n\nWelcome contributions. See our [Contributor Wiki](https://gitee.com/mindspore/mindspore/blob/master/CONTRIBUTING.md) for more details.\n\n## Release Notes\n\nThe release notes, see our [RELEASE](RELEASE.md).\n\n## License\n\n[Apache License 2.0](LICENSE)\n"
  },
  {
    "path": "README_CN.md",
    "content": "# MindArmour\n\n<!-- TOC -->\n\n- [MindArmour](#mindarmour)\n    - [简介](#简介)\n        - [对抗样本鲁棒性模块](#对抗样本鲁棒性模块)\n        - [Fuzz Testing模块](#fuzz-testing模块)\n        - [隐私保护模块](#隐私保护模块)\n            - [差分隐私训练模块](#差分隐私训练模块)\n            - [隐私泄露评估模块](#隐私泄露评估模块)\n    - [开始](#开始)\n        - [确认系统环境信息](#确认系统环境信息)\n        - [安装](#安装)\n            - [源码安装](#源码安装)\n            - [pip安装](#pip安装)\n        - [验证是否成功安装](#验证是否成功安装)\n    - [文档](#文档)\n    - [社区](#社区)\n    - [贡献](#贡献)\n    - [版本](#版本)\n    - [版权](#版权)\n\n<!-- /TOC -->\n\n[View English](./README.md)\n\n## 简介\n\nMindArmour关注AI的安全和隐私问题。致力于增强模型的安全可信、保护训推数据隐私安全。当前版本（v2.0）主要包含3个模块：对抗样本鲁棒性模块、Fuzz Testing模块、隐私保护与评估模块。\n\n![mindarmour_roadmap](docs/roadmap.png)\n\n### 对抗样本鲁棒性模块\n\n对抗样本鲁棒性模块用于评估模型对于对抗样本的鲁棒性，并提供模型增强方法用于增强模型抗对抗样本攻击的能力，提升模型鲁棒性。对抗样本鲁棒性模块包含了4个子模块：对抗样本的生成、对抗样本的检测、模型防御、攻防评估。\n\n对抗样本鲁棒性模块的架构图如下：\n\n![mindarmour_architecture](docs/adversarial_robustness_cn.png)\n\n### Fuzz Testing模块\n\nFuzz Testing模块是针对AI模型的安全测试，根据神经网络的特点，引入神经元覆盖率，作为Fuzz测试的指导，引导Fuzzer朝着神经元覆盖率增加的方向生成样本，让输入能够激活更多的神经元，神经元值的分布范围更广，以充分测试神经网络，探索不同类型的模型输出结果和错误行为。\n\nFuzz Testing模块的架构图如下：\n\n![fuzzer_architecture](docs/fuzzer_architecture_cn.png)\n\n### 隐私保护模块\n\n隐私保护模块包含差分隐私训练与隐私泄露评估。\n\n#### 差分隐私训练模块\n\n差分隐私训练包括动态或者非动态的差分隐私`SGD`、`Momentum`、`Adam`优化器，噪声机制支持高斯分布噪声、拉普拉斯分布噪声，差分隐私预算监测包含ZCDP、RDP。\n\n差分隐私的架构图如下：\n\n![dp_architecture](docs/differential_privacy_architecture_cn.png)\n\n#### 隐私泄露评估模块\n\n隐私泄露评估模块用于评估模型泄露用户隐私的风险。利用成员推理方法来推测样本是否属于用户训练数据集，从而评估深度学习模型的隐私数据安全。\n\n隐私泄露评估模块框架图如下：\n\n![privacy_leakage](docs/privacy_leakage_cn.png)\n\n## 开始\n\n### 确认系统环境信息\n\n- 硬件平台为Ascend、GPU或CPU。\n- 参考[MindSpore安装指南](https://www.mindspore.cn/install)，完成MindSpore的安装。  \n    MindArmour与MindSpore的版本需保持一致。\n- 其余依赖请参见[setup.py](https://gitee.com/mindspore/mindarmour/blob/master/setup.py)。\n\n### 安装\n\n#### MindSpore版本依赖关系\n\n由于MindArmour与MindSpore有依赖关系，请按照下表所示的对应关系，在[MindSpore下载页面](https://www.mindspore.cn/versions)下载并安装对应的whl包。\n\n| MindArmour | 分支                                                      | MindSpore |\n| ---------- | --------------------------------------------------------- | --------- |\n| 2.0.0      | [r2.0](https://gitee.com/mindspore/mindarmour/tree/r2.0/) | >=1.7.0   |\n| 1.9.0      | [r1.9](https://gitee.com/mindspore/mindarmour/tree/r1.9/) | >=1.7.0   |\n| 1.8.0      | [r1.8](https://gitee.com/mindspore/mindarmour/tree/r1.8/) | >=1.7.0   |\n| 1.7.0      | [r1.7](https://gitee.com/mindspore/mindarmour/tree/r1.7/) | r1.7      |\n\n#### 源码安装\n\n1. 从Gitee下载源码。\n\n    ```bash\n    git clone https://gitee.com/mindspore/mindarmour.git\n    ```\n\n2. 在源码根目录下，执行如下命令编译并安装MindArmour。\n\n    ```bash\n    cd mindarmour\n    python setup.py install\n    ```\n\n#### pip安装\n\n```bash\npip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/{version}/MindArmour/{arch}/mindarmour-{version}-cp37-cp37m-linux_{arch}.whl --trusted-host ms-release.obs.cn-north-4.myhuaweicloud.com -i https://pypi.tuna.tsinghua.edu.cn/simple\n```\n\n> - 在联网状态下，安装whl包时会自动下载MindArmour安装包的依赖项（依赖项详情参见[setup.py](https://gitee.com/mindspore/mindarmour/blob/master/setup.py)），其余情况需自行安装。\n> - `{version}`表示MindArmour版本号，例如下载1.0.1版本MindArmour时，`{version}`应写为1.0.1。  \n> - `{arch}`表示系统架构，例如使用的Linux系统是x86架构64位时，`{arch}`应写为`x86_64`。如果系统是ARM架构64位，则写为`aarch64`。\n\n### 验证是否成功安装\n\n执行如下命令，如果没有报错`No module named 'mindarmour'`，则说明安装成功。\n\n```bash\npython -c 'import mindarmour'\n```\n\n## 文档\n\n安装指导、使用教程、API，请参考[用户文档](https://gitee.com/mindspore/docs)。\n\n## 社区\n\n社区问答：[MindSpore Slack](https://join.slack.com/t/mindspore/shared_invite/enQtOTcwMTIxMDI3NjM0LTNkMWM2MzI5NjIyZWU5ZWQ5M2EwMTQ5MWNiYzMxOGM4OWFhZjI4M2E5OGI2YTg3ODU1ODE2Njg1MThiNWI3YmQ)。\n\n## 贡献\n\n欢迎参与社区贡献，详情参考[Contributor Wiki](https://gitee.com/mindspore/mindspore/blob/master/CONTRIBUTING.md)。\n\n## 版本\n\n版本信息参考：[RELEASE](RELEASE.md)。\n\n## 版权\n\n[Apache License 2.0](LICENSE)\n"
  },
  {
    "path": "RELEASE.md",
    "content": "# MindSpore Armour Release Notes\n\n[查看中文](./RELEASE_CN.md)\n\n## MindSpore Armour 2.0.0 Release Notes\n\n### Major Features and Improvements\n\n* Add version check with MindSpore.\n* Upgrade the related software packages, Pillow>=9.3.0，scipy>=1.5.2，pytest>=5.4.3.\n\n### Contributors\n\nThanks goes to these wonderful people:\n\nZhang Shukun, Liu Zhidan, Jin Xiulang, Liu Liu, Tang Cong, Yang Yuan, Li Hongcheng.\n\nContributions of any kind are welcome!\n\n## MindArmour 1.9.0 Release Notes\n\n### API Change\n\n* Add Chinese version api of natural robustness feature.\n\n### Contributors\n\nThanks goes to these wonderful people:\n\nLiu Zhidan, Zhang Shukun, Jin Xiulang, Liu Liu, Tang Cong, Yangyuan.\n\nContributions of any kind are welcome!\n\n## MindArmour 1.8.0 Release Notes\n\n### API Change\n\n* Add Chinese version of all existed api.\n\n### Contributors\n\nThanks goes to these wonderful people:\n\nZhang Shukun, Liu Zhidan, Jin Xiulang, Liu Liu, Tang Cong, Yangyuan.\n\nContributions of any kind are welcome!\n\n## MindArmour 1.7.0 Release Notes\n\n### Major Features and Improvements\n\n#### Robustness\n\n* [STABLE] Real-World Robustness Evaluation Methods\n\n### API Change\n\n* Change value of parameter `mutate_config` in  `mindarmour.fuzz_testing.Fuzzer.fuzzing` interface. ([!333](https://gitee.com/mindspore/mindarmour/pulls/333))\n\n### Bug fixes\n\n* Update version of third-party dependence pillow from more than or equal to 6.2.0 to more than or equal to 7.2.0. ([!329](https://gitee.com/mindspore/mindarmour/pulls/329))\n\n### Contributors\n\nThanks goes to these wonderful people:\n\nLiu Zhidan, Zhang Shukun, Jin Xiulang, Liu Liu.\n\nContributions of any kind are welcome!\n\n# MindArmour 1.６.0\n\n## MindArmour 1.６.0 Release Notes\n\n### Major Features and Improvements\n\n#### Reliability\n\n* [BETA] Data Drift Detection for Image Data\n* [BETA] Model Fault Injection\n\n### Bug fixes\n\n### Contributors\n\nThanks goes to these wonderful people:\n\nWu Xiaoyu，Feng Zhenye, Liu Zhidan, Jin Xiulang, Liu Luobin, Liu Liu, Zhang Shukun\n\n# MindArmour 1.5.0\n\n## MindArmour 1.5.0 Release Notes\n\n### Major Features and Improvements\n\n#### Reliability\n\n* [BETA] Reconstruct AI Fuzz and Neuron Coverage Metrics\n\n### Bug fixes\n\n### Contributors\n\nThanks goes to these wonderful people:\n\nWu Xiaoyu，Liu Zhidan, Jin Xiulang, Liu Luobin, Liu Liu\n\n# MindArmour 1.3.0-rc1\n\n## MindArmour 1.3.0 Release Notes\n\n### Major Features and Improvements\n\n#### Privacy\n\n* [STABLE] Data Drift Detection for Time Series Data\n\n### Bug fixes\n\n* [BUGFIX] Optimization of API description.\n\n### Contributors\n\nThanks goes to these wonderful people:\n\nWu Xiaoyu，Liu Zhidan, Jin Xiulang, Liu Luobin, Liu Liu\n\n# MindArmour 1.2.0\n\n## MindArmour 1.2.0 Release Notes\n\n### Major Features and Improvements\n\n#### Privacy\n\n* [STABLE] Tailored-based privacy protection technology (Pynative)\n* [STABLE] Model Inversion. Reverse analysis technology of privacy information\n\n### API Change\n\n#### Backwards Incompatible Change\n\n##### C++ API\n\n[Modify] ...\n[Add] ...\n[Delete] ...\n\n##### Java API\n\n[Add] ...\n\n#### Deprecations\n\n##### C++ API\n\n##### Java API\n\n### Bug fixes\n\n[BUGFIX] ...\n\n### Contributors\n\nThanks goes to these wonderful people:\n\nhan.yin\n\n# MindArmour 1.1.0 Release Notes\n\n## MindArmour\n\n### Major Features and Improvements\n\n* [STABLE] Attack capability of the Object Detection models.\n    * Some white-box adversarial attacks, such as [iterative] gradient method and DeepFool now can be applied to Object Detection models.\n    * Some black-box adversarial attacks, such as PSO and Genetic Attack now can be applied to Object Detection models.\n\n### Backwards Incompatible Change\n\n#### Python API\n\n#### C++ API\n\n### Deprecations\n\n#### Python API\n\n#### C++ API\n\n### New Features\n\n#### Python API\n\n#### C++ API\n\n### Improvements\n\n#### Python API\n\n#### C++ API\n\n### Bug fixes\n\n#### Python API\n\n#### C++ API\n\n## Contributors\n\nThanks goes to these wonderful people:\n\nXiulang Jin, Zhidan Liu, Luobin Liu and Liu Liu.\n\nContributions of any kind are welcome!\n\n# Release 1.0.0\n\n## Major Features and Improvements\n\n### Differential privacy model training\n\n* Privacy leakage evaluation.\n\n    * Parameter verification enhancement.\n    * Support parallel computing.\n\n### Model robustness evaluation\n\n* Fuzzing based Adversarial Robustness testing.\n\n    * Parameter verification enhancement.\n\n### Other\n\n* Api & Directory Structure\n    * Adjusted the directory structure based on different features.\n    * Optimize the structure of examples.\n\n## Bugfixes\n\n## Contributors\n\nThanks goes to these wonderful people:\n\nLiu Liu, Xiulang Jin, Zhidan Liu and Luobin Liu.\n\nContributions of any kind are welcome!\n\n# Release 0.7.0-beta\n\n## Major Features and Improvements\n\n### Differential privacy model training\n\n* Privacy leakage evaluation.\n\n    * Using Membership inference to evaluate the effectiveness of privacy-preserving techniques for AI.\n\n### Model robustness evaluation\n\n* Fuzzing based Adversarial Robustness testing.\n\n    * Coverage-guided test set generation.\n\n## Bugfixes\n\n## Contributors\n\nThanks goes to these wonderful people:\n\nLiu Liu, Xiulang Jin, Zhidan Liu, Luobin Liu and Huanhuan Zheng.\n\nContributions of any kind are welcome!\n\n# Release 0.6.0-beta\n\n## Major Features and Improvements\n\n### Differential privacy model training\n\n* Optimizers with differential privacy\n\n    * Differential privacy model training now supports some new policies.\n\n    * Adaptive Norm policy is supported.\n\n    * Adaptive Noise policy with exponential decrease is supported.  \n\n* Differential Privacy Training Monitor\n\n    * A new monitor is supported using zCDP as its asymptotic budget estimator.\n\n## Bugfixes\n\n## Contributors\n\nThanks goes to these wonderful people:\n\nLiu Liu, Huanhuan Zheng, XiuLang jin, Zhidan liu.\n\nContributions of any kind are welcome.\n\n# Release 0.5.0-beta\n\n## Major Features and Improvements\n\n### Differential privacy model training\n\n* Optimizers with differential privacy\n\n    * Differential privacy model training now supports both Pynative mode and graph mode.\n\n    * Graph mode is recommended for its performance.\n\n## Bugfixes\n\n## Contributors\n\nThanks goes to these wonderful people:\n\nLiu Liu, Huanhuan Zheng, Xiulang Jin, Zhidan Liu.\n\nContributions of any kind are welcome!\n\n# Release 0.3.0-alpha\n\n## Major Features and Improvements\n\n### Differential Privacy Model Training\n\nDifferential Privacy is coming! By using Differential-Privacy-Optimizers, one can still train a model as usual, while the trained model preserved the privacy of training dataset, satisfying the definition of\ndifferential privacy with proper budget.\n\n* Optimizers with Differential Privacy([PR23](https://gitee.com/mindspore/mindarmour/pulls/23), [PR24](https://gitee.com/mindspore/mindarmour/pulls/24))\n\n    * Some common optimizers now have a differential privacy version (SGD/Adam). We are adding more.\n    * Automatically and adaptively add Gaussian Noise during training to achieve Differential Privacy.\n    * Automatically stop training when Differential Privacy Budget exceeds.\n\n* Differential Privacy Monitor([PR22](https://gitee.com/mindspore/mindarmour/pulls/22))\n\n    * Calculate overall budget consumed during training, indicating the ultimate protect effect.\n\n## Bug fixes\n\n## Contributors\n\nThanks goes to these wonderful people:\nLiu Liu, Huanhuan Zheng, Zhidan Liu, Xiulang Jin\nContributions of any kind are welcome!\n\n# Release 0.2.0-alpha\n\n## Major Features and Improvements\n\n* Add a white-box attack method: M-DI2-FGSM([PR14](https://gitee.com/mindspore/mindarmour/pulls/14)).\n* Add three neuron coverage metrics: KMNCov, NBCov, SNACov([PR12](https://gitee.com/mindspore/mindarmour/pulls/12)).\n* Add a coverage-guided fuzzing test framework for deep neural networks([PR13](https://gitee.com/mindspore/mindarmour/pulls/13)).\n* Update the MNIST Lenet5 examples.\n* Remove some duplicate code.\n\n## Bug fixes\n\n## Contributors\n\nThanks goes to these wonderful people:\nLiu Liu, Huanhuan Zheng, Zhidan Liu, Xiulang Jin\nContributions of any kind are welcome!\n\n# Release 0.1.0-alpha\n\nInitial release of MindArmour.\n\n## Major Features\n\n* Support adversarial attack and defense on the platform of MindSpore.\n* Include 13 white-box and 7 black-box attack methods.\n* Provide 5 detection algorithms to detect attacking in multiple way.\n* Provide adversarial training to enhance model security.\n* Provide 6 evaluation metrics for attack methods and 9 evaluation metrics for defense methods.\n"
  },
  {
    "path": "RELEASE_CN.md",
    "content": "# MindSpore Armour Release Notes\n\n[View English](./RELEASE.md)\n\n## MindSpore Armour 2.1.0 Release Notes\n\n### 主要特性及增强\n\n* 增加与MindSpore的版本校验关系。\n* 升级相关软件包版本，setuptools >= 78.1.1，numpy >= 1.20.0,<2.0.0。\n\n### 贡献者\n\n感谢以下人员做出的贡献：\n\nYang Yuan, Han Zhibin, Liu Siming.\n\n欢迎以任何形式对项目提供贡献！\n\n## MindSpore Armour 2.0.0 Release Notes\n\n### 主要特性及增强\n\n* 增加与MindSpore的版本校验关系。\n* 升级相关软件包版本，Pillow>=9.3.0，scipy>=1.5.2，pytest>=5.4.3。\n\n### 贡献者\n\n感谢以下人员做出的贡献：\n\nZhang Shukun, Liu Zhidan, Jin Xiulang, Liu Liu, Tang Cong, Yang Yuan, Li Hongcheng.\n\n欢迎以任何形式对项目提供贡献！\n\n## MindArmour 1.9.0 Release Notes\n\n### API Change\n\n* 增加自然鲁棒性特性的api中文版本\n\n### 贡献\n\n感谢以下人员做出的贡献：\n\nLiu Zhidan, Zhang Shukun, Jin Xiulang, Liu Liu, Tang Cong, Yangyuan.\n\n欢迎以任何形式对项目提供贡献！\n\n## MindArmour 1.8.0 Release Notes\n\n### API Change\n\n* 增加所有特性的api中文版本\n\n### 贡献\n\n感谢以下人员做出的贡献：\n\nZhang Shukun, Liu Zhidan, Jin Xiulang, Liu Liu, Tang Cong, Yangyuan.\n\n欢迎以任何形式对项目提供贡献！\n\n## MindArmour 1.7.0 Release Notes\n\n### 主要特性和增强\n\n#### 鲁棒性\n\n* [STABLE] 自然扰动评估方法\n\n### API Change\n\n* 接口`mindarmour.fuzz_testing.Fuzzer.fuzzing`的参数`mutate_config`的取值范围变化。 ([!333](https://gitee.com/mindspore/mindarmour/pulls/333))\n\n### Bug修复\n\n* 更新第三方依赖pillow的版本从大于等于6.2.0更新为大于等于7.2.0. ([!329](https://gitee.com/mindspore/mindarmour/pulls/329))\n\n### 贡献\n\n感谢以下人员做出的贡献：\n\nLiu Zhidan, Zhang Shukun, Jin Xiulang, Liu Liu.\n\n欢迎以任何形式对项目提供贡献！\n"
  },
  {
    "path": "docs/README.md",
    "content": "# MindArmour Documentation\n\nThe MindArmour documentation is in the [MindSpore Docs](https://gitee.com/mindspore/docs) repository.\n"
  },
  {
    "path": "docs/api/api_python/mindarmour.adv_robustness.attacks.rst",
    "content": "mindarmour.adv_robustness.attacks\n=================================\n\n本模块包括经典的黑盒和白盒攻击算法，以制作对抗样本。\n\n.. py:class:: mindarmour.adv_robustness.attacks.FastGradientMethod(network, eps=0.07, alpha=None, bounds=(0.0, 1.0), norm_level=2, is_targeted=False, loss_fn=None)\n\n    基于梯度计算的单步攻击，扰动的范数包括 ``'L1'``、``'L2'`` 和 ``'Linf'``。\n\n    参考文献：`I. J. Goodfellow, J. Shlens, and C. Szegedy, \"Explaining and harnessing adversarial examples,\" in ICLR, 2015. <https://arxiv.org/abs/1412.6572>`_。\n\n    参数：\n        - **network** (Cell) - 目标模型。\n        - **eps** (float) - 攻击产生的单步对抗扰动占数据范围的比例。默认值：``0.07``。\n        - **alpha** (Union[float, None]) - 单步随机扰动与数据范围的比例。默认值：``None``。\n        - **bounds** (tuple) - 数据的上下界，表示数据范围。以(数据最小值, 数据最大值)的形式出现。默认值：``(0.0, 1.0)``。\n        - **norm_level** (Union[int, str, numpy.inf]) - 范数类型。\n          可取值：``numpy.inf``、``1``、``2``、``'1'``、``'2'``、``'l1'``、``'l2'``、``'np.inf'``、``'inf'``、``'linf'``。默认值：``2``。\n        - **is_targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。默认值：``False``。\n        - **loss_fn** (Union[loss, None]) - 用于优化的损失函数。如果为 ``None``，则输入网络已配备损失函数。默认值：``None``。\n\n.. py:class:: mindarmour.adv_robustness.attacks.RandomFastGradientMethod(network, eps=0.07, alpha=0.035, bounds=(0.0, 1.0), norm_level=2, is_targeted=False, loss_fn=None)\n\n    使用随机扰动的快速梯度法（Fast Gradient Method）。\n    基于梯度计算的单步攻击，其对抗性噪声是根据输入的梯度生成的，然后加入随机扰动，从而生成对抗样本。\n\n    参考文献：`Florian Tramer, Alexey Kurakin, Nicolas Papernot, \"Ensemble adversarial training: Attacks and defenses\" in ICLR, 2018 <https://arxiv.org/abs/1705.07204>`_。\n\n    参数：\n        - **network** (Cell) - 目标模型。\n        - **eps** (float) - 攻击产生的单步对抗扰动占数据范围的比例。默认值：``0.07``。\n        - **alpha** (float) - 单步随机扰动与数据范围的比例。默认值：``0.035``。\n        - **bounds** (tuple) - 数据的上下界，表示数据范围。以(数据最小值，数据最大值)的形式出现。默认值：``(0.0, 1.0)``。\n        - **norm_level** (Union[int, str, numpy.inf]) - 范数类型。\n          可取值：``numpy.inf``、``1``、``2``、``'1'``、``'2'``、``'l1'``、``'l2'``、``'np.inf'``、``'inf'``、``'linf'``。默认值：``2``。\n        - **is_targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。默认值：``False``。\n        - **loss_fn** (Union[loss, None]) - 用于优化的损失函数。如果为 ``None``，则输入网络已配备损失函数。默认值：``None``。\n\n    异常：\n        - **ValueError** - `eps` 小于 `alpha` 。\n\n.. py:class:: mindarmour.adv_robustness.attacks.FastGradientSignMethod(network, eps=0.07, alpha=None, bounds=(0.0, 1.0), is_targeted=False, loss_fn=None)\n\n    快速梯度下降法（Fast Gradient Sign Method）攻击计算输入数据的梯度，然后使用梯度的符号创建对抗性噪声。\n\n    参考文献：`Ian J. Goodfellow, J. Shlens, and C. Szegedy, \"Explaining and harnessing adversarial examples,\" in ICLR, 2015 <https://arxiv.org/abs/1412.6572>`_。\n\n    参数：\n        - **network** (Cell) - 目标模型。\n        - **eps** (float) - 攻击产生的单步对抗扰动占数据范围的比例。默认值：``0.07``。\n        - **alpha** (Union[float, None]) - 单步随机扰动与数据范围的比例。默认值：``None``。\n        - **bounds** (tuple) - 数据的上下界，表示数据范围。以(数据最小值，数据最大值)的形式出现。默认值：``(0.0, 1.0)``。\n        - **is_targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。默认值：``False``。\n        - **loss_fn** (Union[Loss, None]) - 用于优化的损失函数。如果为 ``None``，则输入网络已配备损失函数。默认值：``None``。\n\n.. py:class:: mindarmour.adv_robustness.attacks.RandomFastGradientSignMethod(network, eps=0.07, alpha=0.035, bounds=(0.0, 1.0), is_targeted=False, loss_fn=None)\n\n    快速梯度下降法（Fast Gradient Sign Method）使用随机扰动。\n    随机快速梯度符号法（Random Fast Gradient Sign Method）攻击计算输入数据的梯度，然后使用带有随机扰动的梯度符号来创建对抗性噪声。\n\n    参考文献：`F. Tramer, et al., \"Ensemble adversarial training: Attacks and defenses,\" in ICLR, 2018 <https://arxiv.org/abs/1705.07204>`_。\n\n    参数：\n        - **network** (Cell) - 目标模型。\n        - **eps** (float) - 攻击产生的单步对抗扰动占数据范围的比例。默认值：``0.07``。\n        - **alpha** (float) - 单步随机扰动与数据范围的比例。默认值：``0.005``。\n        - **bounds** (tuple) - 数据的上下界，表示数据范围。以(数据最小值，数据最大值)的形式出现。默认值：``(0.0, 1.0)``。\n        - **is_targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。默认值：``False``。\n        - **loss_fn** (Union[Loss, None]) - 用于优化的损失函数。如果为 ``None``，则输入网络已配备损失函数。默认值：``None``。\n\n    异常：\n        - **ValueError** - `eps` 小于 `alpha` 。\n\n.. py:class:: mindarmour.adv_robustness.attacks.LeastLikelyClassMethod(network, eps=0.07, alpha=None, bounds=(0.0, 1.0), loss_fn=None)\n\n    单步最不可能类方法（Single Step Least-Likely Class Method）是FGSM的变体，它以最不可能类为目标，以生成对抗样本。\n\n    参考文献：`F. Tramer, et al., \"Ensemble adversarial training: Attacks and defenses,\" in ICLR, 2018 <https://arxiv.org/abs/1705.07204>`_。\n\n    参数：\n        - **network** (Cell) - 目标模型。\n        - **eps** (float) - 攻击产生的单步对抗扰动占数据范围的比例。默认值：``0.07``。\n        - **alpha** (Union[float, None]) - 单步随机扰动与数据范围的比例。默认值：``None``。\n        - **bounds** (tuple) - 数据的上下界，表示数据范围。以(数据最小值，数据最大值)的形式出现。默认值：``(0.0, 1.0)``。\n        - **loss_fn** (Union[Loss, None]) - 用于优化的损失函数。如果为 ``None``，则输入网络已配备损失函数。默认值：``None``。\n\n.. py:class:: mindarmour.adv_robustness.attacks.RandomLeastLikelyClassMethod(network, eps=0.07, alpha=0.035, bounds=(0.0, 1.0), loss_fn=None)\n\n    随机最不可能类攻击方法：以置信度最小类别对应的梯度加一个随机扰动为攻击方向。\n\n    具有随机扰动的单步最不可能类方法（Single Step Least-Likely Class Method）是随机FGSM的变体，它以最不可能类为目标，以生成对抗样本。\n\n    参考文献：`F. Tramer, et al., \"Ensemble adversarial training: Attacks and defenses,\" in ICLR, 2018 <https://arxiv.org/abs/1705.07204>`_。\n\n    参数：\n        - **network** (Cell) - 目标模型。\n        - **eps** (float) - 攻击产生的单步对抗扰动占数据范围的比例。默认值：``0.07``。\n        - **alpha** (float) - 单步随机扰动与数据范围的比例。默认值：``0.005``。\n        - **bounds** (tuple) - 数据的上下界，表示数据范围。以(数据最小值，数据最大值)的形式出现。默认值：``(0.0, 1.0)``。\n        - **loss_fn** (Union[Loss, None]) - 用于优化的损失函数。如果为 ``None``，则输入网络已配备损失函数。默认值：``None``。\n\n    异常：\n        - **ValueError** - `eps` 小于 `alpha` 。\n\n.. py:class:: mindarmour.adv_robustness.attacks.IterativeGradientMethod(network, eps=0.3, eps_iter=0.1, bounds=(0.0, 1.0), nb_iter=5, loss_fn=None)\n\n    所有基于迭代梯度的攻击的抽象基类。\n\n    参数：\n        - **network** (Cell) - 目标模型。\n        - **eps** (float) - 攻击产生的对抗性扰动占数据范围的比例。默认值：``0.3``。\n        - **eps_iter** (float) - 攻击产生的单步对抗扰动占数据范围的比例。默认值：``0.1``。\n        - **bounds** (tuple) - 数据的上下界，表示数据范围。以(数据最小值，数据最大值)的形式出现。默认值：``(0.0, 1.0)``。\n        - **nb_iter** (int) - 迭代次数。默认值：``5``。\n        - **loss_fn** (Union[Loss, None]) - 用于优化的损失函数。如果为 ``None``，则输入网络已配备损失函数。默认值：``None``。\n\n    .. py:method:: generate(inputs, labels)\n        :abstractmethod:\n\n        根据输入样本和原始/目标标签生成对抗样本。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, tuple]) - 良性输入样本，用于创建对抗样本。\n            - **labels** (Union[numpy.ndarray, tuple]) - 原始/目标标签。若每个输入有多个标签，将它包装在元组中。\n\n        异常：\n            - **NotImplementedError** - 此函数在迭代梯度方法中不可用。\n\n.. py:class:: mindarmour.adv_robustness.attacks.BasicIterativeMethod(network, eps=0.3, eps_iter=0.1, bounds=(0.0, 1.0), is_targeted=False, nb_iter=5, loss_fn=None)\n\n    基本迭代法（Basic Iterative Method）攻击，一种生成对抗示例的迭代FGSM方法。\n\n    参考文献：`A. Kurakin, I. Goodfellow, and S. Bengio, \"Adversarial examples in the physical world,\" in ICLR, 2017 <https://arxiv.org/abs/1607.02533>`_。\n\n    参数：\n        - **network** (Cell) - 目标模型。\n        - **eps** (float) - 攻击产生的对抗性扰动占数据范围的比例。默认值：``0.3``。\n        - **eps_iter** (float) - 攻击产生的单步对抗扰动占数据范围的比例。默认值：``0.1``。\n        - **bounds** (tuple) - 数据的上下界，表示数据范围。以(数据最小值，数据最大值)的形式出现。默认值：``(0.0, 1.0)``。\n        - **is_targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。默认值：``False``。\n        - **nb_iter** (int) - 迭代次数。默认值：``5``。\n        - **loss_fn** (Union[Loss, None]) - 用于优化的损失函数。如果为 ``None``，则输入网络已配备损失函数。默认值：``None``。\n\n    .. py:method:: generate(inputs, labels)    \n\n        使用迭代FGSM方法生成对抗样本。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, tuple]) - 良性输入样本，用于创建对抗样本。\n            - **labels** (Union[numpy.ndarray, tuple]) - 原始/目标标签。若每个输入有多个标签，将它包装在元组中。\n\n        返回：\n            - **numpy.ndarray** - 生成的对抗样本。\n\n.. py:class:: mindarmour.adv_robustness.attacks.MomentumIterativeMethod(network, eps=0.3, eps_iter=0.1, bounds=(0.0, 1.0), is_targeted=False, nb_iter=5, decay_factor=1.0, norm_level='inf', loss_fn=None)\n\n    动量迭代法（Momentum Iterative Method）攻击，通过在迭代中积累损失函数的梯度方向上的速度矢量，加速梯度下降算法，如FGSM、FGM和LLCM，从而生成对抗样本。\n\n    参考文献：`Y. Dong, et al., \"Boosting adversarial attacks with momentum,\" arXiv:1710.06081, 2017 <https://arxiv.org/abs/1710.06081>`_。\n\n    参数：\n        - **network** (Cell) - 目标模型。\n        - **eps** (float) - 攻击产生的对抗性扰动占数据范围的比例。默认值：``0.3``。\n        - **eps_iter** (float) - 攻击产生的单步对抗扰动占数据范围的比例。默认值：``0.1``。\n        - **bounds** (tuple) - 数据的上下界，表示数据范围。\n          以(数据最小值，数据最大值)的形式出现。默认值：``(0.0, 1.0)``。\n        - **is_targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。默认值：``False``。\n        - **nb_iter** (int) - 迭代次数。默认值：``5``。\n        - **decay_factor** (float) - 迭代中的衰变因子。默认值：``1.0``。\n        - **norm_level** (Union[int, str, numpy.inf]) - 范数类型。\n          可取值：``numpy.inf``、``1``、``2``、``'1'``、``'2'``、``'l1'``、``'l2'``、``'np.inf'``、``'inf'``、``'linf'``。默认值：``numpy.inf``。\n        - **loss_fn** (Union[Loss, None]) - 用于优化的损失函数。如果为 ``None``，则输入网络已配备损失函数。默认值：``None``。\n\n    .. py:method:: generate(inputs, labels)    \n\n        根据输入数据和原始/目标标签生成对抗样本。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, tuple]) - 良性输入样本，用于创建对抗样本。\n            - **labels** (Union[numpy.ndarray, tuple]) - 原始/目标标签。若每个输入有多个标签，将它包装在元组中。\n\n        返回：\n            - **numpy.ndarray** - 生成的对抗样本。\n\n.. py:class:: mindarmour.adv_robustness.attacks.ProjectedGradientDescent(network, eps=0.3, eps_iter=0.1, bounds=(0.0, 1.0), is_targeted=False, nb_iter=5, norm_level='inf', loss_fn=None)\n\n    投影梯度下降（Projected Gradient Descent）攻击是基本迭代法的变体，在这种方法中，每次迭代之后，扰动被投影在指定半径的p范数球上（除了剪切对抗样本的值，使其位于允许的数据范围内）。这是Madry等人提出的用于对抗性训练的攻击。\n\n    参考文献：`A. Madry, et al., \"Towards deep learning models resistant to adversarial attacks,\" in ICLR, 2018 <https://arxiv.org/abs/1706.06083>`_。\n\n    参数：\n        - **network** (Cell) - 目标模型。\n        - **eps** (float) - 攻击产生的对抗性扰动占数据范围的比例。默认值：``0.3``。\n        - **eps_iter** (float) - 攻击产生的单步对抗扰动占数据范围的比例。默认值：``0.1``。\n        - **bounds** (tuple) - 数据的上下界，表示数据范围。以(数据最小值，数据最大值)的形式出现。默认值：``(0.0, 1.0)``。\n        - **is_targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。默认值：``False``。\n        - **nb_iter** (int) - 迭代次数。默认值：``5``。\n        - **norm_level** (Union[int, str, numpy.inf]) - 范数类型。\n          可取值：``numpy.inf``、``1``、``2``、``'1'``、``'2'``、``'l1'``、``'l2'``、``'np.inf'``、``'inf'``、``'linf'``。默认值：``'numpy.inf'``。\n        - **loss_fn** (Union[Loss, None]) - 用于优化的损失函数。如果为 ``None``，则输入网络已配备损失函数。默认值：``None``。\n\n    .. py:method:: generate(inputs, labels)\n\n        基于BIM方法迭代生成对抗样本。通过带有参数norm_level的投影方法归一化扰动。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, tuple]) - 良性输入样本，用于创建对抗样本。\n            - **labels** (Union[numpy.ndarray, tuple]) - 原始/目标标签。若每个输入有多个标签，将它包装在元组中。\n\n        返回：\n            - **numpy.ndarray** - 生成的对抗样本。\n\n.. py:class:: mindarmour.adv_robustness.attacks.AutoProjectedGradientDescent(network, eps=8 / 255, eps_iter=0.1, bounds=(0.0, 1.0), is_targeted=False, nb_iter=10, norm_level='inf', loss_fn=None, eot_iter=1, thr_decr=0.75)\n\n    自动投影梯度下降（AutoProjected Gradient Descent）攻击是基本迭代法的变体，也是PGD方法的升级版，在这种方法中，每次迭代之后，扰动被投影在指定半径的p范数球上（除了剪切对抗样本的值，使其位于允许的数据范围内），并引入了自适应步长和动量来加速收敛并提高攻击性能。这是Croce等人提出的用于对抗性训练的攻击。\n\n    参考文献：`Croce and Hein, \"Reliable evalua\u0002tion of adversarial robustness with an ensemble of \\\n    diverse parameter-free attacks\" in ICML, 2020 <https://arxiv.org/abs/2003.01690>`_。\n\n    参数：\n        - **network** (Cell) - 目标模型。\n        - **eps** (float) - 攻击产生的对抗性扰动占数据范围的比例。默认值：``8 / 255``。\n        - **eps_iter** (float) - 攻击产生的单步对抗扰动占数据范围的比例。默认值：``0.1``。\n        - **bounds** (tuple) - 数据的上下界，表示数据范围。以(数据最小值，数据最大值)的形式出现。默认值：``(0.0, 1.0)``。\n        - **is_targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。默认值：``False``。\n        - **nb_iter** (int) - 迭代次数。默认值：``10``。\n        - **norm_level** (Union[int, str, numpy.inf]) - 范数类型。可取值： ``inf`` 、 ``1`` 、 ``2`` 。默认值： ``inf`` 。\n        - **loss_fn** (Union[Loss, None]) - 用于优化的损失函数。如果为 ``None``，则输入网络已配备损失函数。默认值：``None``。\n        - **eot_iter** (int) - EOT的迭代次数。默认值: ``1``。\n        - **thr_decr** (float) - 步长更新的参数。默认值: ``0.75``。\n\n    .. py:method:: generate(inputs, labels)\n\n        根据输入样本和原始标签生成对抗样本。通过带有参数 `norm_level` 的投影方法归一化扰动。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, tuple]) - 良性输入样本，用于创建对抗样本。\n            - **labels** (Union[numpy.ndarray, tuple]) - 原始/目标标签。若每个输入有多个标签，将它包装在元组中。\n\n        返回：\n            numpy.ndarray，生成的对抗样本。\n\n.. py:class:: mindarmour.adv_robustness.attacks.DiverseInputIterativeMethod(network, eps=0.3, bounds=(0.0, 1.0), is_targeted=False, prob=0.5, loss_fn=None)\n\n    多样性输入迭代法（Diverse Input Iterative Method）攻击遵循基本迭代法，并在每次迭代时对输入数据应用随机转换。对输入数据的这种转换可以提高对抗样本的可转移性。\n\n    参考文献：`Xie, Cihang and Zhang, et al., \"Improving Transferability of Adversarial Examples With Input Diversity,\" in CVPR, 2019 <https://arxiv.org/abs/1803.06978>`_。\n\n    参数：\n        - **network** (Cell) - 目标模型。\n        - **eps** (float) - 攻击产生的对抗性扰动占数据范围的比例。默认值：``0.3``。\n        - **bounds** (tuple) - 数据的上下界，表示数据范围。以(数据最小值，数据最大值)的形式出现。默认值：``(0.0, 1.0)``。\n        - **is_targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。默认值：``False``。\n        - **prob** (float) - 对输入样本的转换概率。默认值：``0.5``。\n        - **loss_fn** (Union[Loss, None]) - 用于优化的损失函数。如果为 ``None``，则输入网络已配备损失函数。默认值：``None``。\n\n.. py:class:: mindarmour.adv_robustness.attacks.MomentumDiverseInputIterativeMethod(network, eps=0.3, bounds=(0.0, 1.0), is_targeted=False, norm_level='l1', prob=0.5, loss_fn=None)\n\n    动量多样性输入迭代法（Momentum Diverse Input Iterative Method）攻击是一种动量迭代法，在每次迭代时对输入数据应用随机变换。对输入数据的这种转换可以提高对抗样本的可转移性。\n\n    参考文献：`Xie, Cihang and Zhang, et al., \"Improving Transferability of Adversarial Examples With Input Diversity,\" in CVPR, 2019 <https://arxiv.org/abs/1803.06978>`_。\n\n    参数：\n        - **network** (Cell) - 目标模型。\n        - **eps** (float) - 攻击产生的对抗性扰动占数据范围的比例。默认值：``0.3``。\n        - **bounds** (tuple) - 数据的上下界，表示数据范围。以(数据最小值，数据最大值)的形式出现。默认值：``(0.0, 1.0)``。\n        - **is_targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。默认值：``False``。\n        - **norm_level** (Union[int, str, numpy.inf]) - 范数类型。\n          可取值：``numpy.inf``、``1``、``2``、``'1'``、``'2'``、``'l1'``、``'l2'``、``'np.inf'``、``'inf'``、``'linf'``。默认值：``'l1'``。\n        - **prob** (float) - 对输入样本的转换概率。默认值：``0.5``。\n        - **loss_fn** (Union[Loss, None]) - 用于优化的损失函数。如果为 ``None``，则输入网络已配备损失函数。默认值：``None``。\n\n.. py:class:: mindarmour.adv_robustness.attacks.DeepFool(network, num_classes, model_type='classification', reserve_ratio=0.3, max_iters=50, overshoot=0.02, norm_level=2, bounds=None, sparse=True)\n\n    DeepFool是一种无目标的迭代攻击，通过将良性样本移动到最近的分类边界并跨越边界来实现。\n\n    参考文献：`DeepFool: a simple and accurate method to fool deep neural networks <https://arxiv.org/abs/1511.04599>`_。\n\n    参数：\n        - **network** (Cell) - 目标模型。\n        - **num_classes** (int) - 模型输出的标签数，应大于零。\n        - **model_type** (str) - 目标模型的类型。现在支持 ``'classification'`` 和 ``'detection'``。默认值：``'classification'``。\n        - **reserve_ratio** (Union[int, float]) - 攻击后可检测到的对象百分比，仅当model_type为 ``'detection'`` 时有效。保留比率应在(0, 1)的范围内。默认值：``0.3``。\n        - **max_iters** (int) - 最大迭代次数，应大于零。默认值：``50``。\n        - **overshoot** (float) - 过冲参数。默认值：``0.02``。\n        - **norm_level** (Union[int, str, numpy.inf]) - 矢量范数类型。可取值：``numpy.inf`` 或 ``2``。默认值：``2``。\n        - **bounds** (Union[tuple, list]) - 数据范围的上下界。以(数据最小值，数据最大值)的形式出现。默认值：``None``。\n        - **sparse** (bool) - 如果为 ``True``，则输入标签为稀疏编码。如果为 ``False``，则输入标签为one-hot编码。默认值：``True``。\n\n    .. py:method:: generate(inputs, labels)    \n\n        根据输入样本和原始标签生成对抗样本。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, tuple]) - 输入样本。\n\n              - 如果 `model_type` = ``'classification'``，则输入的格式应为numpy.ndarray。输入的格式可以是(input1, input2, ...)。\n              - 如果 `model_type` = ``'detection'``，则只能是一个数组。\n\n            - **labels** (Union[numpy.ndarray, tuple]) - 目标标签或ground-truth标签。\n\n              - 如果 `model_type` = ``'classification'``，标签的格式应为numpy.ndarray。\n              - 如果 `model_type` = ``'detection'``，标签的格式应为(gt_boxes, gt_labels)。\n\n        返回：\n            - **numpy.ndarray** - 对抗样本。\n\n        异常：\n            - **NotImplementedError** - `norm_level` 不为 ``2``、``numpy.inf``、``'2'`` 或 ``'inf'``。\n\n.. py:class:: mindarmour.adv_robustness.attacks.CarliniWagnerL2Attack(network, num_classes, box_min=0.0, box_max=1.0, bin_search_steps=5, max_iterations=1000, confidence=0, learning_rate=5e-3, initial_const=1e-2, abort_early_check_ratio=5e-2, targeted=False, fast=True, abort_early=True, sparse=True)\n\n    使用L2范数的Carlini & Wagner攻击通过分别利用两个损失生成对抗样本：“对抗损失”可使生成的示例实际上是对抗性的，“距离损失”可以控制对抗样本的质量。\n\n    参考文献：`Nicholas Carlini, David Wagner: \"Towards Evaluating the Robustness of Neural Networks\" <https://arxiv.org/abs/1608.04644>`_。\n\n    参数：\n        - **network** (Cell) - 目标模型。\n        - **num_classes** (int) - 模型输出的标签数，应大于零。\n        - **box_min** (float) - 目标模型输入的下界。默认值：``0``。\n        - **box_max** (float) - 目标模型输入的上界。默认值：``1.0``。\n        - **bin_search_steps** (int) - 用于查找距离和置信度之间的最优trade-off常数的二分查找步数。默认值：``5``。\n        - **max_iterations** (int) - 最大迭代次数，应大于零。默认值：``1000``。\n        - **confidence** (float) - 对抗样本输出的置信度。默认值：``0``。\n        - **learning_rate** (float) - 攻击算法的学习率。默认值：``5e-3``。\n        - **initial_const** (float) - 用于平衡扰动范数和置信度差异的初始trade-off常数。默认值：``1e-2``。\n        - **abort_early_check_ratio** (float) - 检查所有迭代中所有比率的损失进度。默认值：``5e-2``。\n        - **targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。默认值：``False``。\n        - **fast** (bool) - 如果为 ``True``，则返回第一个找到的对抗样本。如果为 ``False``，则返回扰动较小的对抗样本。默认值：``True``。\n        - **abort_early** (bool) - 是否提前终止。\n\n          - 如果为 ``True``，则当损失在一段时间内没有减少，Adam将被中止。\n          - 如果为 ``False``，Adam将继续工作，直到到达最大迭代。默认值：``True``。\n\n        - **sparse** (bool) - 如果为 ``True``，则输入标签为稀疏编码。如果为 ``False``，则输入标签为one-hot编码。默认值：``True``。\n\n    .. py:method:: generate(inputs, labels)\n\n        根据输入数据和目标标签生成对抗样本。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 输入样本。\n            - **labels** (numpy.ndarray) - 输入样本的真值标签或目标标签。\n\n        返回：\n            - **numpy.ndarray** - 生成的对抗样本。\n\n.. py:class:: mindarmour.adv_robustness.attacks.JSMAAttack(network, num_classes, box_min=0.0, box_max=1.0, theta=1.0, max_iteration=1000, max_count=3, increase=True, sparse=True)\n\n    基于Jacobian的显著图攻击（Jacobian-based Saliency Map Attack）是一种基于输入特征显著图的有目标的迭代攻击。它使用每个类标签相对于输入的每个组件的损失梯度。然后，使用显著图来选择产生最大误差的维度。\n\n    参考文献：`The limitations of deep learning in adversarial settings <https://arxiv.org/abs/1511.07528>`_。\n\n    参数：\n        - **network** (Cell) - 目标模型。\n        - **num_classes** (int) - 模型输出的标签数，应大于零。\n        - **box_min** (float) - 目标模型输入的下界。默认值：``0``。\n        - **box_max** (float) - 目标模型输入的上界。默认值：``1.0``。\n        - **theta** (float) - 一个像素的变化率（相对于输入数据范围）。默认值：``1.0``。\n        - **max_iteration** (int) - 迭代的最大轮次。默认值：``1000``。\n        - **max_count** (int) - 每个像素的最大更改次数。默认值：``3``。\n        - **increase** (bool) - 如果为 ``True``，则增加扰动。如果为 ``False``，则减少扰动。默认值：``True``。\n        - **sparse** (bool) - 如果为 ``True``，则输入标签为稀疏编码。如果为 ``False``，则输入标签为one-hot编码。默认值：``True``。\n\n    .. py:method:: generate(inputs, labels) \n\n        批量生成对抗样本。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 输入样本。\n            - **labels** (numpy.ndarray) - 目标标签。\n\n        返回：\n            - **numpy.ndarray** - 对抗样本。\n\n.. py:class:: mindarmour.adv_robustness.attacks.LBFGS(network, eps=1e-5, bounds=(0.0, 1.0), is_targeted=True, nb_iter=150, search_iters=30, loss_fn=None, sparse=False)\n\n    L-BFGS-B攻击使用有限内存BFGS优化算法来最小化输入与对抗样本之间的距离。\n\n    参考文献：`Pedro Tabacof, Eduardo Valle. \"Exploring the Space of Adversarial Images\" <https://arxiv.org/abs/1510.05328>`_。\n\n    参数：\n        - **network** (Cell) - 被攻击模型的网络。\n        - **eps** (float) - 攻击步长。默认值：``1e-5``。\n        - **bounds** (tuple) - 数据的上下界。默认值：``(0.0, 1.0)``。\n        - **is_targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。默认值：``True``。\n        - **nb_iter** (int) - lbfgs优化器的迭代次数，应大于零。默认值：``150``。\n        - **search_iters** (int) - 步长的变更数，应大于零。默认值：``30``。\n        - **loss_fn** (Functions) - 替代模型的损失函数。默认值：``None``。\n        - **sparse** (bool) - 如果为 ``True``，则输入标签为稀疏编码。如果为 ``False``，则输入标签为one-hot编码。默认值：``False``。\n\n    .. py:method:: generate(inputs, labels)    \n\n        根据输入数据和目标标签生成对抗样本。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 良性输入样本，用于创建对抗样本。\n            - **labels** (numpy.ndarray) - 原始/目标标签。\n\n        返回：\n            - **numpy.ndarray** - 生成的对抗样本。\n\n.. py:class:: mindarmour.adv_robustness.attacks.GeneticAttack(model, model_type='classification', targeted=True, reserve_ratio=0.3, sparse=True, pop_size=6, mutation_rate=0.005, per_bounds=0.15, max_steps=1000, step_size=0.20, temp=0.3, bounds=(0, 1.0), adaptive=False, c=0.1)\n\n    遗传攻击（Genetic Attack）为基于遗传算法的黑盒攻击，属于差分进化算法。\n\n    此攻击是由Moustafa Alzantot等人（2018）提出的。 \n\n    参考文献： `Moustafa Alzantot, Yash Sharma, Supriyo Chakraborty, \"GeneticAttack: Practical Black-box Attacks with Gradient-FreeOptimization\" <https://arxiv.org/abs/1805.11090>`_。\n\n    参数：\n        - **model** (BlackModel) - 目标模型。\n        - **model_type** (str) - 目标模型的类型。现在支持 ``'classification'`` 和 ``'detection'``。默认值：``'classification'``。\n        - **targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。 `model_type` 为 ``'detection'`` 时仅支持无目标攻击，默认值：``True``。\n        - **reserve_ratio** (Union[int, float]) - 攻击后可检测到的对象百分比，仅当 `model_type` 为 ``'detection'`` 时有效。保留比率应在(0, 1)的范围内。默认值：``0.3``。\n        - **pop_size** (int) - 粒子的数量，应大于零。默认值：``6``。\n        - **mutation_rate** (Union[int, float]) - 突变的概率，应在（0,1）的范围内。默认值：``0.005``。\n        - **per_bounds** (Union[int, float]) - 扰动允许的最大无穷范数距离。\n        - **max_steps** (int) - 每个对抗样本的最大迭代轮次。默认值：``1000``。\n        - **step_size** (Union[int, float]) - 攻击步长。默认值：``0.2``。\n        - **temp** (Union[int, float]) - 用于选择的采样温度。默认值：``0.3``。温度越大，个体选择概率之间的差异就越大。\n        - **bounds** (Union[tuple, list, None]) - 数据的上下界。以(数据最小值，数据最大值)的形式出现。默认值：``(0, 1.0)``。\n        - **adaptive** (bool) - 为 ``True``，则打开突变参数的动态缩放。如果为 ``False``，则打开静态突变参数。默认值：``False``。\n        - **sparse** (bool) - 如果为 ``True``，则输入标签为稀疏编码。如果为 ``False``，则输入标签为one-hot编码。默认值：``True``。\n        - **c** (Union[int, float]) - 扰动损失的权重。默认值：``0.1``。\n\n    .. py:method:: generate(inputs, labels)    \n\n        根据输入数据和目标标签（或ground_truth标签）生成对抗样本。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, tuple]) - 输入样本。\n\n              - 如果 `model_type` = ``'classification'``，则输入的格式应为numpy.ndarray。输入的格式可以是(input1, input2, ...)。\n              - 如果 `model_type` = ``'detection'``，则只能是一个数组。\n\n            - **labels** (Union[numpy.ndarray, tuple]) - 目标标签或ground-truth标签。\n\n              - 如果 `model_type` = ``'classification'``，标签的格式应为numpy.ndarray。\n              - 如果 `model_type` = ``'detection'``，标签的格式应为(gt_boxes, gt_labels)。\n\n        返回：\n            - **numpy.ndarray** - 每个攻击结果的布尔值。\n            - **numpy.ndarray** - 生成的对抗样本。\n            - **numpy.ndarray** - 每个样本的查询次数。\n\n.. py:class:: mindarmour.adv_robustness.attacks.HopSkipJumpAttack(model, init_num_evals=100, max_num_evals=1000, stepsize_search='geometric_progression', num_iterations=20, gamma=1.0, constraint='l2', batch_size=32, clip_min=0.0, clip_max=1.0, sparse=True)\n\n    Chen、Jordan和Wainwright提出的HopSkipJumpAttack是一种基于决策的攻击。此攻击需要访问目标模型的输出标签。\n\n    参考文献：`Chen J, Michael I. Jordan, Martin J. Wainwright. HopSkipJumpAttack: A Query-Efficient Decision-Based Attack. 2019. arXiv:1904.02144 <https://arxiv.org/abs/1904.02144>`_。\n\n    参数：\n        - **model** (BlackModel) - 目标模型。\n        - **init_num_evals** (int) - 梯度估计的初始评估数。默认值：``100``。\n        - **max_num_evals** (int) - 梯度估计的最大评估数。默认值：``1000``。\n        - **stepsize_search** (str) - 表示要如何搜索步长；\n\n          - 可取值为 ``'geometric_progression'`` 或 ``'grid_search'`` 。默认值：``'geometric_progression'``。\n        - **num_iterations** (int) - 迭代次数。默认值：``20``。\n        - **gamma** (float) - 用于设置二进制搜索阈值theta。默认值：``1.0``。\n          对于l2攻击，二进制搜索阈值 `theta` 为 :math:`gamma / d^{3/2}` 。对于linf攻击是 :math:`gamma/d^2` 。默认值：``1.0``。\n        - **constraint** (str) - 要优化距离的范数。可取值为 ``'l2'`` 或 ``'linf'``。默认值：``'l2'``。\n        - **batch_size** (int) - 批次大小。默认值：``32``。\n        - **clip_min** (float, 可选) - 最小图像组件值。默认值：``0``。\n        - **clip_max** (float, 可选) - 最大图像组件值。默认值：``1``。\n        - **sparse** (bool) - 如果为 ``True``，则输入标签为稀疏编码。如果为 ``False``，则输入标签为one-hot编码。默认值：``True``。\n\n    异常：\n        - **ValueError** - `stepsize_search` 不为 ``'geometric_progression'`` 或 ``'grid_search'``。\n        - **ValueError** - `constraint` 不为 ``'l2'`` 或 ``'linf'``。\n\n    .. py:method:: generate(inputs, labels)    \n\n        在for循环中生成对抗图像。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 原始图像。\n            - **labels** (numpy.ndarray) - 目标标签。\n\n        返回：\n            - **numpy.ndarray** - 每个攻击结果的布尔值。\n            - **numpy.ndarray** - 生成的对抗样本。\n            - **numpy.ndarray** - 每个样本的查询次数。\n\n    .. py:method:: set_target_images(target_images)\n\n        设置目标图像进行目标攻击。\n\n        参数：\n            - **target_images** (numpy.ndarray) - 目标图像。\n\n.. py:class:: mindarmour.adv_robustness.attacks.NES(model, scene, max_queries=10000, top_k=-1, num_class=10, batch_size=128, epsilon=0.3, samples_per_draw=128, momentum=0.9, learning_rate=1e-3, max_lr=5e-2, min_lr=5e-4, sigma=1e-3, plateau_length=20, plateau_drop=2.0, adv_thresh=0.25, zero_iters=10, starting_eps=1.0, starting_delta_eps=0.5, label_only_sigma=1e-3, conservative=2, sparse=True)\n\n    该类是自然进化策略（Natural Evolutionary Strategies，NES）攻击法的实现。NES使用自然进化策略来估计梯度，以提高查询效率。NES包括三个设置：Query-Limited设置、Partial-Information置和Label-Only设置。\n\n    - 在'query-limit'设置中，攻击对目标模型的查询数量有限，但可以访问所有类的概率。\n    - 在'partial-info'设置中，攻击仅有权访问top-k类的概率。\n    - 在'label-only'设置中，攻击只能访问按其预测概率排序的k个推断标签列表。 \n\n    在Partial-Information设置和Label-Only设置中，NES会进行目标攻击，因此用户需要使用set_target_images方法来设置目标类的目标图像。\n\n\n    参考文献：`Andrew Ilyas, Logan Engstrom, Anish Athalye, and Jessy Lin. Black-box adversarial attacks with limited queries and information. In ICML, July 2018 <https://arxiv.org/abs/1804.08598>`_。\n\n    参数：\n        - **model** (BlackModel) - 要攻击的目标模型。\n        - **scene** (str) - 确定算法的场景，可选值为：``'Label_Only'``、``'Partial_Info'``、``'Query_Limit'``。\n        - **max_queries** (int) - 生成对抗样本的最大查询编号。默认值：``10000``。\n        - **top_k** (int) - 用于'Partial-Info'或'Label-Only'设置，表示攻击者可用的（Top-k）信息数量。对于Query-Limited设置，此输入应设置为 ``-1``。默认值：``-1``。\n        - **num_class** (int) - 数据集中的类数。默认值：``10``。\n        - **batch_size** (int) - 批次大小。默认值：``128``。\n        - **epsilon** (float) - 攻击中允许的最大扰动。默认值：``0.3``。\n        - **samples_per_draw** (int) - 对偶采样中绘制的样本数。默认值：``128``。\n        - **momentum** (float) - 动量。默认值：``0.9``。\n        - **learning_rate** (float) - 学习率。默认值：``1e-3``。\n        - **max_lr** (float) - 最大学习率。默认值：``5e-2``。\n        - **min_lr** (float) - 最小学习率。默认值：``5e-4``。\n        - **sigma** (float) - 随机噪声的步长。默认值：``1e-3``。\n        - **plateau_length** (int) - 退火算法中使用的平台长度。默认值：``20``。\n        - **plateau_drop** (float) - 退火算法中使用的平台Drop。默认值：``2.0``。\n        - **adv_thresh** (float) - 对抗阈值。默认值：``0.25``。\n        - **zero_iters** (int) - 用于代理分数的点数。默认值：``10``。\n        - **starting_eps** (float) - Label-Only设置中使用的启动epsilon。默认值：``1.0``。\n        - **starting_delta_eps** (float) - Label-Only设置中使用的delta epsilon。默认值：``0.5``。\n        - **label_only_sigma** (float) - Label-Only设置中使用的Sigma。默认值：``1e-3``。\n        - **conservative** (int) - 用于epsilon衰变的守恒，如果没有收敛，它将增加。默认值：``2``。\n        - **sparse** (bool) - 如果为 ``True``，则输入标签为稀疏编码。如果为 ``False``，则输入标签为one-hot编码。默认值：``True``。\n\n    .. py:method:: generate(inputs, labels)    \n\n        根据输入数据和目标标签生成对抗样本。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 良性输入样本。\n            - **labels** (numpy.ndarray) - 目标标签。\n\n        返回：\n            - **numpy.ndarray** - 每个攻击结果的布尔值。\n            - **numpy.ndarray** - 生成的对抗样本。\n            - **numpy.ndarray** - 每个样本的查询次数。\n\n        异常：\n            - **ValueError** - 在'Label-Only'或'Partial-Info'设置中 `top_k` 小于0。\n            - **ValueError** - 在'Label-Only'或'Partial-Info'设置中 `target_imgs` 为 ``None``。\n            - **ValueError** - `scene` 不为 ``'Label_Only'``、``'Partial_Info'`` 或 ``'Query_Limit'``。\n\n    .. py:method:: set_target_images(target_images)\n\n        在'Partial-Info'或'Label-Only'设置中设置目标攻击的目标样本。\n\n        参数：\n            - **target_images** (numpy.ndarray) - 目标攻击的目标样本。\n\n\n.. py:class:: mindarmour.adv_robustness.attacks.PointWiseAttack(model, max_iter=1000, search_iter=10, is_targeted=False, init_attack=None, sparse=True)\n\n    点式攻击（Pointwise Attack）确保使用最小数量的更改像素为每个原始样本生成对抗样本。那些更改的像素将使用二进制搜索，以确保对抗样本和原始样本之间的距离尽可能接近。\n\n    参考文献：`L. Schott, J. Rauber, M. Bethge, W. Brendel: \"Towards the first adversarially robust neural network model on MNIST\", ICLR (2019) <https://arxiv.org/abs/1805.09190>`_。\n\n    参数：\n        - **model** (BlackModel) - 目标模型。\n        - **max_iter** (int) - 生成对抗图像的最大迭代轮数。默认值：``1000``。\n        - **search_iter** (int) - 二进制搜索的最大轮数。默认值：``10``。\n        - **is_targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。默认值：``False``。\n        - **init_attack** (Union[Attack, None]) - 用于查找起点的攻击。默认值：``None``。\n        - **sparse** (bool) - 如果为 ``True``，则输入标签为稀疏编码。如果为 ``False``，则输入标签为one-hot编码。默认值：``True``。\n\n\n    .. py:method:: generate(inputs, labels)    \n\n        根据输入样本和目标标签生成对抗样本。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 良性输入样本，用于创建对抗样本。\n            - **labels** (numpy.ndarray) - 对于有目标的攻击，标签是对抗性的目标标签。对于无目标攻击，标签是ground-truth标签。\n\n        返回：\n            - **numpy.ndarray** - 每个攻击结果的布尔值。\n            - **numpy.ndarray** - 生成的对抗样本。\n            - **numpy.ndarray** - 每个样本的查询次数。\n\n.. py:class:: mindarmour.adv_robustness.attacks.PSOAttack(model, model_type='classification', targeted=False, reserve_ratio=0.3, sparse=True, step_size=0.5, per_bounds=0.6, c1=2.0, c2=2.0, c=2.0, pop_size=6, t_max=1000, pm=0.5, bounds=None)\n\n    PSO攻击表示基于粒子群优化（Particle Swarm Optimization）算法的黑盒攻击，属于进化算法。\n    此攻击由Rayan Mosli等人（2019）提出。 \n\n    参考文献：`Rayan Mosli, Matthew Wright, Bo Yuan, Yin Pan, \"They Might NOT Be Giants: Crafting Black-Box Adversarial Examples with Fewer Queries Using Particle Swarm Optimization\", arxiv: 1909.07490, 2019. <https://arxiv.org/abs/1909.07490>`_。\n\n    参数：\n        - **model** (BlackModel) - 目标模型。\n        - **step_size** (Union[int, float]) - 攻击步长。默认值：``0.5``。\n        - **per_bounds** (Union[int, float]) - 扰动的相对变化范围。默认值：``0.6``。\n        - **c1** (Union[int, float]) - 权重系数。默认值：``2``。\n        - **c2** (Union[int, float]) - 权重系数。默认值：``2``。\n        - **c** (Union[int, float]) - 扰动损失的权重。默认值：``2``。\n        - **pop_size** (int) - 粒子的数量，应大于零。默认值：``6``。\n        - **t_max** (int) - 每个对抗样本的最大迭代轮数，应大于零。默认值：``1000``。\n        - **pm** (Union[int, float]) - 突变的概率，应在（0,1）的范围内。默认值：``0.5``。\n        - **bounds** (Union[list, tuple, None]) - 数据的上下界。以(数据最小值，数据最大值)的形式出现。默认值：``None``。\n        - **targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。 `model_type` 为 ``'detection'`` 时仅支持无目标攻击，默认值：``False``。\n        - **sparse** (bool) - 如果为 ``True``，则输入标签为稀疏编码。如果为 ``False``，则输入标签为one-hot编码。默认值：``True``。\n        - **model_type** (str) - 目标模型的类型。现在支持 ``'classification'`` 和 ``'detection'``。默认值： ``'classification'``。\n        - **reserve_ratio** (Union[int, float]) - 攻击后可检测到的对象百分比，用于 `model_type` 为 ``'detection'`` 模式的情况。保留比率应在(0, 1)的范围内。默认值：``0.3``。\n\n    .. py:method:: generate(inputs, labels)\n\n        根据输入数据和目标标签（或ground_truth标签）生成对抗样本。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, tuple]) - 输入样本。\n\n              - 如果 `model_type` = ``'classification'``，则输入的格式应为numpy.ndarray。输入的格式可以是(input1, input2, ...)。\n              - 如果 `model_type` = ``'detection'``，则只能是一个数组。\n\n            - **labels** (Union[numpy.ndarray, tuple]) - 目标标签或ground-truth标签。\n\n              - 如果 `model_type` = ``'classification'``，标签的格式应为numpy.ndarray。\n              - 如果 `model_type` = ``'detection'``，标签的格式应为(gt_boxes, gt_labels)。\n\n        返回：\n            - **numpy.ndarray** - 每个攻击结果的布尔值。\n            - **numpy.ndarray** - 生成的对抗样本。\n            - **numpy.ndarray** - 每个样本的查询次数。\n\n.. py:class:: mindarmour.adv_robustness.attacks.SaltAndPepperNoiseAttack(model, bounds=(0.0, 1.0), max_iter=100, is_targeted=False, sparse=True)\n\n    增加椒盐噪声的量以生成对抗样本。\n\n    参数：\n        - **model** (BlackModel) - 目标模型。\n        - **bounds** (tuple) - 数据的上下界。以(数据最小值，数据最大值)的形式出现。默认值：``(0.0, 1.0)``。\n        - **max_iter** (int) - 生成对抗样本的最大迭代。默认值：``100``。\n        - **is_targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。默认值：``False``。\n        - **sparse** (bool) - 如果为 ``True``，则输入标签为稀疏编码。如果为 ``False``，则输入标签为one-hot编码。默认值：``True``。\n\n    .. py:method:: generate(inputs, labels)\n\n        根据输入数据和目标标签生成对抗样本。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 原始的、未受扰动的输入。\n            - **labels** (numpy.ndarray) - 目标标签。\n\n        返回：\n            - **numpy.ndarray** - 每个攻击结果的布尔值。\n            - **numpy.ndarray** - 生成的对抗样本。\n            - **numpy.ndarray** - 每个样本的查询次数。\n\n.. py:class:: mindarmour.adv_robustness.attacks.VarianceTuningMomentumIterativeMethod(network, eps=0.3, eps_iter=0.1, bounds=(0.0, 1.0), is_targeted=False, nb_iter=5, decay_factor=1.0, nb_neighbor=5, neighbor_beta=3 / 2, norm_level='inf', loss_fn=None)\n    \n    VMI-FGSM算法是一种基于梯度的迭代式对抗攻击方法，通过引入方差调整机制，利用当前数据点在优化路径上的梯度方差来调整当前梯度，从而提高攻击的迁移性。\n    实验结果表明，在对抗训练模型上，相比于MI-FGSM算法，VMI-FGSM算法可以将攻击传递性提高超过25%。\n\n    参考文献： `X Wang, H Kun, \"Enhancing the Transferability of Adversarial Attacks through Variance Tuning\" in CVPR, 2021 <https://arxiv.org/abs/2103.15571>`_。\n\n    参数：\n        - **network** (Cell) - 目标模型。\n        - **eps** (float) - 攻击产生的对抗性扰动占数据范围的比例。默认值：``0.3``。\n        - **eps_iter** (float) - 攻击产生的单步对抗扰动占数据范围的比例。默认值：``0.1``。\n        - **bounds** (tuple) - 数据的上下界，表示数据范围。\n          以(数据最小值，数据最大值)的形式出现。默认值：``(0.0, 1.0)``。\n        - **is_targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。默认值：``False``。\n        - **nb_iter** (int) - 迭代次数。默认值：``5``。\n        - **decay_factor** (float) - 迭代中的衰变因子。默认值：``1.0``。\n        - **nb_neighbor** (int) - 攻击算法在数据样本领域内采样的样本数量。默认值：``5``。\n        - **neighbor_beta** (float) -  领域的半径上限。默认值: ``3/2``。\n        - **norm_level** (Union[int, str, numpy.inf]) - 范数类型。\n          可取值：``numpy.inf``、``1``、``2``、``'1'``、``'2'``、``'l1'``、``'l2'``、``'np.inf'``、``'inf'``、``'linf'``。默认值：``inf``。\n        - **loss_fn** (Union[Loss, None]) - 用于优化的损失函数。如果为 ``None``，则输入网络已配备损失函数。默认值：``None``。\n\n    .. py:method:: generate(inputs, labels)    \n\n        根据输入数据和原始/目标标签生成对抗样本。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, tuple]) - 良性输入样本，用于创建对抗样本。\n            - **labels** (Union[numpy.ndarray, tuple]) - 原始/目标标签。若每个输入有多个标签，将它包装在元组中。\n\n        返回：\n            - **numpy.ndarray** - 生成的对抗样本。\n\n.. py:class:: mindarmour.adv_robustness.attacks.VarianceTuningNesterovIterativeMethod(network, eps=8/255, eps_iter=2/255, bounds=(0.0, 1.0), is_targeted=False, nb_iter=10, decay_factor=1.0, nb_neighbor=5, neighbor_beta=3/2, norm_level='inf', loss_fn=None)\n    \n    VNI-FGSM算法是一种基于梯度的迭代式对抗攻击方法，与VMI-FGSM相比，VNI-FGSM在每次迭代时不仅使用当前梯度，还使用了之前所有迭代的平均梯度，\n    从而增加了攻击的稳定性和鲁棒性。实验结果表明可以将攻击迁移性提高超过30%，相比于VMI-FGSM算法，VNI-FGSM算法在对抗训练模型上具有更高的攻击成功率。\n\n    参考文献： `X Wang, H Kun, \"Enhancing the Transferability of Adversarial Attacks through Variance Tuning\" in CVPR, 2021 <https://arxiv.org/abs/2103.15571>`_。\n\n    参数：\n        - **network** (Cell) - 目标模型。\n        - **eps** (float) - 攻击产生的对抗性扰动最大占数据范围的比例。默认值： ``8/255`` 。\n        - **eps_iter** (float) - 攻击产生的单步对抗扰动占数据范围的比例。默认值：``2/255``。\n        - **bounds** (tuple) - 数据的上下界，表示数据范围。\n          以(数据最小值，数据最大值)的形式出现。默认值：``(0.0, 1.0)``。\n        - **is_targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。默认值：``False``。\n        - **nb_iter** (int) - 迭代次数。默认值：``10``。\n        - **decay_factor** (float) - 迭代中的衰变因子。默认值：``1.0``。\n        - **nb_neighbor** (int) - 攻击算法在数据样本领域内采样的样本数量。默认值：``5``。\n        - **neighbor_beta** (float) - 领域的半径上限。默认值: ``3/2``。\n        - **norm_level** (Union[int, str, numpy.inf]) - 范数类型。\n          可取值：``numpy.inf``、``1``、``2``、``'1'``、``'2'``、``'l1'``、``'l2'``、``'np.inf'``、``'inf'``、``'linf'``。默认值：``inf``。\n        - **loss_fn** (Union[Loss, None]) - 用于优化的损失函数。如果为 ``None``，则输入网络已配备损失函数。默认值：``None``。\n\n    .. py:method:: generate(inputs, labels)    \n\n        根据输入数据和原始/目标标签生成对抗样本。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, tuple]) - 良性输入样本，用于创建对抗样本。\n            - **labels** (Union[numpy.ndarray, tuple]) - 原始/目标标签。若每个输入有多个标签，将它包装在元组中。\n\n        返回：\n            - **numpy.ndarray** - 生成的对抗样本。\n"
  },
  {
    "path": "docs/api/api_python/mindarmour.adv_robustness.defenses.rst",
    "content": "mindarmour.adv_robustness.defenses\n==================================\n\n该模块包括经典的防御算法，用于防御对抗样本，增强模型的安全性和可信性。\n\n.. py:class:: mindarmour.adv_robustness.defenses.AdversarialDefense(network, loss_fn=None, optimizer=None)\n\n    使用给定的对抗样本进行对抗训练。\n\n    参数：\n        - **network** (Cell) - 要防御的MindSpore网络。\n        - **loss_fn** (Union[Loss, None]) - 损失函数。默认值：``None``。\n        - **optimizer** (Cell) - 用于训练网络的优化器。默认值：``None``。\n\n    .. py:method:: defense(inputs, labels)\n\n        通过使用输入样本进行训练来增强模型。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 输入样本。\n            - **labels** (numpy.ndarray) - 输入样本的标签。\n\n        返回：\n            - **numpy.ndarray** - 防御操作的损失。\n\n.. py:class:: mindarmour.adv_robustness.defenses.AdversarialDefenseWithAttacks(network, attacks, loss_fn=None, optimizer=None, bounds=(0.0, 1.0), replace_ratio=0.5)\n\n    利用特定的攻击方法和给定的对抗例子进行对抗训练，以增强模型的鲁棒性。\n\n    参数：\n        - **network** (Cell) - 要防御的MindSpore网络。\n        - **attacks** (list[Attack]) - 攻击方法序列。\n        - **loss_fn** (Union[Loss, None]) - 损失函数。默认值：``None``。\n        - **optimizer** (Cell) - 用于训练网络的优化器。默认值：``None``。\n        - **bounds** (tuple) - 数据的上下界。以(clip_min, clip_max)的形式出现。默认值：``(0.0, 1.0)``。\n        - **replace_ratio** (float) - 用对抗样本替换原始样本的比率，必须在0到1之间。默认值：``0.5``。\n\n    异常：\n        - **ValueError** - `replace_ratio` 不在0和1之间。\n\n    .. py:method:: defense(inputs, labels)\n\n        通过使用从输入样本生成的对抗样本进行训练来增强模型。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 输入样本。\n            - **labels** (numpy.ndarray) - 输入样本的标签。\n\n        返回：\n            - **numpy.ndarray** - 对抗性防御操作的损失。\n\n.. py:class:: mindarmour.adv_robustness.defenses.NaturalAdversarialDefense(network, loss_fn=None, optimizer=None, bounds=(0.0, 1.0), replace_ratio=0.5, eps=0.1)\n\n    基于FGSM的对抗性训练。\n\n    参考文献：`A. Kurakin, et al., \"Adversarial machine learning at scale,\" in ICLR, 2017 <https://arxiv.org/abs/1611.01236>`_。\n\n    参数：\n        - **network** (Cell) - 要防御的MindSpore网络。\n        - **loss_fn** (Union[Loss, None]) - 损失函数。默认值：``None``。\n        - **optimizer** (Cell) - 用于训练网络的优化器。默认值：``None``。\n        - **bounds** (tuple) - 数据的上下界。以(clip_min, clip_max)的形式出现。默认值：``(0.0, 1.0)``。\n        - **replace_ratio** (float) - 用对抗样本替换原始样本的比率。默认值：``0.5``。\n        - **eps** (float) - 攻击方法（FGSM）的步长。默认值：``0.1``。\n\n.. py:class:: mindarmour.adv_robustness.defenses.ProjectedAdversarialDefense(network, loss_fn=None, optimizer=None, bounds=(0.0, 1.0), replace_ratio=0.5, eps=0.3, eps_iter=0.1, nb_iter=5, norm_level='inf')\n\n    基于PGD的对抗性训练。\n\n    参考文献：`A. Madry, et al., \"Towards deep learning models resistant to adversarial attacks,\" in ICLR, 2018 <https://arxiv.org/abs/1611.01236>`_。\n\n    参数：\n        - **network** (Cell) - 要防御的MindSpore网络。\n        - **loss_fn** (Union[Loss, None]) - 损失函数。默认值：``None``。\n        - **optimizer** (Cell) - 用于训练网络的优化器。默认值：``None``。\n        - **bounds** (tuple) - 输入数据的上下界。以(clip_min, clip_max)的形式出现。默认值：``(0.0, 1.0)``。\n        - **replace_ratio** (float) - 用对抗样本替换原始样本的比率。默认值：``0.5``。\n        - **eps** (float) - PGD攻击参数epsilon。默认值：``0.3``。\n        - **eps_iter** (int) - PGD攻击参数，内环epsilon。默认值：``0.1``。\n        - **nb_iter** (int) - PGD攻击参数，迭代次数。默认值：``5``。\n        - **norm_level** (Union[int, char, numpy.inf]) - 范数类型。可选值：``1``、``2``、``np.inf``、``'l1'``、``'l2'``、``'np.inf'`` 或 ``'inf'``。默认值：``'inf'``。\n\n.. py:class:: mindarmour.adv_robustness.defenses.EnsembleAdversarialDefense(network, attacks, loss_fn=None, optimizer=None, bounds=(0.0, 1.0), replace_ratio=0.5)\n\n    使用特定攻击方法列表和给定的对抗样本进行对抗训练，以增强模型的鲁棒性。\n\n    参数：\n        - **network** (Cell) - 要防御的MindSpore网络。\n        - **attacks** (list[Attack]) - 攻击方法序列。\n        - **loss_fn** (Union[Loss, None]) - 损失函数。默认值：``None``。\n        - **optimizer** (Cell) - 用于训练网络的优化器。默认值：``None``。\n        - **bounds** (tuple) - 数据的上下界。以(clip_min, clip_max)的形式出现。默认值：``(0.0, 1.0)``。\n        - **replace_ratio** (float) - 用对抗样本替换原始样本的比率，必须在0到1之间。默认值：``0.5``。\n\n    异常：\n        - **ValueError** - `replace_ratio` 不在0和1之间。\n"
  },
  {
    "path": "docs/api/api_python/mindarmour.adv_robustness.detectors.rst",
    "content": "mindarmour.adv_robustness.detectors\n===================================\n\n此模块是用于区分对抗样本和良性样本的检测器方法。\n\n.. py:class:: mindarmour.adv_robustness.detectors.ErrorBasedDetector(auto_encoder, false_positive_rate=0.01, bounds=(0.0, 1.0))\n\n    检测器重建输入样本，测量重建误差，并拒绝重建误差大的样本。\n\n    参考文献： `MagNet: a Two-Pronged Defense against Adversarial Examples, by Dongyu Meng and Hao Chen, at CCS 2017. <https://arxiv.org/abs/1705.09064>`_。\n\n    参数：\n        - **auto_encoder** (Model) - 一个（训练过的）自动编码器，对输入图片进行重构。\n        - **false_positive_rate** (float) - 检测器的误报率。默认值：``0.01``。\n        - **bounds** (tuple) - (clip_min, clip_max)。默认值：``(0.0, 1.0)``。\n\n    .. py:method:: detect(inputs)    \n\n        检测输入样本是否具有对抗性。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 待判断的可疑样本。\n\n        返回：\n            - **list[int]** - 样本是否具有对抗性。如果res[i]=1，则索引为i的输入样本是对抗性的。\n\n    .. py:method:: detect_diff(inputs)    \n\n        检测原始样本和重建样本之间的距离。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 输入样本。\n\n        返回：\n            - **float** - 重建样本和原始样本之间的距离。\n\n    .. py:method:: fit(inputs, labels=None)    \n\n        查找给定数据集的阈值，以区分对抗样本。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 输入样本。\n            - **labels** (numpy.ndarray) - 输入样本的标签。默认值：``None``。\n\n        返回：\n            - **float** - 区分对抗样本和良性样本的阈值。\n\n    .. py:method:: set_threshold(threshold)    \n\n        设置阈值。\n\n        参数：\n            - **threshold** (float) - 检测阈值。\n\n    .. py:method:: transform(inputs)    \n\n        重建输入样本。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 输入样本。\n\n        返回：\n            - **numpy.ndarray** - 重建图像。\n\n.. py:class:: mindarmour.adv_robustness.detectors.DivergenceBasedDetector(auto_encoder, model, option='jsd', t=1, bounds=(0.0, 1.0))\n\n    基于发散的检测器学习通过js发散来区分正常样本和对抗样本。\n\n    参考文献： `MagNet: a Two-Pronged Defense against Adversarial Examples, by Dongyu Meng and Hao Chen, at CCS 2017. <https://arxiv.org/abs/1705.09064>`_。\n\n    参数：\n        - **auto_encoder** (Model) - 编码器模型。\n        - **model** (Model) - 目标模型。\n        - **option** (str) - 用于计算发散的方法。默认值：``'jsd'``。\n        - **t** (int) - 用于克服数值问题的温度。默认值：``1``。\n        - **bounds** (tuple) - 数据的上下界。以(clip_min, clip_max)的形式出现。默认值：``(0.0, 1.0)``。\n\n    .. py:method:: detect_diff(inputs)    \n\n        检测原始样本和重建样本之间的距离。\n\n        距离由JSD计算。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 输入样本。\n\n        返回：\n            - **float** - 距离。\n\n        异常：\n            - **NotImplementedError** - 不支持参数 `option` 。\n\n.. py:class:: mindarmour.adv_robustness.detectors.RegionBasedDetector(model, number_points=10, initial_radius=0.0, max_radius=1.0, search_step=0.01, degrade_limit=0.0, sparse=False)\n\n    基于区域的检测器利用对抗样本靠近分类边界的事实，并通过集成给定示例周围的信息，以检测输入是否为对抗样本。\n\n    参考文献： `Mitigating evasion attacks to deep neural networks via region-based classification <https://arxiv.org/abs/1709.05583>`_。\n\n    参数：\n        - **model** (Model) - 目标模型。\n        - **number_points** (int) - 从原始样本的超立方体生成的样本数。默认值：``10``。\n        - **initial_radius** (float) - 超立方体的初始半径。默认值：``0.0``。\n        - **max_radius** (float) - 超立方体的最大半径。默认值：``1.0``。\n        - **search_step** (float) - 半径搜索增量。默认值：``0.01``。\n        - **degrade_limit** (float) - 分类精度的可接受下降。默认值：``0.0``。\n        - **sparse** (bool) - 如果为 ``True``，则输入标签为稀疏编码。如果为 ``False``，则输入标签为onehot编码。默认值：``False``。\n\n    .. py:method:: detect(inputs)    \n\n        判断输入样本是否具有对抗性。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 待判断的可疑样本。\n\n        返回：\n            - **list[int]** - 样本是否具有对抗性。如果res[i]=1，则索引为i的输入样本是对抗性的。\n\n    .. py:method:: detect_diff(inputs)    \n\n        返回原始预测结果和基于区域的预测结果。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 输入样本。\n\n        返回：\n            - **numpy.ndarray** - 输入样本的原始预测结果和基于区域的预测结果。\n\n    .. py:method:: fit(inputs, labels=None)    \n\n        训练检测器来决定最佳半径。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 良性样本。\n            - **labels** (numpy.ndarray) - 输入样本的ground truth标签。默认值：``None``。\n\n        返回：\n            - **float** - 最佳半径。\n\n    .. py:method:: set_radius(radius)    \n\n        设置半径。\n\n        参数：\n            - **radius** (float) - 区域的半径。\n\n    .. py:method:: transform(inputs)    \n\n        为输入样本生成超级立方体。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 输入样本。\n\n        返回：\n            - **numpy.ndarray** - 每个样本对应的超立方体。\n\n.. py:class:: mindarmour.adv_robustness.detectors.SpatialSmoothing(model, ksize=3, is_local_smooth=True, metric='l1', false_positive_ratio=0.05)\n\n    基于空间平滑的检测方法。\n    使用高斯滤波、中值滤波和均值滤波，模糊原始图像。当模型在样本模糊前后的预测值之间有很大的阈值差异时，将其判断为对抗样本。\n\n    参数：\n        - **model** (Model) - 目标模型。\n        - **ksize** (int) - 平滑窗口大小。默认值：``3``。\n        - **is_local_smooth** (bool) - 如果为 ``True``，则触发局部平滑。如果为 ``False``，则无局部平滑。默认值：``True``。\n        - **metric** (str) - 距离方法。默认值：``'l1'``。\n        - **false_positive_ratio** (float) - 良性样本上的假正率。默认值：``0.05``。\n\n    .. py:method:: detect(inputs)    \n\n        检测输入样本是否为对抗样本。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 待判断的可疑样本。\n\n        返回：\n            - **list[int]** - 样本是否具有对抗性。如果res[i]=1，则索引为i的输入样本是对抗样本。\n\n    .. py:method:: detect_diff(inputs)    \n\n        返回输入样本与其平滑对应样本之间的原始距离值（在应用阈值之前）。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 待判断的可疑样本。\n\n        返回：\n            - **float** - 距离。\n\n    .. py:method:: fit(inputs, labels=None)    \n\n        训练检测器来决定阈值。适当的阈值能够确保良性样本上的实际假正率小于给定值。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 良性样本。\n            - **labels** (numpy.ndarray) - 默认 ``None``。\n\n        返回：\n            - **float** - 阈值，大于该距离的距离报告为正，即对抗性。\n\n    .. py:method:: set_threshold(threshold)    \n\n        设置阈值。\n\n        参数：\n            - **threshold** (float) - 检测阈值。\n\n.. py:class:: mindarmour.adv_robustness.detectors.EnsembleDetector(detectors, policy='vote')\n\n    集合检测器，通过检测器列表从输入样本中检测对抗样本。\n\n    参数：\n        - **detectors** (Union[tuple, list]) - 检测器方法列表。\n        - **policy** (str) - 决策策略，取值可为 ``'vote'``、``'all'``、``'any'``。默认值：``'vote'``。\n\n    .. py:method:: detect(inputs)    \n\n        从输入样本中检测对抗性示例。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 输入样本。\n\n        返回：\n            - **list[int]** - 样本是否具有对抗性。如果res[i]=1，则索引为i的输入样本是对抗样本。\n\n        异常：\n            - **ValueError** - 不支持策略。\n\n    .. py:method:: detect_diff(inputs)    \n\n        此方法在此类中不可用。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, list, tuple]) - 用于创建对抗样本。\n\n        异常：\n            - **NotImplementedError** - 此函数在集成中不可用。\n\n    .. py:method:: fit(inputs, labels=None)    \n\n        像机器学习模型一样拟合检测器。此方法在此类中不可用。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 计算阈值的数据。\n            - **labels** (numpy.ndarray) - 数据的标签。默认值：``None``。\n\n        异常：\n            - **NotImplementedError** - 此函数在集成中不可用。\n\n    .. py:method:: transform(inputs)    \n\n        过滤输入样本中的对抗性噪声。\n        此方法在此类中不可用。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, list, tuple]) - 用于创建对抗样本。\n\n        异常：\n            - **NotImplementedError** - 此函数在集成中不可用。\n\n.. py:class:: mindarmour.adv_robustness.detectors.SimilarityDetector(trans_model, max_k_neighbor=1000, chunk_size=1000, max_buffer_size=10000, tuning=False, fpr=0.001)\n\n    检测器测量相邻查询之间的相似性，并拒绝与以前的查询非常相似的查询。\n\n    参考文献： `Stateful Detection of Black-Box Adversarial Attacks by Steven Chen, Nicholas Carlini, and David Wagner. at arxiv 2019 <https://arxiv.org/abs/1907.05587>`_。\n\n    参数：\n        - **trans_model** (Model) - 一个MindSpore模型，将输入数据编码为低维向量。\n        - **max_k_neighbor** (int) - 最近邻的最大数量。默认值：``1000``。\n        - **chunk_size** (int) - 缓冲区大小。默认值：``1000``。\n        - **max_buffer_size** (int) - 最大缓冲区大小。默认值：``10000``。\n        - **tuning** (bool) - 计算k个最近邻的平均距离。\n\n          - 如果'tuning'为 ``True``，k= `max_k_neighbor` 。\n          - 如果为 ``False``，k=1,..., `max_k_neighbor` 。默认值：``False``。\n\n        - **fpr** (float) - 合法查询序列上的误报率。默认值：``0.001``。\n\n    .. py:method:: clear_buffer()    \n\n        清除缓冲区内存。\n\n    .. py:method:: detect(inputs)    \n\n        处理查询以检测黑盒攻击。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 查询序列。\n\n        异常：\n            - **ValueError** - 阈值或set_threshold方法中 `num_of_neighbors` 参数不可用。\n\n    .. py:method:: detect_diff(inputs)    \n\n        从输入样本中检测对抗样本，如常见机器学习模型中的predict_proba函数。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, list, tuple]) - 用于创建对抗样本。\n\n        异常：\n            - **NotImplementedError** - 此函数在 `SimilarityDetector` 类（class）中不可用。\n\n    .. py:method:: fit(inputs, labels=None)    \n\n        处理输入训练数据以计算阈值。\n        适当的阈值应确保假正率低于给定值。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 用于计算阈值的训练数据。\n            - **labels** (numpy.ndarray) - 训练数据的标签。\n\n        返回：\n            - **list[int]** - 最近邻的数量。\n\n            - **list[float]** - 不同k的阈值。\n\n        异常：\n            - **ValueError** - 训练数据个数小于 `max_k_neighbor`。\n\n    .. py:method:: get_detected_queries()    \n\n        获取检测到的查询的索引。\n\n        返回：\n            - **list[int]** - 检测到的恶意查询的序列号。\n\n    .. py:method:: get_detection_interval()    \n\n        获取相邻检测之间的间隔。\n\n        返回：\n            - **list[int]** - 相邻检测之间的查询数。\n\n    .. py:method:: set_threshold(num_of_neighbors, threshold)    \n\n        设置参数num_of_neighbors和threshold。\n\n        参数：\n            - **num_of_neighbors** (int) - 最近邻的数量。\n            - **threshold** (float) - 检测阈值。\n\n    .. py:method:: transform(inputs)    \n\n        过滤输入样本中的对抗性噪声。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, list, tuple]) - 用于创建对抗样本。\n\n        异常：\n            - **NotImplementedError** - 此函数在 `SimilarityDetector` 类（class）中不可用。\n"
  },
  {
    "path": "docs/api/api_python/mindarmour.adv_robustness.evaluations.rst",
    "content": "mindarmour.adv_robustness.evaluations\n=====================================\n\n此模块包括各种指标，用于评估攻击或防御的结果。\n\n.. py:class:: mindarmour.adv_robustness.evaluations.AttackEvaluate(inputs, labels, adv_inputs, adv_preds, targeted=False, target_label=None)\n\n    攻击方法的评估指标。\n\n    参数：\n        - **inputs** (numpy.ndarray) - 原始样本。\n        - **labels** (numpy.ndarray) - 原始样本的one-hot格式标签。\n        - **adv_inputs** (numpy.ndarray) - 从原始样本生成的对抗样本。\n        - **adv_preds** (numpy.ndarray) - 对对抗样本的对所有标签的预测概率。\n        - **targeted** (bool) - 如果为 ``True``，则为目标攻击。如果为 ``False``，则为无目标攻击。默认值：``False``。\n        - **target_label** (numpy.ndarray) - 对抗样本的目标标签，是大小为adv_inputs.shape[0]的一维。默认值：``None``。\n\n    异常：\n        - **ValueError** - 如果 `targeted` 为 ``True`` 时， `target_label` 为 ``None``。\n\n    .. py:method:: avg_conf_adv_class()\n\n        计算对抗类的平均置信度（ACAC）。\n\n        返回：\n            - **float** - 范围在（0,1）之间。值越高，攻击就越成功。\n\n    .. py:method:: avg_conf_true_class()\n\n        计算真类的平均置信度（ACTC）。\n\n        返回：\n            - **float** - 范围在（0,1）之间。值越低，攻击就越成功。\n\n    .. py:method:: avg_lp_distance()\n\n        计算平均lp距离（lp-dist）。\n\n        返回：\n            - **float** - 返回所有成功对抗样本的平均'l0'、'l2'或'linf'距离，返回值包括以下情况：\n          \n              - 如果返回值 :math:`>=` 0，则为平均lp距离。值越低，攻击就越成功。\n              - 如果返回值为-1，则没有成功的对抗样本。\n\n    .. py:method:: avg_ssim()\n\n        计算平均结构相似性（ASS）。\n\n        返回：\n            - **float** - 平均结构相似性。\n\n              - 如果返回值在（0,1）之间，则值越高，攻击越成功。\n              - 如果返回值为-1，则没有成功的对抗样本。\n\n    .. py:method:: mis_classification_rate()\n\n        计算错误分类率（MR）。\n\n        返回：\n            - **float** - 范围在（0,1）之间。值越高，攻击就越成功。\n\n    .. py:method:: nte()\n\n        计算噪声容量估计（NTE）。\n\n        参考文献：`Towards Imperceptible and Robust Adversarial Example Attacks against Neural Networks <https://arxiv.org/abs/1801.04693>`_。\n\n        返回：\n            - **float** - 范围在（0,1）之间。值越高，攻击就越成功。\n\n.. py:class:: mindarmour.adv_robustness.evaluations.BlackDefenseEvaluate(raw_preds, def_preds, raw_query_counts, def_query_counts, raw_query_time, def_query_time, def_detection_counts, true_labels, max_queries)\n\n    反黑盒防御方法的评估指标。\n\n    参数：\n        - **raw_preds** (numpy.ndarray) - 原始模型上特定样本的预测结果。\n        - **def_preds** (numpy.ndarray) - 原始防御模型上特定样本的预测结果。\n        - **raw_query_counts** (numpy.ndarray) - 在原始模型上生成对抗样本的查询数，原始模型是大小是与raw_preds.shape[0]的第一纬度相同。对于良性样本，查询计数必须设置为 ``0``。\n        - **def_query_counts** (numpy.ndarray) - 在防御模型上生成对抗样本的查询数，原始模型是大小是与raw_preds.shape[0]的第一纬度相同。对于良性样本，查询计数必须设置为 ``0``。\n        - **raw_query_time** (numpy.ndarray) - 在原始模型上生成对抗样本的总持续时间，该样本是大小是与raw_preds.shape[0]的第一纬度。\n        - **def_query_time** (numpy.ndarray) - 在防御模型上生成对抗样本的总持续时间，该样本是大小是与raw_preds.shape[0]的第一纬度。\n        - **def_detection_counts** (numpy.ndarray) - 每次对抗样本生成期间检测到的查询总数，大小是与raw_preds.shape[0]的第一纬度。对于良性样本，如果查询被识别为可疑，则将 `def_detection_counts` 设置为 ``1``，否则将其设置为 ``0``。\n        - **true_labels** (numpy.ndarray) - 大小是与raw_preds.shape[0]的第一纬度真标签。\n        - **max_queries** (int) - 攻击预算，最大查询数。\n\n    .. py:method:: asv()\n\n        计算攻击成功率方差（ASV）。\n\n        返回：\n            - **float** - 值越低，防守就越强。如果num_adv_samples=0，则返回-1。\n\n    .. py:method:: fpr()\n\n        计算基于查询的检测器的假正率（FPR）。\n\n        返回：\n            - **float** - 值越低，防御的可用性越高。如果num_adv_samples=0，则返回-1。\n\n    .. py:method:: qcv()\n\n        计算查询计数方差（QCV）。\n\n        返回：\n            - **float** - 值越高，防守就越强。如果num_adv_samples=0，则返回-1。\n\n    .. py:method:: qrv()\n\n        计算良性查询响应时间方差（QRV）。\n\n        返回：\n            - **float** - 值越低，防御的可用性越高。如果num_adv_samples=0，则返回-1。\n\n.. py:class:: mindarmour.adv_robustness.evaluations.DefenseEvaluate(raw_preds, def_preds, true_labels)\n\n    防御方法的评估指标。\n\n    参数：\n        - **raw_preds** (numpy.ndarray) - 原始模型上某些样本的预测结果。\n        - **def_preds** (numpy.ndarray) - 防御模型上某些样本的预测结果。\n        - **true_labels** (numpy.ndarray) - 样本的ground-truth标签，一个大小为ground-truth的一维数组。\n\n    .. py:method:: cav()\n\n        计算分类精度方差（CAV）。\n\n        返回：\n            - **float** - 值越高，防守就越成功。\n\n    .. py:method:: ccv()\n\n        计算分类置信度方差（CCV）。\n\n        返回：\n            - **float** - 值越低，防守就越成功。如果返回值== -1，则说明样本数量为0。\n\n    .. py:method:: cos()\n\n        参考文献：`Calculate classification output stability (COS) <https://en.wikipedia.org/wiki/Jensen%E2%80%93Shannon_divergence>`_。\n\n        返回：\n            - **float** - 如果返回值>=0，则是有效的防御。值越低，防守越成功。如果返回值== -1, 则说明样本数量为0。\n\n    .. py:method:: crr()\n\n        计算分类校正率（CRR）。\n\n        返回：\n            - **float** - 值越高，防守就越成功。\n\n    .. py:method:: csr()\n\n        计算分类牺牲比（CSR），越低越好。\n\n        返回：\n            - **float** - 值越低，防守就越成功。\n\n.. py:class:: mindarmour.adv_robustness.evaluations.NeuronMetric(model, inputs, adv_inputs, hook_names)\n\n    神经元敏感度，通过计算神经元在输入正常样本和对抗样本时的激活值变化，来衡量神经元的敏感度。\n\n    参数：\n        - **model** (mindspore.nn.Cell) - 待测量神经元敏感度的模型本身。\n        - **inputs** (mindspore.Tensor) - 所使用数据的原始样本。\n        - **adv_inputs** (mindspore.Tensor) - 所使用数据的对抗样本，需要和原始样本一一对应。\n        - **hook_names** (List[str]) - 所需要计算神经元敏感度的层的名字。\n\n    异常：\n        - **ValueError** - 模型中间层输出的shape维度数目小于等于1。\n\n    .. py:method:: neuron_sensitivity()\n\n        计算并返回神经元敏感度。\n\n        返回：\n            - **nsense** - 神经元敏感度的字典，包含每个层的名字和层的神经元对应的神经元敏感度。\n\n.. py:class:: mindarmour.adv_robustness.evaluations.RadarMetric(metrics_name, metrics_data, labels, title, scale='hide')\n\n    雷达图，通过多个指标显示模型的鲁棒性。\n\n    参数：\n        - **metrics_name** (Union[tuple, list]) - 要显示的度量名称数组。每组值对应一条雷达曲线。\n        - **metrics_data** (numpy.ndarray) - 多个雷达曲线的每个度量的（归一化）值，如[[0.5, 0.8, ...], [0.2,0.6,...], ...]。\n        - **labels** (Union[tuple, list]) - 所有雷达曲线的图例。\n        - **title** (str) - 图表的标题。\n        - **scale** (str) - 用于调整轴刻度的标量，如 ``'hide'``、``'norm'``、``'sparse'``、``'dense'``。默认值：``'hide'``。\n\n    异常：\n        - **ValueError** - `scale` 值不为 ``'hide'``、``'norm'``、``'sparse'``、``'dense'``。\n\n    .. py:method:: show()\n\n        显示雷达图。\n"
  },
  {
    "path": "docs/api/api_python/mindarmour.fuzz_testing.rst",
    "content": "mindarmour.fuzz_testing\n=======================\n\n该模块提供了一种基于神经元覆盖率增益的模糊测试方法来评估给定模型的鲁棒性。\n\n.. py:class:: mindarmour.fuzz_testing.Fuzzer(target_model)\n\n    深度神经网络的模糊测试框架。\n\n    参考文献：`DeepHunter: A Coverage-Guided Fuzz Testing Framework for Deep Neural Networks <https://dl.acm.org/doi/10.1145/3293882.3330579>`_。\n\n    参数：\n        - **target_model** (Model) - 目标模糊模型。\n\n    .. py:method:: fuzzing(mutate_config, initial_seeds, coverage, evaluate=True, max_iters=10000, mutate_num_per_seed=20)\n\n        深度神经网络的模糊测试。\n\n        参数：\n            - **mutate_config** (list) - 变异方法配置。格式为：\n\n              .. code-block:: python\n\n                  mutate_config = [\n                      {'method': 'GaussianBlur',\n                       'params': {'ksize': [1, 2, 3, 5], 'auto_param': [True, False]}},\n                      {'method': 'UniformNoise',\n                       'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n                      {'method': 'GaussianNoise',\n                       'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n                      {'method': 'Contrast',\n                       'params': {'alpha': [0.5, 1, 1.5], 'beta': [-10, 0, 10], 'auto_param': [False, True]}},\n                      {'method': 'Rotate',\n                       'params': {'angle': [20, 90], 'auto_param': [False, True]}},\n                      {'method': 'FGSM',\n                       'params': {'eps': [0.3, 0.2, 0.4], 'alpha': [0.1], 'bounds': [(0, 1)]}}\n                      ...]\n\n              - 支持的方法在列表 `self._strategies` 中，每个方法的参数必须在可选参数的范围内。支持的方法分为两种类型：\n              - 首先，自然鲁棒性方法包括：'Translate'、'Scale'、'Shear'、'Rotate'、'Perspective'、'Curve'、'GaussianBlur'、'MotionBlur'、'GradientBlur'、'Contrast'、'GradientLuminance'、'UniformNoise'、'GaussianNoise'、'SaltAndPepperNoise'、'NaturalNoise'。\n              - 其次，对抗样本攻击方式包括：'FGSM'、'PGD'和'MDIM'。'FGSM'、'PGD'和'MDIM'分别是 FastGradientSignMethod、ProjectedGradientDent和MomentumDiverseInputIterativeMethod的缩写。 `mutate_config` 必须包含在['Contrast', 'GradientLuminance', 'GaussianBlur', 'MotionBlur', 'GradientBlur', 'UniformNoise', 'GaussianNoise', 'SaltAndPepperNoise', 'NaturalNoise']中的方法。\n\n              - 第一类方法的参数设置方式可以在'mindarmour/natural_robustness/transform/image'中看到。第二类方法参数配置参考 `self._attack_param_checklists` 。\n            - **initial_seeds** (list[list]) - 用于生成变异样本的初始种子队列。初始种子队列的格式为[[image_data, label], [...], ...]，且标签必须为one-hot。\n            - **coverage** (CoverageMetrics) - 神经元覆盖率指标类。\n            - **evaluate** (bool) - 是否返回评估报告。默认值：``True``。\n            - **max_iters** (int) - 选择要变异的种子的最大数量。默认值：``10000``。\n            - **mutate_num_per_seed** (int) - 每个种子的最大变异次数。默认值：``20``。\n\n        返回：\n            - **list** - 模糊测试生成的变异样本。\n            - **list** - 变异样本的ground truth标签。\n            - **list** - 预测结果。\n            - **list** - 变异策略。\n            - **dict** - Fuzzer的指标报告。\n\n        异常：\n            - **ValueError** - 参数 `coverage` 必须是CoverageMetrics的子类。\n            - **ValueError** - 初始种子队列为空。\n            - **ValueError** - `initial_seeds` 中的种子未包含两个元素。\n\n.. py:class:: mindarmour.fuzz_testing.SensitivityMaximizingFuzzer(target_model)\n\n    深度神经网络的模糊测试框架。\n\n    参考文献：\n        `Themis_Sensitivity_Testing_for_Deep_Learning_System <https://huangd1999.github.io/Themis__Sensitivity_Testing_for_Deep_Learning_System.pdf>`_。\n\n    参数：\n        - **target_model** (Model) - 目标模糊模型。\n\n    .. py:method:: fuzzing(mutate_config, initial_seeds, coverage, evaluate=True, max_iters=1000, mutate_num_per_seed=20)\n\n        深度神经网络的模糊测试。\n\n        参数：\n            - **mutate_config** (list) - 变异方法配置。格式为：\n\n              .. code-block:: python\n\n                  mutate_config = [\n                      {'method': 'GaussianBlur',\n                       'params': {'ksize': [1, 2, 3, 5], 'auto_param': [True, False]}},\n                      {'method': 'UniformNoise',\n                       'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n                      {'method': 'GaussianNoise',\n                       'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n                      {'method': 'Contrast',\n                       'params': {'alpha': [0.5, 1, 1.5], 'beta': [-10, 0, 10], 'auto_param': [False, True]}},\n                      {'method': 'Rotate',\n                       'params': {'angle': [20, 90], 'auto_param': [False, True]}},\n                      {'method': 'FGSM',\n                       'params': {'eps': [0.3, 0.2, 0.4], 'alpha': [0.1], 'bounds': [(0, 1)]}}\n                      ...]\n\n              - 支持的方法在列表 `self._strategies` 中，每个方法的参数必须在可选参数的范围内。支持的方法分为两种类型：\n              - 首先，自然鲁棒性方法包括：'Translate'、'Scale'、'Shear'、'Rotate'、'Perspective'、'Curve'、'GaussianBlur'、'MotionBlur'、'GradientBlur'、'Contrast'、'GradientLuminance'、'UniformNoise'、'GaussianNoise'、'SaltAndPepperNoise'、'NaturalNoise'。\n              - 其次，对抗样本攻击方式包括：'FGSM'、'PGD'和'MDIM'。'FGSM'、'PGD'和'MDIM'分别是 FastGradientSignMethod、ProjectedGradientDent和MomentumDiverseInputIterativeMethod的缩写。 `mutate_config` 必须包含在['Contrast', 'GradientLuminance', 'GaussianBlur', 'MotionBlur', 'GradientBlur', 'UniformNoise', 'GaussianNoise', 'SaltAndPepperNoise', 'NaturalNoise']中的方法。\n\n              - 第一类方法的参数设置方式可以在'mindarmour/natural_robustness/transform/image'中看到。第二类方法参数配置参考 `self._attack_param_checklists` 。\n\n            - **initial_seeds** (list[list]) - 用于生成变异样本的初始种子队列。初始种子队列的格式为[[image_data, label], [...], ...]，且标签必须为one-hot。\n            - **coverage** (CoverageMetrics) - 神经元覆盖率指标类。\n            - **evaluate** (bool) - 是否返回评估报告。默认值： ``True``。\n            - **max_iters** (int) - 选择要变异的种子的最大数量。默认值： ``1000``。\n            - **mutate_num_per_seed** (int) - 每个种子的最大变异次数。默认值： ``20``。\n\n        返回：\n            - list，模糊测试生成的变异样本。\n            - list，变异样本的ground truth标签。\n            - list，预测结果。\n            - list，变异策略。\n            - dict，Fuzzer的指标报告。\n\n        异常：\n            - **ValueError** - 参数 `coverage` 必须是CoverageMetrics的子类。\n            - **ValueError** - 初始种子队列为空。\n            - **ValueError** - `initial_seeds` 中的种子未包含两个元素。\n\n.. py:class:: mindarmour.fuzz_testing.CoverageMetrics(model, incremental=False, batch_size=32)\n\n    计算覆盖指标的神经元覆盖类的抽象基类。\n\n    训练后网络的每个神经元输出有一个输出范围（我们称之为原始范围），测试数据集用于估计训练网络的准确性。然而，不同的测试数据集，神经元的输出分布会有所不同。因此，与传统模糊测试类似，模型模糊测试意味着测试这些神经元的输出，并评估在测试数据集上神经元输出值占原始范围的比例。\n\n    参考文献： `DeepGauge: Multi-Granularity Testing Criteria for Deep Learning Systems <https://arxiv.org/abs/1803.07519>`_。\n\n    参数：\n        - **model** (Model) - 被测模型。\n        - **incremental** (bool) - 指标将以增量方式计算。默认值：``False``。\n        - **batch_size** (int) - 模糊测试批次中的样本数。默认值：``32``。\n    \n    .. py:method:: get_metrics(dataset)\n        :abstractmethod:\n\n        计算给定数据集的覆盖率指标。\n\n        参数：\n            - **dataset** (numpy.ndarray) - 用于计算覆盖指标的数据集。\n\n        异常：\n            - **NotImplementedError** - 抽象方法。\n\n.. py:class:: mindarmour.fuzz_testing.NeuronCoverage(model, threshold=0.1, incremental=False, batch_size=32)\n\n    计算神经元激活的覆盖率。当神经元的输出大于阈值时，神经元被激活。\n\n    神经元覆盖率等于网络中激活的神经元占总神经元的比例。\n\n    参数：\n        - **model** (Model) - 被测模型。\n        - **threshold** (float) - 用于确定神经元是否激活的阈值。默认值：``0.1``。\n        - **incremental** (bool) - 指标将以增量方式计算。默认值：``False``。\n        - **batch_size** (int) - 模糊测试批次中的样本数。默认值：``32``。\n\n    .. py:method:: get_metrics(dataset)\n\n        获取神经元覆盖率的指标：激活的神经元占网络中神经元总数的比例。\n\n        参数：\n            - **dataset** (numpy.ndarray) - 用于计算覆盖率指标的数据集。\n\n        返回：\n            - **float** - 'neuron coverage'的指标。\n\n.. py:class:: mindarmour.fuzz_testing.TopKNeuronCoverage(model, top_k=3, incremental=False, batch_size=32)\n\n    计算前k个激活神经元的覆盖率。当隐藏层神经元的输出值在最大的 `top_k` 范围内，神经元就会被激活。`top_k` 神经元覆盖率等于网络中激活神经元占总神经元的比例。\n\n    参数：\n        - **model** (Model) - 被测模型。\n        - **top_k** (int) - 当隐藏层神经元的输出值在最大的 `top_k` 范围内，神经元就会被激活。默认值：``3``。\n        - **incremental** (bool) - 指标将以增量方式计算。默认值：``False``。\n        - **batch_size** (int) - 模糊测试批次中的样本数。默认值：``32``。\n\n    .. py:method:: get_metrics(dataset)\n\n        获取Top K激活神经元覆盖率的指标。\n\n        参数：\n            - **dataset** (numpy.ndarray) - 用于计算覆盖率指标的数据集。\n\n        返回：\n            - **float** - 'top k neuron coverage'的指标。\n\n.. py:class:: mindarmour.fuzz_testing.NeuronBoundsCoverage(model, train_dataset, incremental=False, batch_size=32)\n\n    获取'neuron boundary coverage'的指标 :math:`NBC = (|UpperCornerNeuron| + |LowerCornerNeuron|)/(2*|N|)` ，其中 :math:`|N|` 是神经元的数量，NBC是指测试数据集中神经元输出值超过训练数据集中相应神经元输出值的上下界的神经元比例。\n\n    参数：\n        - **model** (Model) - 等待测试的预训练模型。\n        - **train_dataset** (numpy.ndarray) - 用于确定神经元输出边界的训练数据集。\n        - **incremental** (bool) - 指标将以增量方式计算。默认值：``False``。\n        - **batch_size** (int) - 模糊测试批次中的样本数。默认值：``32``。\n\n    .. py:method:: get_metrics(dataset)\n\n        获取'neuron boundary coverage'的指标。\n\n        参数：\n            - **dataset** (numpy.ndarray) - 用于计算覆盖指标的数据集。\n\n        返回：\n            - **float** - 'neuron boundary coverage'的指标。\n\n.. py:class:: mindarmour.fuzz_testing.SuperNeuronActivateCoverage(model, train_dataset, incremental=False, batch_size=32)\n\n    获取超激活神经元覆盖率（'super neuron activation coverage'）的指标。 :math:`SNAC = |UpperCornerNeuron|/|N|` 。SNAC是指测试集中神经元输出值超过训练集中相应神经元输出值上限的神经元比例。\n\n    参数：\n        - **model** (Model) - 等待测试的预训练模型。\n        - **train_dataset** (numpy.ndarray) - 用于确定神经元输出边界的训练数据集。\n        - **incremental** (bool) - 指标将以增量方式计算。默认值：``False``。\n        - **batch_size** (int) - 模糊测试批次中的样本数。默认值：``32``。\n\n    .. py:method:: get_metrics(dataset)\n\n        获取超激活神经元覆盖率（'super neuron activation coverage'）的指标。\n\n        参数：\n            - **dataset** (numpy.ndarray) - 用于计算覆盖指标的数据集。\n\n        返回：\n            - **float** - 超激活神经元覆盖率（'super neuron activation coverage'）的指标\n\n.. py:class:: mindarmour.fuzz_testing.KMultisectionNeuronCoverage(model, train_dataset, segmented_num=100, incremental=False, batch_size=32)\n\n    获取K分神经元覆盖率的指标。KMNC度量测试集神经元输出落在训练集输出范围k等分间隔上的比例。\n\n    参数：\n        - **model** (Model) - 等待测试的预训练模型。\n        - **train_dataset** (numpy.ndarray) - 用于确定神经元输出边界的训练数据集。\n        - **segmented_num** (int) - 神经元输出间隔的分段部分数量。默认值：``100``。\n        - **incremental** (bool) - 指标将以增量方式计算。默认值：``False``。\n        - **batch_size** (int) - 模糊测试批次中的样本数。默认值：``32``。\n\n    .. py:method:: get_metrics(dataset)\n\n        获取'k-multisection neuron coverage'的指标。\n\n        参数：\n            - **dataset** (numpy.ndarray) - 用于计算覆盖指标的数据集。\n\n        返回：\n            - **float** - 'k-multisection neuron coverage'的指标。\n\n.. py:class:: mindarmour.fuzz_testing.SensitivityConvergenceCoverage(model, threshold=0.5, incremental=False, batch_size=32, selected_neurons_num=100, n_iter=1000)\n\n    获取神经元收敛覆盖率的指标。SCC度量神经元输出变化值收敛为正态分布的比例。\n\n    参数：\n        - **model** (Model) - 等待测试的预训练模型。\n        - **threshold** (float) - 神经元收敛阈值。默认值： ``0.5``。\n        - **incremental** (bool) - 指标将以增量方式计算。默认值： ``False``。\n        - **batch_size** (int) - 模糊测试批次中的样本数。默认值： ``32``。\n        - **selected_neurons_num** (int) - 模糊测试时所选取的神经元数量。默认值： ``100``。\n        - **n_iter** (int) - 模糊测试时最大测试次数。默认值： ``1000``。\n\n    .. py:method:: get_metrics(dataset)\n\n        获取'neuron convergence coverage'的指标。\n\n        参数：\n            - **dataset** (numpy.ndarray) - 用于计算覆盖指标的数据集。\n\n        返回：\n            - **float** - 'neuron convergence coverage'的指标。\n"
  },
  {
    "path": "docs/api/api_python/mindarmour.natural_robustness.transform.image.rst",
    "content": "mindarmour.natural_robustness.transform.image\r\n=============================================\r\n\r\n本模块包含图像的自然扰动方法。\r\n\r\n.. py:class:: mindarmour.natural_robustness.transform.image.Contrast(alpha=1, beta=0, auto_param=False)\r\n\r\n    图像的对比度。\r\n\r\n    参数：\r\n        - **alpha** (Union[float, int]) - 控制图像的对比度。:math:`out\\_image = in\\_image \\times alpha+beta`。建议值范围[0.2, 2]。默认值：1。\r\n        - **beta** (Union[float, int]) - 补充alpha的增量。默认值：``0``。\r\n        - **auto_param** (bool) - 自动选择参数。在保留图像的语义的范围内自动选择参数。默认值：``False``。\r\n\r\n.. py:class:: mindarmour.natural_robustness.transform.image.GradientLuminance(color_start=(0, 0, 0), color_end=(255, 255, 255), start_point=(10, 10), scope=0.5, pattern='light', bright_rate=0.3, mode='circle', auto_param=False)\r\n\r\n    渐变调整图片的亮度。\r\n\r\n    参数：\r\n        - **color_start** (union[tuple, list]) - 渐变中心的颜色。默认值：``(0, 0, 0)``。\r\n        - **color_end** (union[tuple, list]) - 渐变边缘的颜色。默认值：``(255, 255, 255)``。\r\n        - **start_point** (union[tuple, list]) - 渐变中心的二维坐标。默认值：``(10, 10)``。\r\n        - **scope** (float) - 渐变的范围。值越大，渐变范围越大。默认值：``0.5``。\r\n        - **pattern** (str) - 深色或浅色，此值必须为 ``'light'`` 或 ``'dark'``。默认值： ``'light'``。\r\n        - **bright_rate** (float) - 控制亮度。值越大，梯度范围越大。如果参数 `pattern` 为 ``'light'``，建议值范围为[0.1, 0.7]，如果参数 `pattern` 为 ``'dark'``，建议值范围为[0.1, 0.9]。默认值：``0.3``。\r\n        - **mode** (str) - 渐变模式，值必须为 ``'circle'``、``'horizontal'`` 或 ``'vertical'``。默认值：``'circle'``。\r\n        - **auto_param** (bool) - 自动选择参数。在保留图像的语义的范围内自动选择参数。默认值：``False``。\r\n\r\n.. py:class:: mindarmour.natural_robustness.transform.image.GaussianBlur(ksize=2, auto_param=False)\r\n\r\n    使用高斯模糊滤镜模糊图像。\r\n\r\n    参数：\r\n        - **ksize** (int) - 高斯核的大小，必须为非负数。默认值：``2``。\r\n        - **auto_param** (bool) - 自动选择参数。在保留图像的语义的范围内自动选择参数。默认值：``False``。\r\n\r\n.. py:class:: mindarmour.natural_robustness.transform.image.MotionBlur(degree=5, angle=45, auto_param=False)\r\n\r\n    运动模糊。\r\n\r\n    参数：\r\n        - **degree** (int) - 模糊程度。必须为正值。建议取值范围[1, 15]。默认值：``5``。\r\n        - **angle** (union[float, int]) - 运动模糊的方向。angle=0表示上下运动模糊。角度为逆时针方向。默认值：``45``。\r\n        - **auto_param** (bool) - 自动选择参数。在保留图像的语义的范围内自动选择参数。默认值：``False``。\r\n\r\n\r\n.. py:class:: mindarmour.natural_robustness.transform.image.GradientBlur(point, kernel_num=3, center=True, auto_param=False)\r\n\r\n    渐变模糊。\r\n\r\n    参数：\r\n        - **point** (union[tuple, list]) - 模糊中心点的二维坐标。\r\n        - **kernel_num** (int) - 模糊核的数量。建议取值范围[1, 8]。默认值：``3``。\r\n        - **center** (bool) - 指定中心点模糊或指定中心点清晰。默认值：``True``。\r\n        - **auto_param** (bool) - 自动选择参数。在保留图像的语义的范围内自动选择参数。默认值：``False``。\r\n\r\n.. py:class:: mindarmour.natural_robustness.transform.image.UniformNoise(factor=0.1, auto_param=False)\r\n\r\n    图像添加均匀噪声。\r\n\r\n    参数：\r\n        - **factor** (float) - 噪声密度，单位像素区域添加噪声的比例。建议取值范围：[0.001, 0.15]。默认值：``0.1``。\r\n        - **auto_param** (bool) - 自动选择参数。在保留图像的语义的范围内自动选择参数。默认值：``False``。\r\n\r\n.. py:class:: mindarmour.natural_robustness.transform.image.GaussianNoise(factor=0.1, auto_param=False)\r\n\r\n    图像添加高斯噪声。\r\n\r\n    参数：\r\n        - **factor** (float) - 噪声密度，单位像素区域添加噪声的比例。建议取值范围：[0.001, 0.15]。默认值：``0.1``。\r\n        - **auto_param** (bool) - 自动选择参数。在保留图像的语义的范围内自动选择参数。默认值：``False``。\r\n\r\n.. py:class:: mindarmour.natural_robustness.transform.image.SaltAndPepperNoise(factor=0, auto_param=False)\r\n\r\n    图像添加椒盐噪声。\r\n\r\n    参数：\r\n        - **factor** (float) - 噪声密度，单位像素区域添加噪声的比例。建议取值范围：[0.001, 0.15]。默认值：``0``。\r\n        - **auto_param** (bool) - 自动选择参数。在保留图像的语义的范围内自动选择参数。默认值：``False``。\r\n\r\n.. py:class:: mindarmour.natural_robustness.transform.image.NaturalNoise(ratio=0.0002, k_x_range=(1, 5), k_y_range=(3, 25), auto_param=False)\r\n\r\n    图像添加自然噪声。\r\n\r\n    参数：\r\n        - **ratio** (float) - 噪声密度，单位像素区域添加噪声的比例。建议取值范围：[0.00001, 0.001]。默认值：``0.0002``。\r\n        - **k_x_range** (union[list, tuple]) - 噪声块长度的取值范围。默认值：``(1, 5)``。\r\n        - **k_y_range** (union[list, tuple]) - 噪声块宽度的取值范围。默认值：``(3, 25)``。\r\n        - **auto_param** (bool) - 自动选择参数。在保留图像的语义的范围内自动选择参数。默认值：``False``。\r\n\r\n.. py:class:: mindarmour.natural_robustness.transform.image.Translate(x_bias=0, y_bias=0, auto_param=False)\r\n\r\n    图像平移。\r\n\r\n    参数：\r\n        - **x_bias** (Union[int, float]) - X方向平移， :math:`x = x + x\\_bias \\times image\\_length` 。建议取值范围在[-0.1, 0.1]中。默认值：``0``。\r\n        - **y_bias** (Union[int, float]) - Y方向平移， :math:`y = y + y\\_bias \\times image\\_width` 。建议取值范围在[-0.1, 0.1]中。默认值：``0``。\r\n        - **auto_param** (bool) - 自动选择参数。在保留图像的语义的范围内自动选择参数。默认值：``False``。\r\n\r\n.. py:class:: mindarmour.natural_robustness.transform.image.Scale(factor_x=1, factor_y=1, auto_param=False)\r\n\r\n    图像缩放。\r\n\r\n    参数：\r\n        - **factor_x** (Union[float, int]) - 在X方向缩放， :math:`x=factor_x \\times x` 。建议取值范围在[0.5, 1]且abs(factor_y - factor_x) < 0.5。默认值：``1``。\r\n        - **factor_y** (Union[float, int]) - 沿Y方向缩放， :math:`y=factor_y \\times y` 。建议取值范围在[0.5, 1]且abs(factor_y - factor_x) < 0.5。默认值：``1``。\r\n        - **auto_param** (bool) - 自动选择参数。在保留图像的语义的范围内自动选择参数。默认值：``False``。\r\n\r\n.. py:class:: mindarmour.natural_robustness.transform.image.Shear(factor=0.2, direction='horizontal', auto_param=False)\r\n\r\n    图像错切，错切后图像和原图的映射关系为： :math:`(new_x, new_y) = (x+factor_x \\times y, factor_y \\times x+y)` 。错切后图像将重新缩放到原图大小。\r\n\r\n    参数：\r\n        - **factor** (Union[float, int]) - 沿错切方向上的错切比例。建议值范围[0.05, 0.5]。默认值：``0.2``。\r\n        - **direction** (str) - 形变方向。可选值为 ``'vertical'`` 或 ``'horizontal'``。默认值：``'horizontal'``。\r\n        - **auto_param** (bool) - 自动选择参数。在保留图像的语义的范围内自动选择参数。默认值：``False``。\r\n\r\n.. py:class:: mindarmour.natural_robustness.transform.image.Rotate(angle=20, auto_param=False)\r\n\r\n    围绕图像中心点逆时针旋转图像。\r\n\r\n    参数：\r\n        - **angle** (Union[float, int]) - 逆时针旋转的度数。建议值范围[-60, 60]。默认值：``20``。\r\n        - **auto_param** (bool) - 自动选择参数。在保留图像的语义的范围内自动选择参数。默认值：``False``。\r\n\r\n.. py:class:: mindarmour.natural_robustness.transform.image.Perspective(ori_pos, dst_pos, auto_param=False)\r\n\r\n    透视变换。\r\n\r\n    参数：\r\n        - **ori_pos** (list[list[int]]) - 原始图像中的四个点的坐标。\r\n        - **dst_pos** (list[list[int]]) - 对应的 `ori_pos` 中4个点透视变换后的点坐标。\r\n        - **auto_param** (bool) - 自动选择参数。在保留图像的语义的范围内自动选择参数。默认值：``False``。\r\n\r\n.. py:class:: mindarmour.natural_robustness.transform.image.Curve(curves=3, depth=10, mode='vertical', auto_param=False)\r\n\r\n    使用Sin函数的曲线变换。\r\n\r\n    参数：\r\n        - **curves** (union[float, int]) - 曲线周期数。建议取值范围[0.1, 5]。默认值：``3``。\r\n        - **depth** (union[float, int]) - sin函数的幅度。建议取值不超过图片长度的1/10。默认值：``10``。\r\n        - **mode** (str) - 形变方向。可选值 ``'vertical'`` 或 ``'horizontal'``。默认值：``'vertical'``。\r\n        - **auto_param** (bool) - 自动选择参数。在保留图像的语义的范围内自动选择参数。默认值：``False``。"
  },
  {
    "path": "docs/api/api_python/mindarmour.privacy.diff_privacy.rst",
    "content": "mindarmour.privacy.diff_privacy\n===============================\n\n本模块提供差分隐私功能，以保护用户隐私。\n\n.. py:class:: mindarmour.privacy.diff_privacy.NoiseGaussianRandom(norm_bound=1.0, initial_noise_multiplier=1.0, seed=0, decay_policy=None)\n\n    基于 :math:`mean=0` 以及 :math:`standard\\_deviation = norm\\_bound * initial\\_noise\\_multiplier` 的高斯分布产生噪声。\n\n    参数：\n        - **norm_bound** (float) - 梯度的l2范数的裁剪范围。默认值：``1.0``。\n        - **initial_noise_multiplier** (float) - 高斯噪声标准偏差除以 `norm_bound` 的比率，将用于计算隐私预算。默认值：``1.0``。\n        - **seed** (int) - 原始随机种子。如果值为 ``0``，随机正态将使用安全随机数，否则随机正态将使用给定的种子生成值。默认值：``0``。\n        - **decay_policy** (str) - 衰减策略。默认值：``None``。\n\n    .. py:method:: construct(gradients)\n\n        产生高斯噪声。\n\n        参数：\n            - **gradients** (Tensor) - 梯度。\n\n        返回：\n            - **Tensor** - 生成的shape与给定梯度相同的噪声。\n\n.. py:class:: mindarmour.privacy.diff_privacy.NoiseAdaGaussianRandom(norm_bound=1.0, initial_noise_multiplier=1.0, seed=0, noise_decay_rate=6e-6, decay_policy='Exp')\n\n    自适应高斯噪声产生机制。噪音会随着训练而衰减。衰减模式可以是 ``'Time'``、``'Step'``、``'Exp'``。\n    在模型训练过程中，将更新 `self._noise_multiplier` 。\n\n    参数：\n        - **norm_bound** (float) - 梯度的l2范数的裁剪范围。默认值：``1.0``。\n        - **initial_noise_multiplier** (float) - 高斯噪声标准偏差除以 `norm_bound` 的比率，将用于计算隐私预算。默认值：``1.0``。\n        - **seed** (int) - 原始随机种子。如果值为 ``0``，随机正态将使用安全随机数，否则随机正态将使用给定的种子生成值。默认值：``0``。\n        - **noise_decay_rate** (float) - 控制噪声衰减的超参数。默认值：``6e-6``。\n        - **decay_policy** (str) - 噪声衰减策略包括 ``'Step'``、``'Time'``、``'Exp'``。默认值：``'Exp'``。\n\n    .. py:method:: construct(gradients)\n\n        生成自适应高斯噪声。\n\n        参数：\n            - **gradients** (Tensor) - 梯度。\n\n        返回：\n            - **Tensor** - 生成的shape与给定梯度相同的噪声。\n\n.. py:class:: mindarmour.privacy.diff_privacy.AdaClippingWithGaussianRandom(decay_policy='Linear', learning_rate=0.001, target_unclipped_quantile=0.9, fraction_stddev=0.01, seed=0)\n\n    自适应剪裁。\n    如果 `decay_policy` 是'Linear'，则更新公式为：:math:`norm\\_bound = norm\\_bound - learning\\_rate*(beta - target\\_unclipped\\_quantile)` 。\n\n    如果 `decay_policy` 是'Geometric'，则更新公式为 :math:`norm\\_bound = norm\\_bound*exp(-learning\\_rate*(empirical\\_fraction - target\\_unclipped\\_quantile))` 。\n\n    其中，beta是值最多为 `target_unclipped_quantile` 的样本的经验分数。\n\n    参数：\n        - **decay_policy** (str) - 自适应剪裁的衰变策略， `decay_policy` 必须为 ``'Linear'`` 或 ``'Geometric'``。默认值：``'Linear'``。\n        - **learning_rate** (float) - 更新范数裁剪的学习率。默认值：``0.001``。\n        - **target_unclipped_quantile** (float) - 范数裁剪的目标分位数。默认值：``0.9``。\n        - **fraction_stddev** (float) - 高斯正态的stddev，用于 `empirical_fraction` ，公式为empirical_fraction + N(0, fraction_stddev)。默认值：``0.01``。\n        - **seed** (int) - 原始随机种子。如果值为 ``0``，随机正态将使用安全随机数，否则随机正态将使用给定的种子生成值。默认值：``0``。\n\n    返回：\n        - **Tensor** - 更新后的梯度裁剪阈值。\n\n    .. py:method:: construct(empirical_fraction, norm_bound)\n\n        更新 `norm_bound` 的值。\n\n        参数：\n            - **empirical_fraction** (Tensor) - 梯度裁剪的经验分位数,最大值不超过 `target_unclipped_quantile` 。\n            - **norm_bound** (Tensor) - 梯度的l2范数的裁剪范围。\n\n        返回：\n            - **Tensor** - 生成的shape与给定梯度相同的噪声。\n\n.. py:class:: mindarmour.privacy.diff_privacy.NoiseMechanismsFactory\n\n    噪声产生机制的工厂类。它目前支持高斯随机噪声（Gaussian Random Noise）和自适应高斯随机噪声（Adaptive Gaussian Random Noise）。\n\n    详情请查看： `教程 <https://mindspore.cn/mindarmour/docs/zh-CN/master/protect_user_privacy_with_differential_privacy.html#%E5%B7%AE%E5%88%86%E9%9A%90%E7%A7%81>`_。\n\n    .. py:method:: create(mech_name, norm_bound=1.0, initial_noise_multiplier=1.0, seed=0, noise_decay_rate=6e-6, decay_policy=None)\n        :abstractmethod:\n\n        参数：\n            - **mech_name** (str) - 噪声生成策略，可以是 ``'Gaussian'`` 或 ``'AdaGaussian'``。噪声在 ``'AdaGaussian'`` 机制下衰减，而在 ``'Gaussian'`` 机制下则恒定。\n            - **norm_bound** (float) - 梯度的l2范数的裁剪范围。默认值：``1.0``。\n            - **initial_noise_multiplier** (float) - 高斯噪声标准偏差除以 `norm_bound` 的比率，将用于计算隐私预算。默认值：``1.0``。\n            - **seed** (int) - 原始随机种子。如果值为 ``0``，随机正态将使用安全随机数，否则随机正态将使用给定的种子生成值。默认值：``0``。\n            - **noise_decay_rate** (float) - 控制噪声衰减的超参数。默认值：``6e-6``。\n            - **decay_policy** (str) - 衰减策略。如果 `decay_policy` 为 ``None``，则不需要更新参数。默认值：``None``。\n\n        返回：\n            - **Mechanisms** - 产生的噪声类别机制。\n\n        异常：\n            - **NameError** - `mech_name` 必须为 ``'Gaussian'`` 或 ``'AdaGaussian'``。\n\n.. py:class:: mindarmour.privacy.diff_privacy.ClipMechanismsFactory\n\n    梯度剪裁机制的工厂类。它目前支持高斯随机噪声（Gaussian Random Noise）的自适应剪裁（Adaptive Clipping）。\n\n    详情请查看： `教程 <https://mindspore.cn/mindarmour/docs/zh-CN/master/protect_user_privacy_with_differential_privacy.html#%E5%B7%AE%E5%88%86%E9%9A%90%E7%A7%81>`_。\n\n    .. py:method:: create(mech_name, decay_policy='Linear', learning_rate=0.001, target_unclipped_quantile=0.9, fraction_stddev=0.01, seed=0)\n        :abstractmethod:\n\n        参数：\n            - **mech_name** (str) - 噪声裁剪生成策略，现支持 ``'Gaussian'``。\n            - **decay_policy** (str) - 自适应剪裁的衰变策略，``decay_policy`` 必须为 ``'Linear'`` 或 ``'Geometric'``。默认值：``'Linear'``。\n            - **learning_rate** (float) - 更新范数裁剪的学习率。默认值：``0.001``。\n            - **target_unclipped_quantile** (float) - 范数裁剪的目标分位数。默认值：``0.9``。\n            - **fraction_stddev** (float) - 高斯正态的stddev，用于empirical_fraction，公式为 :math:`empirical\\_fraction + N(0, fraction\\_stddev)` 。默认值：``0.01``。\n            - **seed** (int) - 原始随机种子。如果值为 ``0``，随机正态将使用安全随机数，否则随机正态将使用给定的种子生成值。默认值：``0``。\n\n        返回：\n            - **Mechanisms** - 产生的噪声类别机制。 \n\n        异常：\n            - **NameError** - `mech_name` 必须为 ``'Gaussian'``。\n\n.. py:class:: mindarmour.privacy.diff_privacy.PrivacyMonitorFactory\n\n    DP训练隐私监视器的工厂类。\n\n    详情请查看： `教程 <https://mindspore.cn/mindarmour/docs/zh-CN/master/protect_user_privacy_with_differential_privacy.html#%E5%B7%AE%E5%88%86%E9%9A%90%E7%A7%81>`_。\n\n    .. py:method:: create(policy, *args, **kwargs)\n        :abstractmethod:\n\n        创建隐私预算监测类。\n\n        参数：\n            - **policy** (str) - 监控策略，现支持 ``'rdp'`` 和 ``'zcdp'``。\n\n              - 如果策略为 ``'rdp'``，监控器将根据Renyi差分隐私（Renyi differential privacy，RDP）理论计算DP训练的隐私预算；\n              - 如果策略为 ``'zcdp'``，监控器将根据零集中差分隐私（zero-concentrated differential privacy，zCDP）理论计算DP训练的隐私预算。注意，``'zcdp'`` 不适合子采样噪声机制。\n            - **args** (Union[int, float, numpy.ndarray, list, str]) - 用于创建隐私监视器的参数。\n            - **kwargs** (Union[int, float, numpy.ndarray, list, str]) - 用于创建隐私监视器的关键字参数。\n\n        返回：\n            - **Callback** - 隐私监视器。\n\n.. py:class:: mindarmour.privacy.diff_privacy.RDPMonitor(num_samples, batch_size, initial_noise_multiplier=1.5, max_eps=10.0, target_delta=1e-3, max_delta=None, target_eps=None, orders=None, noise_decay_mode='Time', noise_decay_rate=6e-4, per_print_times=50, dataset_sink_mode=False)\n\n    基于Renyi差分隐私（RDP）理论，计算DP训练的隐私预算。根据下面的参考文献，如果随机化机制被认为具有α阶的ε'-Renyi差分隐私，它也满足常规差分隐私(ε, δ)，如下所示：\n\n    .. math::\n        (ε'+\\frac{log(1/δ)}{α-1}, δ)\n\n    详情请查看： `教程 <https://mindspore.cn/mindarmour/docs/zh-CN/master/protect_user_privacy_with_differential_privacy.html#%E5%B7%AE%E5%88%86%E9%9A%90%E7%A7%81>`_。\n\n    参考文献： `Rényi Differential Privacy of the Sampled Gaussian Mechanism <https://arxiv.org/abs/1908.10530>`_。\n\n    参数：\n        - **num_samples** (int) - 训练数据集中的样本总数。\n        - **batch_size** (int) - 训练时批处理中的样本数。\n        - **initial_noise_multiplier** (Union[float, int]) - 高斯噪声标准偏差除以norm_bound的比率，将用于计算隐私预算。默认值：``1.5``。\n        - **max_eps** (Union[float, int, None]) - DP训练的最大可接受epsilon预算，用于估计最大训练epoch。``None`` 表示epsilon预算没有限制。默认值：``10.0``。\n        - **target_delta** (Union[float, int, None]) - DP训练的目标delta预算。如果 `target_delta` 设置为 ``δ``，则隐私预算 ``δ`` 将在整个训练过程中是固定的。默认值：``1e-3``。\n        - **max_delta** (Union[float, int, None]) - DP训练的最大可接受delta预算，用于估计最大训练epoch。 `max_delta` 必须小于1，建议小于1e-3，否则会溢出。``None`` 表示delta预算没有限制。默认值：``None``。\n        - **target_eps** (Union[float, int, None]) - DP训练的目标epsilon预算。如果 `target_eps` 设置为 ``ε``，则隐私预算 ``ε`` 将在整个训练过程中是固定的。默认值：``None``。\n        - **orders** (Union[None, list[int, float]]) - 用于计算rdp的有限阶数，必须大于1。不同阶的隐私预算计算结果会有所不同。为了获得更严格（更小）的隐私预算估计，可以尝试阶列表。默认值：``None``。\n        - **noise_decay_mode** (Union[None, str]) - 训练时添加噪音的衰减模式，可以是 ``None``、``'Time'``、``'Step'``、``'Exp'``。默认值：``'Time'``。\n        - **noise_decay_rate** (float) - 训练时噪音的衰变率。默认值：``6e-4``。\n        - **per_print_times** (int) - 计算和打印隐私预算的间隔步数。默认值：``50``。\n        - **dataset_sink_mode** (bool) - 如果为 ``True``，所有训练数据都将一次性传递到设备（Ascend）。如果为 ``False``，则训练数据将在每步训练后传递到设备。默认值：``False``。\n\n    .. py:method:: max_epoch_suggest()\n\n        估计最大训练epoch，以满足预定义的隐私预算。\n\n        返回：\n            - **int** - 建议的最大训练epoch。\n\n    .. py:method:: step_end(run_context)\n\n        在每个训练步骤后计算隐私预算。\n\n        参数：\n            - **run_context** (RunContext) - 包含模型的一些信息。\n\n.. py:class:: mindarmour.privacy.diff_privacy.ZCDPMonitor(num_samples, batch_size, initial_noise_multiplier=1.5, max_eps=10.0, target_delta=1e-3, noise_decay_mode='Time', noise_decay_rate=6e-4, per_print_times=50, dataset_sink_mode=False)\n\n    基于零集中差分隐私（zCDP）理论，计算DP训练的隐私预算。根据下面的参考文献，如果随机化机制满足ρ-zCDP机制，它也满足传统的差分隐私（ε, δ），如下所示：\n\n    .. math::\n        (ρ+２\\sqrt{ρ*log(1/δ)}, δ)\n\n    注意，ZCDPMonitor不适合子采样噪声机制（如NoiseAdaGaussianRandom和NoiseGaussianRandom）。未来将开发zCDP的匹配噪声机制。\n\n    详情请查看：`教程 <https://mindspore.cn/mindarmour/docs/zh-CN/master/protect_user_privacy_with_differential_privacy.html#%E5%B7%AE%E5%88%86%E9%9A%90%E7%A7%81>`_。\n\n    参考文献：`Concentrated Differentially Private Gradient Descent with Adaptive per-Iteration Privacy Budget <https://arxiv.org/abs/1808.09501>`_。\n\n    参数：\n        - **num_samples** (int) - 训练数据集中的样本总数。\n        - **batch_size** (int) - 训练时批处理中的样本数。\n        - **initial_noise_multiplier** (Union[float, int]) - 高斯噪声标准偏差除以norm_bound的比率，将用于计算隐私预算。默认值：``1.5``。\n        - **max_eps** (Union[float, int]) - DP训练的最大可接受epsilon预算，用于估计最大训练epoch。默认值：``10.0``。\n        - **target_delta** (Union[float, int]) - DP训练的目标delta预算。如果 `target_delta` 设置为 ``δ``，则隐私预算 `δ` 将在整个训练过程中是固定的。默认值：``1e-3``。\n        - **noise_decay_mode** (Union[None, str]) - 训练时添加噪音的衰减模式，可以是 ``None``、``'Time'``、``'Step'``、``'Exp'``。默认值：``'Time'``。\n        - **noise_decay_rate** (float) - 训练时噪音的衰变率。默认值：``6e-4``。\n        - **per_print_times** (int) - 计算和打印隐私预算的间隔步数。默认值：``50``。\n        - **dataset_sink_mode** (bool) - 如果为 ``True``，所有训练数据都将一次性传递到设备（Ascend）。如果为 ``False``，则训练数据将在每步训练后传递到设备。默认值：``False``。\n\n    .. py:method:: max_epoch_suggest()\n\n        估计最大训练epoch，以满足预定义的隐私预算。\n\n        返回：\n            - **int** - 建议的最大训练epoch。\n\n    .. py:method:: step_end(run_context)\n\n        在每个训练步骤后计算隐私预算。\n\n        参数：\n            - **run_context** (RunContext) - 包含模型的一些信息。\n\n.. py:class:: mindarmour.privacy.diff_privacy.DPOptimizerClassFactory(micro_batches=2)\n\n    优化器的工厂类。\n\n    参数：\n        - **micro_batches** (int) - 从原始批次拆分的小批次中的样本数量。默认值：``2``。\n\n    返回：\n        - **Optimizer** - 优化器类。\n\n    .. py:method:: create(policy)\n\n        创建DP优化器。策略可以是 ``'sgd'``、``'momentum'``、``'adam'``。\n\n        参数：\n            - **policy** (str) - 选择原始优化器类型。\n\n        返回：\n            - **Optimizer** - 一个带有差分加噪的优化器。\n\n    .. py:method:: set_mechanisms(policy, *args, **kwargs)\n\n        获取噪音机制对象。策略可以是 ``'Gaussian'`` 或 ``'AdaGaussian'``。候选的args和kwargs可以在 `NoiseMechanismsFactory` 类中看到。\n\n        参数：\n            - **policy** (str) - 选择机制类型。\n\n.. py:class:: mindarmour.privacy.diff_privacy.DPModel(micro_batches=2, norm_bound=1.0, noise_mech=None, clip_mech=None, optimizer=nn.Momentum, **kwargs)\n\n    DPModel用于构建差分隐私训练的模型。\n    \n    这个类重载自 `mindspore.train.Model` 。\n\n    详情请查看： `教程 <https://mindspore.cn/mindarmour/docs/zh-CN/master/protect_user_privacy_with_differential_privacy.html#%E5%B7%AE%E5%88%86%E9%9A%90%E7%A7%81>`_。\n\n    参数：\n        - **micro_batches** (int) - 从原始批次拆分的小批次数。默认值：``2``。\n        - **norm_bound** (float) - 用于裁剪范围，如果设置为 ``1.0``，将返回原始数据。默认值：``1.0``。\n        - **noise_mech** (Mechanisms) - 用于生成不同类型的噪音。默认值：``None``。\n        - **clip_mech** (Mechanisms) - 用于更新自适应剪裁。默认值：``None``。\n        - **optimizer** (Cell) - 用于更新差分隐私训练过程中的模型权重值。默认值：``nn.Momentum``。\n\n    异常：\n        - **ValueError** - `optimizer` 值为 ``None``。\n        - **ValueError** - `optimizer` 不是DPOptimizer，且 `noise_mech` 为 ``None``。\n        - **ValueError** - `optimizer` 是DPOptimizer，且 `noise_mech` 非 ``None``。\n        - **ValueError** - `noise_mech` 或DPOptimizer的mech方法是自适应的，而 `clip_mech` 不是 ``None``。\n"
  },
  {
    "path": "docs/api/api_python/mindarmour.privacy.evaluation.rst",
    "content": "mindarmour.privacy.evaluation\n=============================\n\n本模块提供了一些评估给定模型隐私泄露风险的方法。\n\n.. py:class:: mindarmour.privacy.evaluation.MembershipInference(model, n_jobs=-1)\n\n    成员推理是由Shokri、Stronati、Song和Shmatikov提出的一种用于推断用户隐私数据的灰盒攻击。它需要训练样本的loss或logits结果，隐私是指单个用户的一些敏感属性。\n\n    有关详细信息，请参见： `教程 <https://mindspore.cn/mindarmour/docs/zh-CN/master/test_model_security_membership_inference.html>`_。\n\n    参考文献：`Reza Shokri, Marco Stronati, Congzheng Song, Vitaly Shmatikov. Membership Inference Attacks against Machine Learning Models. 2017. <https://arxiv.org/abs/1610.05820v2>`_。\n\n    参数：\n        - **model** (Model) - 目标模型。\n        - **n_jobs** (int) - 并行运行的任务数量。``-1`` 表示使用所有处理器，否则 `n_jobs` 的值必须为正整数。\n\n    异常：\n        - **TypeError** - 模型的类型不是 `mindspore.train.Model` 。\n        - **TypeError** - `n_jobs` 的类型不是int。\n        - **ValueError** - `n_jobs` 的值既不是 ``-1``，也不是正整数。\n\n    .. py:method:: eval(dataset_train, dataset_test, metrics)\n\n        评估目标模型的隐私泄露程度。\n        评估指标应由metrics规定。\n\n        参数：\n            - **dataset_train** (mindspore.dataset) - 目标模型的训练数据集。\n            - **dataset_test** (mindspore.dataset) - 目标模型的测试数据集。\n            - **metrics** (Union[list, tuple]) - 评估指标。指标的值必须为 ``\"precision\"``、``\"accuracy\"`` 或 ``\"recall\"``。默认值：``\"precision\"``。\n\n        返回：\n            - **list** - 每个元素都包含攻击模型的评估指标。\n\n    .. py:method:: train(dataset_train, dataset_test, attack_config)\n\n        根据配置，使用输入数据集训练攻击模型。\n\n        参数：\n            - **dataset_train** (mindspore.dataset) - 目标模型的训练数据集。\n            - **dataset_test** (mindspore.dataset) - 目标模型的测试集。\n            - **attack_config** (Union[list, tuple]) - 攻击模型的参数设置。格式为\n\n              .. code-block:: python\n\n                  attack_config =\n                      [{\"method\": \"knn\", \"params\": {\"n_neighbors\": [3, 5, 7]}},\n                       {\"method\": \"lr\", \"params\": {\"C\": np.logspace(-4, 2, 10)}}]\n\n              - 支持的方法有 ``knn``、``lr``、``mlp`` 和 ``rf``，每个方法的参数必须在可变参数的范围内。参数实现的提示可在下面找到：\n\n                - `KNN <https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html>`_\n                - `LR <https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html>`_\n                - `RF <https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html>`_\n                - `MLP <https://scikit-learn.org/stable/modules/generated/sklearn.neural_network.MLPRegressor.html>`_\n\n        异常：\n            - **KeyError** - `attack_config` 中的配置没有键{\"method\", \"params\"}。\n            - **NameError** - `attack_config` 中的方法（不区分大小写）不为 ``\"lr\"``、``\"knn\"``、``\"rf\"`` 或 ``\"mlp\"``。\n\n.. py:class:: mindarmour.privacy.evaluation.ImageInversionAttack(network, input_shape, input_bound, loss_weights=(1, 0.2, 5))\n\n    一种通过还原图像的深层表达来重建图像的攻击方法。\n\n    参考文献：`Aravindh Mahendran, Andrea Vedaldi. Understanding Deep Image Representations by Inverting Them. 2014. <https://arxiv.org/pdf/1412.0035.pdf>`_。\n\n    参数：\n        - **network** (Cell) - 网络，用于推断图像的深层特征。\n        - **input_shape** (tuple) - 单个网络输入的数据形状，应与给定网络一致。形状的格式应为 :math:`(channel, image\\_width, image\\_height)` 。\n        - **input_bound** (Union[tuple, list]) - 原始图像的像素范围，应该像[minimum_pixel, maximum_pixel]或(minimum_pixel, maximum_pixel)。\n        - **loss_weights** (Union[list, tuple]) - InversionLoss中三个子损失的权重，可以调整以获得更好的结果。默认值：``(1, 0.2, 5)``。\n\n    异常：\n        - **TypeError** - 网络类型不是Cell。\n        - **ValueError** - `input_shape` 的值有非正整数。\n        - **ValueError** - `loss_weights` 的值有非正数。\n\n    .. py:method:: evaluate(original_images, inversion_images, labels=None, new_network=None)\n\n        通过三个指标评估还原图像的质量：原始图像和还原图像之间的平均L2距离和SSIM值，以及新模型对还原图像的推理结果在真实标签上的置信度平均值。\n\n        参数：\n            - **original_images** (numpy.ndarray) - 原始图像，其形状应为 :math:`(img\\_num, channels, img\\_width, img\\_height)` 。\n            - **inversion_images** (numpy.ndarray) - 还原图像，其形状应为 :math:`(img\\_num, channels, img\\_width, img\\_height)` 。\n            - **labels** (numpy.ndarray) - 原始图像的ground truth标签。默认值：``None``。\n            - **new_network** (Cell) - 其结构包含self._network中所有网络，但加载了不同的模型文件。默认值：``None``。\n\n        返回：\n            - **float** - l2距离。\n            - **float** - 平均ssim值。\n            - **Union[float, None]** - 平均置信度。如果 `labels` 或 `new_network` 为 ``None``，则该值为 ``None``。\n\n    .. py:method:: generate(target_features, iters=100)\n\n        根据 `target_features` 重建图像。\n\n        参数：\n            - **target_features** (numpy.ndarray) - 原始图像的深度表示。 `target_features` 的第一个维度应该是img_num。需要注意的是，如果img_num等于1，则 `target_features` 的shape应该是 :math:`(1, dim2, dim3, ...)` 。\n            - **iters** (int) - 逆向攻击的迭代次数，应为正整数。默认值：``1.0``。\n\n        返回：\n            - **numpy.ndarray** - 重建图像，预计与原始图像相似。\n\n        异常：\n            - **TypeError** - `target_features` 的类型不是numpy.ndarray。\n            - **ValueError** - `iters` 的值都不是正整数.\n\n"
  },
  {
    "path": "docs/api/api_python/mindarmour.privacy.sup_privacy.rst",
    "content": "mindarmour.privacy.sup_privacy\n==============================\n\n本模块提供抑制隐私功能，以保护用户隐私。\n\n.. py:class:: mindarmour.privacy.sup_privacy.SuppressMasker(model, suppress_ctrl)\n\n    周期性检查抑制隐私功能状态和切换（启动/关闭）抑制操作。\n\n    详情请查看： `应用抑制隐私机制保护用户隐私\n    <https://mindspore.cn/mindarmour/docs/zh-CN/master/protect_user_privacy_with_suppress_privacy.html#%E5%BC%95%E5%85%A5%E6%8A%91%E5%88%B6%E9%9A%90%E7%A7%81%E8%AE%AD%E7%BB%83>`_。\n\n    参数：\n        - **model** (SuppressModel) - SuppressModel 实例。\n        - **suppress_ctrl** (SuppressCtrl) - SuppressCtrl 实例。\n\n    .. py:method:: step_end(run_context)\n\n        更新用于抑制模型实例的掩码矩阵张量。\n\n        参数：\n            - **run_context** (RunContext) - 包含模型的一些信息。\n\n.. py:class:: mindarmour.privacy.sup_privacy.SuppressModel(network, loss_fn, optimizer, **kwargs)\n\n    抑制隐私训练器，重载自 `mindspore.train.Model` 。\n\n    有关详细信息，请查看： `应用抑制隐私机制保护用户隐私 <https://mindspore.cn/mindarmour/docs/zh-CN/master/protect_user_privacy_with_suppress_privacy.html#%E5%BC%95%E5%85%A5%E6%8A%91%E5%88%B6%E9%9A%90%E7%A7%81%E8%AE%AD%E7%BB%83>`_。\n\n    参数：\n        - **network** (Cell) - 要训练的神经网络模型。\n        - **loss_fn** (Cell) - 优化器的损失函数。\n        - **optimizer** (Optimizer) - 优化器实例。\n        - **kwargs** - 创建抑制模型时使用的关键字参数。\n\n    .. py:method:: link_suppress_ctrl(suppress_pri_ctrl)\n\n        SuppressCtrl实例关联到SuppressModel实例。\n\n        参数：\n            - **suppress_pri_ctrl** (SuppressCtrl) - SuppressCtrl实例。\n\n.. py:class:: mindarmour.privacy.sup_privacy.SuppressPrivacyFactory\n\n    SuppressCtrl机制的工厂类。\n\n    详情请查看： `应用抑制隐私机制保护用户隐私 <https://mindspore.cn/mindarmour/docs/zh-CN/master/protect_user_privacy_with_suppress_privacy.html#%E5%BC%95%E5%85%A5%E6%8A%91%E5%88%B6%E9%9A%90%E7%A7%81%E8%AE%AD%E7%BB%83>`_。\n\n    .. py:method:: create(networks, mask_layers, policy='local_train', end_epoch=10, batch_num=20, start_epoch=3, mask_times=1000, lr=0.05, sparse_end=0.90, sparse_start=0.0)\n        :abstractmethod:\n\n        参数：\n            - **networks** (Cell) - 要训练的神经网络模型。此网络参数应与SuppressModel()的'network'参数相同。\n            - **mask_layers** (list) - 需要抑制的训练网络层的描述。\n            - **policy** (str) - 抑制隐私训练的训练策略。默认值： ``\"local_train\"``，表示本地训练。\n            - **end_epoch** (int) - 最后一次抑制操作对应的epoch序号，0<start_epoch<=end_epoch<=100。默认值：``10``。此参数应与 `mindspore.train.model.train()` 的 `epoch` 参数相同。\n            - **batch_num** (int) - 一个epoch中批次的数量，应等于num_samples/batch_size。默认值：``20``。\n            - **start_epoch** (int) - 第一个抑制操作对应的epoch序号，0<start_epoch<=end_epoch<=100。默认值：``3``。\n            - **mask_times** (int) - 抑制操作的数量。默认值：``1000``。\n            - **lr** (Union[float, int]) - 学习率，在训练期间应保持不变。0<lr<=0.50. 默认值：0.05。此lr参数应与 `mindspore.nn.SGD()` 的 `learning_rate` 参数相同。\n            - **sparse_end** (float) - 要到达的稀疏性，0.0<=sparse_start<sparse_end<1.0。默认值：``0.90``。\n            - **sparse_start** (Union[float, int]) - 抑制操作启动时对应的稀疏性，0.0<=sparse_start<sparse_end<1.0。默认值：``0.0``。\n\n        返回：\n            - **SuppressCtrl** - 抑制隐私机制的类。\n\n.. py:class:: mindarmour.privacy.sup_privacy.SuppressCtrl(networks, mask_layers, end_epoch, batch_num, start_epoch, mask_times, lr, sparse_end, sparse_start)\n\n    完成抑制隐私操作，包括计算抑制比例，找到应该抑制的参数，并永久抑制这些参数。\n\n    详情请查看： `应用抑制隐私机制保护用户隐私 <https://mindspore.cn/mindarmour/docs/zh-CN/master/protect_user_privacy_with_suppress_privacy.html#%E5%BC%95%E5%85%A5%E6%8A%91%E5%88%B6%E9%9A%90%E7%A7%81%E8%AE%AD%E7%BB%83>`_。\n\n    参数：\n        - **networks** (Cell) - 要训练的神经网络模型。\n        - **mask_layers** (list) - 需要抑制的层的描述。\n        - **end_epoch** (int) - 最后一次抑制操作对应的epoch序号。\n        - **batch_num** (int) - 一个epoch中的batch数量。\n        - **start_epoch** (int) - 第一个抑制操作对应的epoch序号。\n        - **mask_times** (int) - 抑制操作的数量。\n        - **lr** (Union[float, int]) - 学习率。\n        - **sparse_end** (float) - 要到达的稀疏性。\n        - **sparse_start** (Union[float, int]) - 要启动的稀疏性。\n\n    .. py:method:: calc_actual_sparse_for_conv(networks)\n\n        计算con1层和con2层的网络稀疏性。\n\n        参数：\n            - **networks** (Cell) - 要训练的神经网络模型。\n\n    .. py:method:: calc_actual_sparse_for_fc1(networks)\n\n        计算全连接1层的实际稀疏\n\n        参数：\n            - **networks** (Cell) - 要训练的神经网络模型。\n\n    .. py:method:: calc_actual_sparse_for_layer(networks, layer_name)\n\n        计算一个网络层的实际稀疏性\n\n        参数：\n            - **networks** (Cell) - 要训练的神经网络模型。\n            - **layer_name** (str) - 目标层的名称。\n\n    .. py:method:: calc_theoretical_sparse_for_conv()\n\n        计算卷积层的掩码矩阵的实际稀疏性。\n\n    .. py:method:: print_paras()\n\n        显示参数信息\n\n    .. py:method:: reset_zeros()\n\n        将用于加法运算的掩码数组设置为0。\n\n    .. py:method:: update_mask(networks, cur_step, target_sparse=0.0)\n\n        对整个模型的用于加法运算和乘法运算的掩码数组进行更新。\n\n        参数：\n            - **networks** (Cell) - 训练网络。\n            - **cur_step** (int) - 整个训练过程的当前epoch。\n            - **target_sparse** (float) - 要到达的稀疏性。默认值：``0.0``。\n\n    .. py:method:: update_mask_layer(weight_array_flat, sparse_weight_thd, sparse_stop_pos, weight_abs_max, layer_index)\n\n        对单层的用于加法运算和乘法运算的掩码数组进行更新。\n\n        参数：\n            - **weight_array_flat** (numpy.ndarray) - 层参数权重数组。\n            - **sparse_weight_thd** (float) - 绝对值小于该阈值的权重会被抑制。\n            - **sparse_stop_pos** (int) - 要抑制的最大元素数。\n            - **weight_abs_max** (float) - 权重的最大绝对值。\n            - **layer_index** (int) - 目标层的索引。\n\n    .. py:method:: update_mask_layer_approximity(weight_array_flat, weight_array_flat_abs, actual_stop_pos, layer_index)\n\n        对单层的用于加法运算和乘法运算的掩码数组进行更新。\n\n        禁用clipping lower、clipping、adding noise操作。\n\n        参数：\n            - **weight_array_flat** (numpy.ndarray) - 层参数权重数组。\n            - **weight_array_flat_abs** (numpy.ndarray) - 层参数权重的绝对值的数组。\n            - **actual_stop_pos** (int) - 应隐藏实际参数编号。\n            - **layer_index** (int) - 目标层的索引。\n\n    .. py:method:: update_status(cur_epoch, cur_step, cur_step_in_epoch)\n\n        更新抑制操作状态。\n\n        参数：\n            - **cur_epoch** (int) - 整个训练过程的当前epoch。\n            - **cur_step** (int) - 整个训练过程的当前步骤。\n            - **cur_step_in_epoch** (int) - 当前epoch的当前步骤。\n\n.. py:class:: mindarmour.privacy.sup_privacy.MaskLayerDes(layer_name, grad_idx, is_add_noise, is_lower_clip, min_num, upper_bound=1.20)\n\n    对抑制目标层的描述。\n\n    参数：\n        - **layer_name** (str) - 层名称，如下获取一个层的名称：\n\n          .. code-block::\n\n              for layer in networks.get_parameters(expand=True):\n                  if layer.name == \"conv\": ...\n\n        - **grad_idx** (int) - 掩码层在梯度元组中的索引。可参考 `model.py <https://gitee.com/mindspore/mindarmour/blob/master/mindarmour/privacy/sup_privacy/train/model.py>`_ 中TrainOneStepCell的构造函数，在PYNATIVE_MODE模式下打印某些层的索引值。\n        - **is_add_noise** (bool) - 如果为 ``True``，则此层的权重可以添加噪声。如果为 ``False``，则此层的权重不能添加噪声。如果参数num大于100000，则　`is_add_noise` 无效。\n        - **is_lower_clip** (bool) - 如果为 ``True``，则此层的权重将被剪裁到大于下限值。如果为 ``False``，此层的权重不会被要求大于下限制。如果参数num大于100000，则 `is_lower_clip` 无效。\n        - **min_num** (int) - 未抑制的剩余权重数。如果 `min_num` 小于（参数总数量 *　`SupperssCtrl.sparse_end` ），则 `min_num` 无效。\n        - **upper_bound** (Union[float, int]) - 此层权重的最大abs值，默认值：``1.20``。如果参数num大于100000，则 `upper_bound` 无效。\n\n"
  },
  {
    "path": "docs/api/api_python/mindarmour.reliability.rst",
    "content": "mindarmour.reliability\n======================\n\nMindArmour的可靠性方法。\n\n.. py:class:: mindarmour.reliability.FaultInjector(model, fi_type=None, fi_mode=None, fi_size=None)\n\n    故障注入模块模拟深度神经网络的各种故障场景，并评估模型的性能和可靠性。\n\n    详情请查看 `实现模型故障注入评估模型容错性 <https://mindspore.cn/mindarmour/docs/zh-CN/master/fault_injection.html>`_。\n\n    参数：\n        - **model** (Model) - 需要评估模型。\n        - **fi_type** (list) - 故障注入的类型，包括 ``'bitflips_random'`` （随机翻转）、 ``'bitflips_designated'`` （翻转关键位）、 ``'random'``、 ``'zeros'``、 ``'nan'``、 ``'inf'``、 ``'anti_activation'``、 ``'precision_loss'`` 等。\n        - **fi_mode** (list) - 故障注入的模式。可选值： ``'single_layer'``、 ``'all_layer'`` 。\n        - **fi_size** (list) - 故障注入的次数，表示需要注入多少值。\n\n    .. py:method:: kick_off(ds_data, ds_label, iter_times=100)\n\n        启动故障注入并返回最终结果。\n\n        参数：\n            - **ds_data** (np.ndarray) - 输入测试数据。评估基于这些数据。\n            - **ds_label** (np.ndarray) - 数据的标签，对应于数据。\n            - **iter_times** (int) - 评估数，这将决定批处理大小。\n\n        返回：\n            - **list** - 故障注入的结果。\n\n    .. py:method:: metrics()\n\n        最终结果的指标。\n\n        返回：\n            - **list** - 结果总结。\n\n.. py:class:: mindarmour.reliability.ConceptDriftCheckTimeSeries(window_size=100, rolling_window=10, step=10, threshold_index=1.5, need_label=False)\n\n    概念漂移检查时间序列（ConceptDriftCheckTimeSeries）用于样本序列分布变化检测。\n\n    有关详细信息，请查看 `实现时序数据概念漂移检测应用\n    <https://mindspore.cn/mindarmour/docs/zh-CN/master/concept_drift_time_series.html>`_。\n\n    参数：\n        - **window_size** (int) - 概念窗口的大小，不小于10。如果给定输入数据， `window_size` 取值范围为[10, 1/3*len( `data` )]。\n          如果数据是周期性的，通常 `window_size` 等于2-5个周期。例如，对于月/周数据，30/7天的数据量是一个周期。默认值：``1.0``。\n        - **rolling_window** (int) - 平滑窗口大小，在[1, `window_size` ]中。默认值：``10``。\n        - **step** (int) - 滑动窗口的跳跃长度，取值范围为[1, `window_size` ]。默认值：``10``。\n        - **threshold_index** (float) - 阈值索引，:math:`(-\\infty, +\\infty)` 。默认值：``1.5``。\n        - **need_label** (bool) - 如果为 ``True``，则需要概念漂移标签。默认值：``False``。\n\n    .. py:method:: concept_check(data)\n\n        在数据序列中查找概念漂移位置。\n\n        参数：\n            - **data** (numpy.ndarray) - 输入数据。数据的shape可以是 :math:`(n,1)` 或 :math:`(n,m)`。\n              请注意，每列（m列）是一个数据序列。\n\n        返回：\n            - **numpy.ndarray** - 样本序列的概念漂移分数。\n            - **float** - 判断概念漂移的阈值。\n            - **list** - 概念漂移的位置。\n\n.. py:class:: mindarmour.reliability.OodDetector(model, ds_train)\n\n    分布外检测器的抽象类。\n\n    参数：\n        - **model** (Model) - 训练模型。\n        - **ds_train** (numpy.ndarray) - 训练数据集。\n\n    .. py:method:: get_optimal_threshold(label, ds_eval)\n\n        获取最佳阈值。尝试找到一个最佳阈值来检测OOD样本。最佳阈值由标记的数据集 `ds_eval` 计算。\n\n        参数：\n            - **label** (numpy.ndarray) - 区分图像是否为分布内或分布外的标签。\n            - **ds_eval** (numpy.ndarray) - 帮助查找阈值的测试数据集。\n\n        返回：\n            - **float** - 最佳阈值。\n\n    .. py:method:: ood_predict(threshold, ds_test)\n\n        分布外（out-of-distribution，OOD）检测。此函数的目的是检测被视为 `ds_test` 的图像是否为OOD样本。如果一张图像的预测分数大于 `threshold` ，则该图像为分布外。\n\n        参数：\n            - **threshold** (float) - 判断ood数据的阈值。可以根据经验设置值，也可以使用函数get_optimal_threshold。\n            - **ds_test** (numpy.ndarray) - 测试数据集。\n\n        返回：\n            - **numpy.ndarray** - 检测结果。``0`` 表示数据不是ood，``1`` 表示数据是ood。\n\n.. py:class:: mindarmour.reliability.OodDetectorFeatureCluster(model, ds_train, n_cluster, layer)\n\n    训练OOD检测器。提取训练数据特征，得到聚类中心。测试数据特征与聚类中心之间的距离确定图像是否为分布外（OOD）图像。\n\n    有关详细信息，请查看 `实现图像数据概念漂移检测应用 <https://mindspore.cn/mindarmour/docs/zh-CN/master/concept_drift_images.html>`_。\n\n    参数：\n        - **model** (Model) - 训练模型。\n        - **ds_train** (numpy.ndarray) - 训练数据集。\n        - **n_cluster** (int) - 聚类数量。取值属于[2,100]。\n          通常，`n_cluster` 等于训练数据集的类号。如果OOD检测器在测试数据集中性能较差，我们可以适当增加 `n_cluster` 的值。\n        - **layer** (str) - 特征层的名称。layer (str)由'name[:Tensor]'表示，其中'name'由用户在训练模型时给出。\n          请查看有关如何在'README.md'中命名模型层的更多详细信息。\n\n    .. py:method:: get_optimal_threshold(label, ds_eval)\n\n        获取最佳阈值。尝试找到一个最佳阈值来检测OOD样本。最佳阈值由标记的数据集 `ds_eval` 计算。\n\n        参数：\n            - **label** (numpy.ndarray) - 区分图像是否为分布内或分布外的标签。\n            - **ds_eval** (numpy.ndarray) - 帮助查找阈值的测试数据集。\n\n        返回：\n            - **float** - 最佳阈值。\n\n    .. py:method:: ood_predict(threshold, ds_test)\n\n        分布外（out-of-distribution，OOD）检测。此函数的目的是检测 `ds_test` 中的图像是否为OOD样本。如果一张图像的预测分数大于 `threshold` ，则该图像为分布外。\n\n        参数：\n            - **threshold** (float) - 判断ood数据的阈值。可以根据经验设置值，也可以使用函数get_optimal_threshold。\n            - **ds_test** (numpy.ndarray) - 测试数据集。\n\n        返回：\n            - **numpy.ndarray** - 检测结果。``0`` 表示数据不是ood，``1`` 表示数据是ood。\n"
  },
  {
    "path": "docs/api/api_python/mindarmour.rst",
    "content": "mindarmour\n==========\n\nMindArmour是MindSpore的工具箱，用于增强模型可信，实现隐私保护机器学习。\n\n.. py:class:: mindarmour.Attack\n\n    所有通过创建对抗样本的攻击类的抽象基类。\n\n    对抗样本是通过向原始样本添加对抗噪声来生成的。\n\n    .. py:method:: batch_generate(inputs, labels, batch_size=64)\n\n        根据输入样本及其标签来批量生成对抗样本。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, tuple]) - 生成对抗样本的原始样本。\n            - **labels** (Union[numpy.ndarray, tuple]) - 原始/目标标签。若每个输入有多个标签，将它包装在元组中。\n            - **batch_size** (int) - 一个批次中的样本数。默认值：``64``。\n\n        返回：\n            - **numpy.ndarray** - 生成的对抗样本。\n\n    .. py:method:: generate(inputs, labels)\n        :abstractmethod:\n\n        根据正常样本及其标签生成对抗样本。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, tuple]) - 生成对抗样本的原始样本。\n            - **labels** (Union[numpy.ndarray, tuple]) - 原始/目标标签。若每个输入有多个标签，将它包装在元组中。\n\n        异常：\n            - **NotImplementedError** - 此为抽象方法。\n\n.. py:class:: mindarmour.BlackModel\n\n    将目标模型视为黑盒的抽象类。模型应由用户定义。\n\n    .. py:method:: is_adversarial(data, label, is_targeted)\n\n        检查输入样本是否为对抗样本。\n\n        参数：\n            - **data** (numpy.ndarray) - 要检查的输入样本，通常是一些恶意干扰的样本。\n            - **label** (numpy.ndarray) - 对于目标攻击，标签是受扰动样本的预期标签。对于无目标攻击，标签是相应未扰动样本的原始标签。\n            - **is_targeted** (bool) - 对于有目标/无目标攻击，请选择 ``True`` / ``False``。\n\n        返回：\n            bool。\n            \n            - 如果为 ``True``，则输入样本是对抗性的。\n\n            - 如果为 ``False``，则输入样本不是对抗性的。\n\n    .. py:method:: predict(inputs)\n        :abstractmethod:\n\n        使用用户指定的模型进行预测。预测结果的shape应该是 :math:`(m, n)`，其中n表示此模型分类的类数。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 要预测的输入样本。\n\n        异常：\n            - **NotImplementedError** - 抽象方法未实现。\n\n.. py:class:: mindarmour.Detector\n\n    所有对抗样本检测器的抽象基类。\n\n    .. py:method:: detect(inputs)\n        :abstractmethod:\n\n        从输入样本中检测对抗样本。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, list, tuple]) - 要检测的输入样本。\n\n        异常：\n            - **NotImplementedError** - 抽象方法未实现。\n\n    .. py:method:: detect_diff(inputs)\n        :abstractmethod:\n\n        计算输入样本和去噪样本之间的差值。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, list, tuple]) - 要检测的输入样本。\n\n        异常：\n            - **NotImplementedError** - 抽象方法未实现。\n\n    .. py:method:: fit(inputs, labels=None)\n        :abstractmethod:\n\n        拟合阈值，拒绝与去噪样本差异大于阈值的对抗样本。当应用于正常样本时，阈值由假正率决定。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 用于计算阈值的输入样本。\n            - **labels** (numpy.ndarray) - 训练数据的标签。默认值：``None``。\n\n        异常：\n            - **NotImplementedError** - 抽象方法未实现。\n\n    .. py:method:: transform(inputs)\n        :abstractmethod:\n\n        过滤输入样本中的对抗性噪声。\n\n        参数：\n            - **inputs** (Union[numpy.ndarray, list, tuple]) - 要转换的输入样本。\n\n        异常：\n            - **NotImplementedError** - 抽象方法未实现。\n\n.. py:class:: mindarmour.Defense(network)\n\n    所有防御类的抽象基类，用于防御对抗样本。\n\n    参数：\n        - **network** (Cell) - 要防御的MindSpore风格的深度学习模型。\n\n    .. py:method:: batch_defense(inputs, labels, batch_size=32, epochs=5)\n\n        对输入进行批量防御操作。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 生成对抗样本的原始样本。\n            - **labels** (numpy.ndarray) - 输入样本的标签。\n            - **batch_size** (int) - 一个批次中的样本数。默认值：``32``。\n            - **epochs** (int) - epochs的数量。默认值：``5``。\n\n        返回：\n            - **numpy.ndarray** - `batch_defense` 操作的损失。\n\n        异常：\n            - **ValueError** - `batch_size` 为 ``0``。\n\n    .. py:method:: defense(inputs, labels)\n        :abstractmethod:\n\n        对输入进行防御操作。\n\n        参数：\n            - **inputs** (numpy.ndarray) - 生成对抗样本的原始样本。\n            - **labels** (numpy.ndarray) - 输入样本的标签。\n\n        异常：\n            - **NotImplementedError** - 抽象方法未实现。\n"
  },
  {
    "path": "docs/api/api_python/mindarmour.utils.rst",
    "content": "mindarmour.utils\n================\n\nMindArmour的工具方法。\n\n.. py:class:: mindarmour.utils.LogUtil\n\n    日志记录模块。\n\n    在长期运行的脚本中记录随时间推移的日志统计信息。\n\n    异常：\n        - **SyntaxError** - 创建此类异常。\n\n    .. py:method:: add_handler(handler)\n\n        添加日志模块支持的其他处理程序。\n\n        参数：\n            - **handler** (logging.Handler) - 日志模块支持的其他处理程序。\n\n        异常：\n            - **ValueError** - 输入handler不是logging.Handler的实例。\n\n    .. py:method:: debug(tag, msg, *args)\n\n        记录'[tag] msg % args'，严重性为'DEBUG'。\n\n        参数：\n            - **tag** (str) - Logger标记。\n            - **msg** (str) - Logger消息。\n            - **args** (Any) - 辅助值。\n\n    .. py:method:: error(tag, msg, *args)\n\n        记录'[tag] msg % args'，严重性为'ERROR'。\n\n        参数：\n            - **tag** (str) - Logger标记。\n            - **msg** (str) - Logger消息。\n            - **args** (Any) - 辅助值。\n\n    .. py:method:: get_instance()\n        :abstractmethod:\n\n        获取类 `LogUtil` 的实例。\n\n        返回：\n            - **Object** - 类 `LogUtil` 的实例。\n\n    .. py:method:: info(tag, msg, *args)\n\n        记录'[tag] msg % args'，严重性为'INFO'。\n\n        参数：\n            - **tag** (str) - Logger标记。\n            - **msg** (str) - Logger消息。\n            - **args** (Any) - 辅助值。\n\n    .. py:method:: set_level(level)\n\n        设置此logger的日志级别，级别必须是整数或字符串。支持的级别为 ``'NOTSET'(integer: 0)``、``'ERROR'(integer: 1-40)``、``'WARNING'('WARN', integer: 1-30)``、``'INFO'(integer: 1-20)`` 以及 ``'DEBUG'(integer: 1-10)``。\n\n        例如，如果logger.set_level('WARNING')或logger.set_level(21)，则在运行时将打印脚本中的logger.warn()和logger.error()，而logger.info()或logger.debug()将不会打印。\n\n        参数：\n            - **level** (Union[int, str]) - logger的级别。\n\n    .. py:method:: warn(tag, msg, *args)\n\n        记录'[tag] msg % args'，严重性为'WARNING'。\n\n        参数：\n            - **tag** (str) - Logger标记。\n            - **msg** (str) - Logger消息。\n            - **args** (Any) - 辅助值。\n\n.. py:class:: mindarmour.utils.GradWrapWithLoss(network)\n\n    构造一个网络来计算输入空间中损失函数的梯度，并由 `weight` 加权。\n\n    参数：\n        - **network** (Cell) - 要包装的目标网络。\n\n    .. py:method:: construct(inputs, labels)\n\n        使用标签和权重计算 `inputs` 的梯度。\n\n        参数：\n            - **inputs** (Tensor) - 网络的输入。\n            - **labels** (Tensor) - 输入的标签。\n\n        返回：\n            - **Tensor** - 梯度矩阵。\n\n.. py:class:: mindarmour.utils.GradWrap(network)\n\n    构建一个网络，以计算输入空间中网络输出的梯度，并由 `weight` 加权，表示为雅可比矩阵。\n\n    参数：\n        - **network** (Cell) - 要包装的目标网络。\n\n    .. py:method:: construct(*data)\n\n        计算雅可比矩阵（jacobian matrix）。\n\n        参数：\n            - **data** (Tensor) - 数据由输入和权重组成。\n\n              - inputs: 网络的输入。\n              - weight: 每个梯度的权重，'weight'与'labels'的shape相同。\n\n        返回：\n            - **Tensor** - 雅可比矩阵。\n"
  },
  {
    "path": "docs/api/api_python_en/mindarmour.adv_robustness.attacks.rst",
    "content": "mindarmour.adv_robustness.attacks\n=================================\n\n.. automodule:: mindarmour.adv_robustness.attacks\n    :members:\n"
  },
  {
    "path": "docs/api/api_python_en/mindarmour.adv_robustness.defenses.rst",
    "content": "mindarmour.adv_robustness.defenses\n==================================\n\n.. automodule:: mindarmour.adv_robustness.defenses\n    :members:\n"
  },
  {
    "path": "docs/api/api_python_en/mindarmour.adv_robustness.detectors.rst",
    "content": "mindarmour.adv_robustness.detectors\n===================================\n\n.. automodule:: mindarmour.adv_robustness.detectors\n    :members:\n"
  },
  {
    "path": "docs/api/api_python_en/mindarmour.adv_robustness.evaluations.rst",
    "content": "mindarmour.adv_robustness.evaluations\n=====================================\n\n.. automodule:: mindarmour.adv_robustness.evaluations\n    :members:\n"
  },
  {
    "path": "docs/api/api_python_en/mindarmour.fuzz_testing.rst",
    "content": "mindarmour.fuzz_testing\n=======================\n\n.. automodule:: mindarmour.fuzz_testing\n    :members:\n"
  },
  {
    "path": "docs/api/api_python_en/mindarmour.natural_robustness.transform.image.rst",
    "content": "mindarmour.natural_robustness.transform.image\n=============================================\n\n.. automodule:: mindarmour.natural_robustness.transform.image\n    :members:"
  },
  {
    "path": "docs/api/api_python_en/mindarmour.privacy.diff_privacy.rst",
    "content": "mindarmour.privacy.diff_privacy\n===============================\n\n.. automodule:: mindarmour.privacy.diff_privacy\n    :members:\n"
  },
  {
    "path": "docs/api/api_python_en/mindarmour.privacy.evaluation.rst",
    "content": "mindarmour.privacy.evaluation\n=============================\n\n.. automodule:: mindarmour.privacy.evaluation\n    :members:\n"
  },
  {
    "path": "docs/api/api_python_en/mindarmour.privacy.sup_privacy.rst",
    "content": "mindarmour.privacy.sup_privacy\n===============================\n\n.. automodule:: mindarmour.privacy.sup_privacy\n    :members:\n"
  },
  {
    "path": "docs/api/api_python_en/mindarmour.reliability.rst",
    "content": "mindarmour.reliability\n======================\n\n.. automodule:: mindarmour.reliability\n    :members:\n"
  },
  {
    "path": "docs/api/api_python_en/mindarmour.rst",
    "content": "mindarmour\n==========\n\n.. automodule:: mindarmour\n    :members:\n    :exclude-members: SuppressModel, SuppressMasker, SuppressCtrl, Fuzzer, DPModel, MembershipInference, ImageInversionAttack, ConceptDriftCheckTimeSeries"
  },
  {
    "path": "docs/api/api_python_en/mindarmour.utils.rst",
    "content": "mindarmour.utils\n================\n\n.. automodule:: mindarmour.utils\n    :members:"
  },
  {
    "path": "examples/README.md",
    "content": "# Examples\n\n## Introduction\n\nThis package includes application demos for all developed tools of MindArmour. Through these demos, you will soon\n master those tools of MindArmour. Let's Start!\n\n## Preparation\n\nMost of those demos are implemented based on LeNet5 and MNIST dataset. As a preparation, we should download MNIST and\n train a LeNet5 model first.\n\n### 1. download dataset\n\nThe MNIST database of handwritten digits has a training set of 60,000 examples, and a test set of 10,000 examples\n. It is a subset of a larger set available from MNIST. The digits have been size-normalized and centered in a fixed-size image.\n\n```sh\ncd examples/common/dataset\nmkdir MNIST\ncd MNIST\nmkdir train\nmkdir test\ncd train\nwget \"http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz\"\nwget \"http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz\"\ngzip train-images-idx3-ubyte.gz -d\ngzip train-labels-idx1-ubyte.gz -d\ncd ../test\nwget \"http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz\"\nwget \"http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz\"\ngzip t10k-images-idx3-ubyte.gz -d\ngzip t10k-labels-idx1-ubyte.gz -d\n```\n\n### 2. trian LeNet5 model\n\nAfter training the network, you will obtain a group of ckpt files. Those ckpt files save the trained model parameters\n of LeNet5, which can be used in 'examples/ai_fuzzer' and 'examples/model_security'.\n\n```sh\ncd examples/common/networks/lenet5\npython mnist_train.py\n\n```\n"
  },
  {
    "path": "examples/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis package includes real application examples for developed features of MindArmour.\n\"\"\"\n"
  },
  {
    "path": "examples/ai_fuzzer/README.md",
    "content": "# Application demos of model fuzzing\n\n## Introduction\n\nThe same as the traditional software fuzz testing, we can also design fuzz test for AI models. Compared to\n branch coverage or line coverage of traditional software, some people propose the\n  concept of 'neuron coverage' based on the unique structure of deep neural network. We can use the neuron coverage\n   as a guide to search more metamorphic inputs to test our models.\n\n## 1. calculation of neuron coverage\n\nThere are five metrics proposed for evaluating the neuron coverage of a test:NC, Effective NC, KMNC, NBC and SNAC.\n Usually we need to feed all the training dataset into the model first, and record the output range of all neurons\n  (however, in KMNC, NBC and SNAC, only the last layer of neurons are recorded in our method). In the testing phase,\n   we feed test samples into the model, and calculate those three metrics mentioned above according to those neurons'\n    output distribution.\n\n```sh\ncd examples/ai_fuzzer/\npython lenet5_mnist_coverage.py\n```\n\n## 2. fuzz test for AI model\n\nWe have provided several types of methods for manipulating metamorphic inputs: affine transformation, pixel\n transformation and adversarial attacks. Usually we feed the original samples into the fuzz function as seeds, and\n  then metamorphic samples are generated through iterative manipulations.\n\n```sh\ncd examples/ai_fuzzer/\npython lenet5_mnist_fuzzing.py\n```"
  },
  {
    "path": "examples/ai_fuzzer/__init__.py",
    "content": ""
  },
  {
    "path": "examples/ai_fuzzer/fuzz_testing_and_model_enhense.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nAn example of fuzz testing and then enhance non-robustness model.\n\"\"\"\nimport random\nimport numpy as np\n\nimport mindspore\nfrom mindspore import Model\nfrom mindspore import context\nfrom mindspore import Tensor\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nfrom mindspore.nn import SoftmaxCrossEntropyWithLogits\nfrom mindspore.nn.optim.momentum import Momentum\n\nfrom mindarmour.adv_robustness.defenses import AdversarialDefense\nfrom mindarmour.fuzz_testing import Fuzzer\nfrom mindarmour.fuzz_testing import KMultisectionNeuronCoverage\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\nfrom examples.common.networks.lenet5.lenet5_net_for_fuzzing import LeNet5\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Fuzz_testing and enhance model'\nLOGGER.set_level('INFO')\n\n\ndef split_dataset(image, label, proportion):\n    \"\"\"\n    Split the generated fuzz data into train and test set.\n    \"\"\"\n    indices = np.arange(len(image))\n    random.shuffle(indices)\n    train_length = int(len(image) * proportion)\n    train_image = [image[i] for i in indices[:train_length]]\n    train_label = [label[i] for i in indices[:train_length]]\n    test_image = [image[i] for i in indices[:train_length]]\n    test_label = [label[i] for i in indices[:train_length]]\n    return train_image, train_label, test_image, test_label\n\n\ndef example_lenet_mnist_fuzzing():\n    \"\"\"\n    An example of fuzz testing and then enhance the non-robustness model.\n    \"\"\"\n    # upload trained network\n    ckpt_path = '../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n    model = Model(net)\n    mutate_config = [\n        {'method': 'GaussianBlur',\n         'params': {'ksize': [1, 2, 3, 5], 'auto_param': [True, False]}},\n        {'method': 'MotionBlur',\n         'params': {'degree': [1, 2, 5], 'angle': [45, 10, 100, 140, 210, 270, 300], 'auto_param': [True]}},\n        {'method': 'GradientBlur',\n         'params': {'point': [[10, 10]], 'auto_param': [True]}},\n        {'method': 'UniformNoise',\n         'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n        {'method': 'GaussianNoise',\n         'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n        {'method': 'SaltAndPepperNoise',\n         'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n        {'method': 'NaturalNoise',\n         'params': {'ratio': [0.1], 'k_x_range': [(1, 3), (1, 5)], 'k_y_range': [(1, 5)], 'auto_param': [False, True]}},\n        {'method': 'Contrast',\n         'params': {'alpha': [0.5, 1, 1.5], 'beta': [-10, 0, 10], 'auto_param': [False, True]}},\n        {'method': 'GradientLuminance',\n         'params': {'color_start': [(0, 0, 0)], 'color_end': [(255, 255, 255)], 'start_point': [(10, 10)],\n                    'scope': [0.5], 'pattern': ['light'], 'bright_rate': [0.3], 'mode': ['circle'],\n                    'auto_param': [False, True]}},\n        {'method': 'Translate',\n         'params': {'x_bias': [0, 0.05, -0.05], 'y_bias': [0, -0.05, 0.05], 'auto_param': [False, True]}},\n        {'method': 'Scale',\n         'params': {'factor_x': [1, 0.9], 'factor_y': [1, 0.9], 'auto_param': [False, True]}},\n        {'method': 'Shear',\n         'params': {'factor': [0.2, 0.1], 'direction': ['horizontal', 'vertical'], 'auto_param': [False, True]}},\n        {'method': 'Rotate',\n         'params': {'angle': [20, 90], 'auto_param': [False, True]}},\n        {'method': 'Perspective',\n         'params': {'ori_pos': [[[0, 0], [0, 800], [800, 0], [800, 800]]],\n                    'dst_pos': [[[50, 0], [0, 800], [780, 0], [800, 800]]], 'auto_param': [False, True]}},\n        {'method': 'Curve',\n         'params': {'curves': [5], 'depth': [2], 'mode': ['vertical'], 'auto_param': [False, True]}},\n        {'method': 'FGSM',\n         'params': {'eps': [0.3, 0.2, 0.4], 'alpha': [0.1], 'bounds': [(0, 1)]}}]\n\n    # get training data\n    data_list = \"../common/dataset/MNIST/train\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size, sparse=False)\n    train_images = []\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        images = data[0].astype(np.float32)\n        train_images.append(images)\n    train_images = np.concatenate(train_images, axis=0)\n    segmented_num = 100\n\n    # fuzz test with original test data\n    data_list = \"../common/dataset/MNIST/test\"\n    batch_size = batch_size\n    init_samples = 50\n    max_iters = 500\n    mutate_num_per_seed = 10\n    ds = generate_mnist_dataset(data_list, batch_size=batch_size, num_samples=init_samples, sparse=False)\n    test_images = []\n    test_labels = []\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        test_images.append(data[0].astype(np.float32))\n        test_labels.append(data[1])\n    test_images = np.concatenate(test_images, axis=0)\n    test_labels = np.concatenate(test_labels, axis=0)\n\n    coverage = KMultisectionNeuronCoverage(model, train_images, segmented_num=segmented_num, incremental=True)\n    kmnc = coverage.get_metrics(test_images[:100])\n    print('kmnc: ', kmnc)\n\n    # make initial seeds\n    initial_seeds = []\n    for img, label in zip(test_images, test_labels):\n        initial_seeds.append([img, label])\n\n    model_fuzz_test = Fuzzer(model)\n    gen_samples, gt, _, _, metrics = model_fuzz_test.fuzzing(mutate_config,\n                                                             initial_seeds, coverage,\n                                                             evaluate=True,\n                                                             max_iters=max_iters,\n                                                             mutate_num_per_seed=mutate_num_per_seed)\n\n    if metrics:\n        for key in metrics:\n            LOGGER.info(TAG, key + ': %s', metrics[key])\n\n    train_image, train_label, test_image, test_label = split_dataset(gen_samples, gt, 0.7)\n\n    # load model B and test it on the test set\n    ckpt_path = '../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n    model_b = Model(net)\n    pred_b = model_b.predict(Tensor(test_image, dtype=mindspore.float32)).asnumpy()\n    acc_b = np.sum(np.argmax(pred_b, axis=1) == np.argmax(test_label, axis=1)) / len(test_label)\n    print('Accuracy of model B on test set is ', acc_b)\n\n    # enhense model robustness\n    lr = 0.001\n    momentum = 0.9\n    loss_fn = SoftmaxCrossEntropyWithLogits(sparse=True)\n    optimizer = Momentum(net.trainable_params(), lr, momentum)\n\n    adv_defense = AdversarialDefense(net, loss_fn, optimizer)\n    adv_defense.batch_defense(np.array(train_image).astype(np.float32), np.argmax(train_label, axis=1).astype(np.int32))\n    preds_en = net(Tensor(test_image, dtype=mindspore.float32)).asnumpy()\n    acc_en = np.sum(np.argmax(preds_en, axis=1) == np.argmax(test_label, axis=1)) / len(test_label)\n    print('Accuracy of enhensed model on test set is ', acc_en)\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    example_lenet_mnist_fuzzing()\n"
  },
  {
    "path": "examples/ai_fuzzer/lenet5_mnist_coverage.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy as np\nfrom mindspore import Model\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\n\nfrom mindarmour.fuzz_testing.model_coverage_metrics import NeuronCoverage, TopKNeuronCoverage, NeuronBoundsCoverage,\\\n    SuperNeuronActivateCoverage, KMultisectionNeuronCoverage\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\nfrom examples.common.networks.lenet5.lenet5_net_for_fuzzing import LeNet5\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Neuron coverage test'\nLOGGER.set_level('INFO')\n\n\ndef test_lenet_mnist_coverage():\n    # upload trained network\n    ckpt_path = '../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n    model = Model(net)\n\n    # get training data\n    data_list = \"../common/dataset/MNIST/train\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size, sparse=True)\n    train_images = []\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        images = data[0].astype(np.float32)\n        train_images.append(images)\n    train_images = np.concatenate(train_images, axis=0)\n\n    # fuzz test with original test data\n    # get test data\n    data_list = \"../common/dataset/MNIST/test\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size, sparse=True)\n    test_images = []\n    test_labels = []\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        images = data[0].astype(np.float32)\n        labels = data[1]\n        test_images.append(images)\n        test_labels.append(labels)\n    test_images = np.concatenate(test_images, axis=0)\n\n    # initialize fuzz test with training dataset\n    nc = NeuronCoverage(model, threshold=0.1)\n    nc_metric = nc.get_metrics(test_images)\n\n    tknc = TopKNeuronCoverage(model, top_k=3)\n    tknc_metrics = tknc.get_metrics(test_images)\n\n    snac = SuperNeuronActivateCoverage(model, train_images)\n    snac_metrics = snac.get_metrics(test_images)\n\n    nbc = NeuronBoundsCoverage(model, train_images)\n    nbc_metrics = nbc.get_metrics(test_images)\n\n    kmnc = KMultisectionNeuronCoverage(model, train_images, segmented_num=100)\n    kmnc_metrics = kmnc.get_metrics(test_images)\n\n    print('KMNC of this test is: ', kmnc_metrics)\n    print('NBC of this test is: ', nbc_metrics)\n    print('SNAC of this test is: ', snac_metrics)\n    print('NC of this test is: ', nc_metric)\n    print('TKNC of this test is: ', tknc_metrics)\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    test_lenet_mnist_coverage()\n"
  },
  {
    "path": "examples/ai_fuzzer/lenet5_mnist_fuzzing.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy as np\nfrom mindspore import Model\nfrom mindspore import context\nfrom mindspore import load_checkpoint, load_param_into_net\n\nfrom mindarmour.fuzz_testing import Fuzzer\nfrom mindarmour.fuzz_testing import KMultisectionNeuronCoverage\nfrom mindarmour.utils import LogUtil\n\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\nfrom examples.common.networks.lenet5.lenet5_net_for_fuzzing import LeNet5\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Fuzz_test'\nLOGGER.set_level('INFO')\n\n\ndef test_lenet_mnist_fuzzing():\n    # upload trained network\n    ckpt_path = '../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n    model = Model(net)\n    mutate_config = [\n        {'method': 'GaussianBlur',\n         'params': {'ksize': [1, 2, 3, 5],\n                    'auto_param': [True, False]}},\n        {'method': 'MotionBlur',\n         'params': {'degree': [1, 2, 5], 'angle': [45, 10, 100, 140, 210, 270, 300], 'auto_param': [True]}},\n        {'method': 'GradientBlur',\n         'params': {'point': [[10, 10]], 'auto_param': [True]}},\n        {'method': 'UniformNoise',\n         'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n        {'method': 'GaussianNoise',\n         'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n        {'method': 'SaltAndPepperNoise',\n         'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n        {'method': 'NaturalNoise',\n         'params': {'ratio': [0.1, 0.2, 0.3], 'k_x_range': [(1, 3), (1, 5)], 'k_y_range': [(1, 5)],\n                    'auto_param': [False, True]}},\n        {'method': 'Contrast',\n         'params': {'alpha': [0.5, 1, 1.5], 'beta': [-10, 0, 10], 'auto_param': [False, True]}},\n        {'method': 'GradientLuminance',\n         'params': {'color_start': [(0, 0, 0)], 'color_end': [(255, 255, 255)], 'start_point': [(10, 10)],\n                    'scope': [0.5], 'pattern': ['light'], 'bright_rate': [0.3], 'mode': ['circle'],\n                    'auto_param': [False, True]}},\n        {'method': 'Translate',\n         'params': {'x_bias': [0, 0.05, -0.05], 'y_bias': [0, -0.05, 0.05], 'auto_param': [False, True]}},\n        {'method': 'Scale',\n         'params': {'factor_x': [1, 0.9], 'factor_y': [1, 0.9], 'auto_param': [False, True]}},\n        {'method': 'Shear',\n         'params': {'factor': [0.2, 0.1], 'direction': ['horizontal', 'vertical'], 'auto_param': [False, True]}},\n        {'method': 'Rotate',\n         'params': {'angle': [20, 90], 'auto_param': [False, True]}},\n        {'method': 'Perspective',\n         'params': {'ori_pos': [[[0, 0], [0, 800], [800, 0], [800, 800]]],\n                    'dst_pos': [[[50, 0], [0, 800], [780, 0], [800, 800]]], 'auto_param': [False, True]}},\n        {'method': 'Curve',\n         'params': {'curves': [5], 'depth': [2], 'mode': ['vertical'], 'auto_param': [False, True]}},\n        {'method': 'FGSM',\n         'params': {'eps': [0.3, 0.2, 0.4], 'alpha': [0.1], 'bounds': [(0, 1)]}},\n        {'method': 'PGD',\n         'params': {'eps': [0.1, 0.2, 0.4], 'eps_iter': [0.05, 0.1], 'nb_iter': [1, 3]}},\n        {'method': 'MDIIM',\n         'params': {'eps': [0.1, 0.2, 0.4], 'prob': [0.5, 0.1],\n                    'norm_level': [1, 2, '1', '2', 'l1', 'l2', 'inf', 'np.inf', 'linf']}}\n    ]\n\n    # get training data\n    data_list = \"../common/dataset/MNIST/train\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size, sparse=False)\n    train_images = []\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        images = data[0].astype(np.float32)\n        train_images.append(images)\n    train_images = np.concatenate(train_images, axis=0)\n\n    # fuzz test with original test data\n    # get test data\n    data_list = \"../common/dataset/MNIST/test\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size, sparse=False)\n    test_images = []\n    test_labels = []\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        images = data[0].astype(np.float32)\n        labels = data[1]\n        test_images.append(images)\n        test_labels.append(labels)\n    test_images = np.concatenate(test_images, axis=0)\n    test_labels = np.concatenate(test_labels, axis=0)\n    initial_seeds = []\n\n    # make initial seeds\n    for img, label in zip(test_images, test_labels):\n        initial_seeds.append([img, label])\n    coverage = KMultisectionNeuronCoverage(model, train_images, segmented_num=100, incremental=True)\n    kmnc = coverage.get_metrics(test_images[:100])\n    print('KMNC of initial seeds is: ', kmnc)\n    initial_seeds = initial_seeds[:100]\n    model_fuzz_test = Fuzzer(model)\n    _, _, _, _, metrics = model_fuzz_test.fuzzing(mutate_config,\n                                                  initial_seeds, coverage,\n                                                  evaluate=True,\n                                                  max_iters=10,\n                                                  mutate_num_per_seed=20)\n\n    if metrics:\n        for key in metrics:\n            print(key + ': ', metrics[key])\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\"GPU, \"\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    test_lenet_mnist_fuzzing()\n"
  },
  {
    "path": "examples/ai_fuzzer/lenet5_mnist_scc.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nA sample example for SCC.\n\"\"\"\nimport numpy as np\n\nimport mindspore\nfrom mindspore import Model\nfrom mindspore import nn\n\nfrom mindspore.dataset import vision, transforms\nfrom mindspore.dataset import MnistDataset\nfrom mindspore.common.initializer import TruncatedNormal\nfrom mindspore.ops import operations as P\nfrom mindspore.ops import TensorSummary\nfrom mindarmour.fuzz_testing.fuzzing import SensitivityMaximizingFuzzer\nfrom mindarmour.fuzz_testing.sensitivity_convergence_coverage import SensitivityConvergenceCoverage\n\n\ndef datapipe(path):\n    \"\"\"Prepare and return the MNIST dataset.\"\"\"\n    image_transforms = [\n        vision.Rescale(1.0 / 255.0, 0),\n        vision.HWC2CHW()\n    ]\n    label_transform = transforms.TypeCast(mindspore.int32)\n\n    dataset = MnistDataset(path)\n    dataset = dataset.map(image_transforms, 'image')\n    dataset = dataset.map(label_transform, 'label')\n    dataset = dataset.batch(100)\n    return dataset\n\n\nclass Net(nn.Cell):\n    \"\"\"Convolutional neural network model.\"\"\"\n    def __init__(self):\n        super().__init__()\n        self.conv1 = nn.Conv2d(1, 6, 4, padding=0, weight_init=TruncatedNormal(0.02), pad_mode=\"valid\")\n        self.conv2 = nn.Conv2d(6, 16, 4, padding=0, weight_init=TruncatedNormal(0.02), pad_mode=\"valid\")\n        self.fc1 = nn.Dense(16 * 4 * 4, 120, TruncatedNormal(0.02), TruncatedNormal(0.02))\n        self.fc2 = nn.Dense(120, 84, TruncatedNormal(0.02), TruncatedNormal(0.02))\n        self.fc3 = nn.Dense(84, 10, TruncatedNormal(0.02), TruncatedNormal(0.02))\n        self.relu = nn.ReLU()\n        self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.reshape = P.Reshape()\n        self.summary = TensorSummary()\n\n    def construct(self, x):\n        \"\"\"Construct the network.\"\"\"\n        x = self.conv1(x)\n        x = self.relu(x)\n        self.summary('conv1', x)\n        x = self.max_pool2d(x)\n        x = self.conv2(x)\n        x = self.relu(x)\n        self.summary('conv2', x)\n        x = self.max_pool2d(x)\n        x = self.reshape(x, (-1, 16 * 4 * 4))\n        x = self.fc1(x)\n        x = self.relu(x)\n        self.summary('fc1', x)\n        x = self.fc2(x)\n        x = self.relu(x)\n        self.summary('fc2', x)\n        x = self.fc3(x)\n        self.summary('fc3', x)\n        return x\n\nmodel = Net()\nparam_dict = mindspore.load_checkpoint(\"model.ckpt\")\nmindspore.load_param_into_net(model, param_dict)\n\nmodel = Model(model)\nmutate_config = [{'method': 'GaussianBlur',\n                  'params': {'ksize': [1, 2, 3, 5], 'auto_param': [True, False]}},\n                 {'method': 'MotionBlur',\n                  'params': {'degree': [1, 2, 5], 'angle': [45, 10, 100, 140, 210, 270, 300]}},\n                 {'method': 'UniformNoise',\n                  'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n                 {'method': 'GaussianNoise',\n                  'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n                 {'method': 'Contrast',\n                  'params': {'alpha': [0.5, 1, 1.5], 'beta': [-10, 0, 10], 'auto_param': [False, True]}},\n                 {'method': 'Rotate',\n                  'params': {'angle': [20, 90], 'auto_param': [False, True]}},\n                 {'method': 'FGSM',\n                  'params': {'eps': [0.3, 0.2, 0.4], 'alpha': [0.1], 'bounds': [(0, 1)]}}]\n\n# make initial seeds\ntest_dataset = datapipe('MNIST_Data/test')\n\n\nfor data, label in test_dataset.create_tuple_iterator():\n    initial_data = data\n    initial_label = label\n    break\n\ninitial_seeds = []\nfor data, label in test_dataset.create_tuple_iterator():\n    initial_data = data\n    initial_label = label\n    break\n\nfor img, label in zip(initial_data, initial_label):\n    label_array = np.array([0 if i != label else 1 for i in range(10)])\n    initial_seeds.append([np.array(img).astype(np.float32), label_array.astype(np.float32)])\n\nSCC = SensitivityConvergenceCoverage(model, batch_size=32)\n\nprint(\"SCC.get_metrics(initial_data)\", SCC.get_metrics(initial_data))\n\nmodel_fuzz_test = SensitivityMaximizingFuzzer(model)\nsamples, gt_labels, preds, strategies, metrics = model_fuzz_test.fuzzing(\n    mutate_config, initial_seeds, SCC, max_iters=10)\n\nprint(metrics)\n"
  },
  {
    "path": "examples/common/__init__.py",
    "content": ""
  },
  {
    "path": "examples/common/dataset/__init__.py",
    "content": ""
  },
  {
    "path": "examples/common/dataset/data_processing.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"data processing\"\"\"\n\nimport os\nimport mindspore.dataset as ds\nimport mindspore.dataset.vision as CV\nimport mindspore.dataset.transforms as C\nfrom mindspore.dataset.vision import Inter\nimport mindspore.common.dtype as mstype\n\n\ndef generate_mnist_dataset(data_path, batch_size=32, repeat_size=1,\n                           num_samples=None, num_parallel_workers=1, sparse=True):\n    \"\"\"\n    create dataset for training or testing\n    \"\"\"\n    # define dataset\n    ds1 = ds.MnistDataset(data_path, num_samples=num_samples)\n\n    # define operation parameters\n    resize_height, resize_width = 32, 32\n    rescale = 1.0 / 255.0\n    shift = 0.0\n\n    # define map operations\n    resize_op = CV.Resize((resize_height, resize_width),\n                          interpolation=Inter.LINEAR)\n    rescale_op = CV.Rescale(rescale, shift)\n    hwc2chw_op = CV.HWC2CHW()\n    type_cast_op = C.TypeCast(mstype.int32)\n\n    # apply map operations on images\n    if not sparse:\n        one_hot_enco = C.OneHot(10)\n        ds1 = ds1.map(input_columns=\"label\", operations=one_hot_enco,\n                      num_parallel_workers=num_parallel_workers)\n        type_cast_op = C.TypeCast(mstype.float32)\n    ds1 = ds1.map(input_columns=\"label\", operations=type_cast_op,\n                  num_parallel_workers=num_parallel_workers)\n    ds1 = ds1.map(input_columns=\"image\", operations=resize_op,\n                  num_parallel_workers=num_parallel_workers)\n    ds1 = ds1.map(input_columns=\"image\", operations=rescale_op,\n                  num_parallel_workers=num_parallel_workers)\n    ds1 = ds1.map(input_columns=\"image\", operations=hwc2chw_op,\n                  num_parallel_workers=num_parallel_workers)\n\n    # apply DatasetOps\n    buffer_size = 10000\n    ds1 = ds1.shuffle(buffer_size=buffer_size)\n    ds1 = ds1.batch(batch_size, drop_remainder=True)\n    ds1 = ds1.repeat(repeat_size)\n\n    return ds1\n\n\ndef vgg_create_dataset100(data_home, image_size, batch_size, rank_id=0, rank_size=1, repeat_num=1,\n                          training=True, num_samples=None, shuffle=True):\n    \"\"\"Data operations.\"\"\"\n    ds.config.set_seed(1)\n    data_dir = os.path.join(data_home, \"train\")\n    if not training:\n        data_dir = os.path.join(data_home, \"test\")\n\n    if num_samples is not None:\n        data_set = ds.Cifar100Dataset(data_dir, num_shards=rank_size, shard_id=rank_id,\n                                      num_samples=num_samples, shuffle=shuffle)\n    else:\n        data_set = ds.Cifar100Dataset(data_dir, num_shards=rank_size, shard_id=rank_id)\n\n    input_columns = [\"fine_label\"]\n    output_columns = [\"label\"]\n    data_set = data_set.rename(input_columns=input_columns, output_columns=output_columns)\n    data_set = data_set.project([\"image\", \"label\"])\n\n    rescale = 1.0 / 255.0\n    shift = 0.0\n\n    # define map operations\n    random_crop_op = CV.RandomCrop((32, 32), (4, 4, 4, 4))  # padding_mode default CONSTANT\n    random_horizontal_op = CV.RandomHorizontalFlip()\n    resize_op = CV.Resize(image_size)  # interpolation default BILINEAR\n    rescale_op = CV.Rescale(rescale, shift)\n    normalize_op = CV.Normalize((0.4465, 0.4822, 0.4914), (0.2010, 0.1994, 0.2023))\n    changeswap_op = CV.HWC2CHW()\n    type_cast_op = C.TypeCast(mstype.int32)\n\n    c_trans = []\n    if training:\n        c_trans = [random_crop_op, random_horizontal_op]\n    c_trans += [resize_op, rescale_op, normalize_op,\n                changeswap_op]\n\n    # apply map operations on images\n    data_set = data_set.map(input_columns=\"label\", operations=type_cast_op)\n    data_set = data_set.map(input_columns=\"image\", operations=c_trans)\n\n    # apply shuffle operations\n    data_set = data_set.shuffle(buffer_size=1000)\n\n    # apply batch operations\n    data_set = data_set.batch(batch_size=batch_size, drop_remainder=True)\n\n    # apply repeat operations\n    data_set = data_set.repeat(repeat_num)\n    return data_set\n\n\ndef create_dataset_imagenet(path, batch_size=32, repeat_size=20, status=\"train\", target=\"GPU\"):\n    image_ds = ds.ImageFolderDataset(path, decode=True)\n    rescale = 1.0 / 255.0\n    shift = 0.0\n    cfg = {'num_classes': 10,\n           'learning_rate': 0.002,\n           'momentum': 0.9,\n           'epoch_size': 30,\n           'batch_size': batch_size,\n           'buffer_size': 1000,\n           'image_height': 224,\n           'image_width': 224,\n           'save_checkpoint_steps': 1562,\n           'keep_checkpoint_max': 10,\n           'device': target,\n           'status': status}\n    resize_op = CV.Resize((cfg['image_height'], cfg['image_width']))\n    rescale_op = CV.Rescale(rescale, shift)\n    normalize_op = CV.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))\n\n    random_crop_op = CV.RandomCrop([32, 32], [4, 4, 4, 4])\n    random_horizontal_op = CV.RandomHorizontalFlip()\n    channel_swap_op = CV.HWC2CHW()\n    typecast_op = C.TypeCast(mstype.int32)\n    image_ds = image_ds.map(input_columns=\"label\", operations=typecast_op, num_parallel_workers=6)\n\n    image_ds = image_ds.map(input_columns=\"image\", operations=random_crop_op, num_parallel_workers=6)\n    image_ds = image_ds.map(input_columns=\"image\", operations=random_horizontal_op, num_parallel_workers=6)\n    image_ds = image_ds.map(input_columns=\"image\", operations=resize_op, num_parallel_workers=6)\n    image_ds = image_ds.map(input_columns=\"image\", operations=rescale_op, num_parallel_workers=6)\n    image_ds = image_ds.map(input_columns=\"image\", operations=normalize_op, num_parallel_workers=6)\n    image_ds = image_ds.map(input_columns=\"image\", operations=channel_swap_op, num_parallel_workers=6)\n\n    image_ds = image_ds.shuffle(buffer_size=cfg['buffer_size'])\n    image_ds = image_ds.repeat(repeat_size)\n    return image_ds\n\n\ndef create_dataset_cifar(data_path, image_height, image_width, repeat_num=1, training=True):\n    \"\"\"\n    create data for next use such as training or inferring\n    \"\"\"\n    usage = \"train\" if training else \"test\"\n    cifar_ds = ds.Cifar10Dataset(dataset_dir=data_path, usage=usage)\n    resize_height = image_height  # 224\n    resize_width = image_width  # 224\n    rescale = 1.0 / 255.0\n    shift = 0.0\n    batch_size = 32\n    # define map operations\n    random_crop_op = CV.RandomCrop((32, 32), (4, 4, 4, 4))  # padding_mode default CONSTANT\n    random_horizontal_op = CV.RandomHorizontalFlip()\n    resize_op = CV.Resize((resize_height, resize_width))  # interpolation default BILINEAR\n    rescale_op = CV.Rescale(rescale, shift)\n    normalize_op = CV.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))\n    changeswap_op = CV.HWC2CHW()\n    type_cast_op = C.TypeCast(mstype.int32)\n    c_trans = []\n    if training:\n        c_trans = [random_crop_op, random_horizontal_op]\n    c_trans += [resize_op, rescale_op, normalize_op,\n                changeswap_op]\n    # apply map operations on images\n    cifar_ds = cifar_ds.map(operations=type_cast_op, input_columns=\"label\")\n    cifar_ds = cifar_ds.map(operations=c_trans, input_columns=\"image\")\n    # apply shuffle operations\n    cifar_ds = cifar_ds.shuffle(buffer_size=10)\n    # apply batch operations\n    cifar_ds = cifar_ds.batch(batch_size=batch_size, drop_remainder=True)\n    # apply repeat operations\n    cifar_ds = cifar_ds.repeat(repeat_num)\n    return cifar_ds\n\n\ndef generate_dataset_cifar(data_path, batch_size, usage, repeat_num=1):\n    \"\"\"\n    create data for next use such as training or inferring\n    \"\"\"\n    cifar_ds = ds.Cifar10Dataset(data_path, usage=usage)\n    resize_height = 32\n    resize_width = 32\n    rescale = 1.0 / 255.0\n    shift = 0.0\n    batch_size = batch_size\n    # define map operations\n    resize_op = CV.Resize((resize_height, resize_width))  # interpolation default BILINEAR\n    rescale_op = CV.Rescale(rescale, shift)\n    changeswap_op = CV.HWC2CHW()\n    type_cast_op = C.TypeCast(mstype.int32)\n    c_trans = []\n    c_trans += [resize_op, rescale_op,\n                changeswap_op]\n    # apply map operations on images\n    cifar_ds = cifar_ds.map(operations=type_cast_op, input_columns=\"label\")\n    cifar_ds = cifar_ds.map(operations=c_trans, input_columns=\"image\")\n    # apply shuffle operations\n    cifar_ds = cifar_ds.shuffle(buffer_size=10)\n    # apply batch operations\n    cifar_ds = cifar_ds.batch(batch_size=batch_size, drop_remainder=True)\n    # apply repeat operations\n    cifar_ds = cifar_ds.repeat(repeat_num)\n    return cifar_ds\n"
  },
  {
    "path": "examples/common/networks/__init__.py",
    "content": ""
  },
  {
    "path": "examples/common/networks/cifar10cnn/__init__.py",
    "content": ""
  },
  {
    "path": "examples/common/networks/cifar10cnn/cifar10cnn_net.py",
    "content": "# Copyright 2024 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nCIFAR10CNN network.\n\"\"\"\nimport collections\nfrom mindspore import nn\nfrom mindspore.common.initializer import TruncatedNormal\n\ndef weight_variable():\n    return TruncatedNormal(0.05)\n\ndef conv(in_channels, out_channels, kernel_size, stride=1, padding=0):\n    weight = weight_variable()\n    return nn.Conv2d(in_channels, out_channels,\n                     kernel_size=kernel_size, stride=stride, padding=padding,\n                     weight_init=weight, has_bias=False, pad_mode=\"pad\")\n\n\ndef fc_with_initialize(input_channels, out_channels):\n    weight = weight_variable()\n    bias = weight_variable()\n    return nn.Dense(input_channels, out_channels, weight, bias)\n\nclass CIFAR10CNN(nn.Cell):\n    \"\"\"\n    Part of CIFAR10CNN network.\n    \"\"\"\n    def __init__(self):\n        super(CIFAR10CNN, self).__init__()\n        self.features = []\n        self.layerdict = collections.OrderedDict()\n\n        self.conv11 = conv(3, 64, 3, padding=1)\n        self.relu11 = nn.ReLU()\n        self.conv12 = conv(64, 64, 3, padding=1)\n        self.relu12 = nn.ReLU()\n        self.pool1 = nn.MaxPool2d(2, 2)\n\n        self.features.extend([\n            self.conv11, self.relu11, self.conv12, self.relu12, self.pool1\n        ])\n        self.layerdict['conv11'] = self.conv11\n        self.layerdict['relu11'] = self.relu11\n        self.layerdict['conv12'] = self.conv12\n        self.layerdict['relu12'] = self.relu12\n        self.layerdict['pool1'] = self.pool1\n\n        self.conv21 = conv(64, 128, 3, padding=1)\n        self.relu21 = nn.ReLU()\n        self.conv22 = conv(128, 128, 3, padding=1)\n        self.relu22 = nn.ReLU()\n        self.pool2 = nn.MaxPool2d(2, 2)\n        self.features.extend([\n            self.conv21, self.relu21, self.conv22, self.relu22, self.pool2\n        ])\n        self.layerdict['conv21'] = self.conv21\n        self.layerdict['relu21'] = self.relu21\n        self.layerdict['conv22'] = self.conv22\n        self.layerdict['relu22'] = self.relu22\n        self.layerdict['pool2'] = self.pool2\n\n        self.conv31 = conv(128, 128, 3, padding=1)\n        self.relu31 = nn.ReLU()\n        self.conv32 = conv(128, 128, 3, padding=1)\n        self.relu32 = nn.ReLU()\n        self.pool3 = nn.MaxPool2d(2, 2)\n        self.features.extend([\n            self.conv31, self.relu31, self.conv32, self.relu32, self.pool3\n        ])\n        self.layerdict['conv31'] = self.conv31\n        self.layerdict['relu31'] = self.relu31\n        self.layerdict['conv32'] = self.conv32\n        self.layerdict['relu32'] = self.relu32\n        self.layerdict['pool3'] = self.pool3\n\n        self.classifier = []\n        self.feature_dims = 4 * 4 * 128\n        self.fc1 = fc_with_initialize(self.feature_dims, 512)\n        self.fc1act = nn.Sigmoid()\n        self.fc2 = fc_with_initialize(512, 10)\n        self.classifier.extend([\n            self.fc1, self.fc1act, self.fc2\n        ])\n        self.layerdict['fc1'] = self.fc1\n        self.layerdict['fc1act'] = self.fc1act\n        self.layerdict['fc2'] = self.fc2\n\n    def construct(self, x):\n        for layer in self.features:\n            x = layer(x)\n        x = x.view(-1, self.feature_dims)\n\n        for layer in self.classifier:\n            x = layer(x)\n        return x\n\n    def forward_from(self, x, layer):\n        \"\"\"\n        Forward the network from the target layer.\n        \"\"\"\n        if layer in self.layerdict:\n            targetlayer = self.layerdict[layer]\n\n            if targetlayer in self.features:\n                layeridx = self.features.index(targetlayer)\n                for func in self.features[layeridx + 1:]:\n                    x = func(x)\n\n                x = x.view(-1, self.feature_dims)\n                for func in self.classifier:\n                    x = func(x)\n                return x\n            layeridx = self.classifier.index(targetlayer)\n            for func in self.classifier[layeridx:]:\n                x = func(x)\n            return x\n        msg = \"Target Layer not exists\"\n        raise ValueError(msg)\n\n    def get_layer_output(self, x, targetlayer):\n        \"\"\"\n        Get the output of the target layer.\n        \"\"\"\n        targetlayer = self.layerdict.get(targetlayer, None)\n        for layer in self.features:\n            x = layer(x)\n            if layer == targetlayer:\n                return x\n        x = x.view(-1, self.feature_dims)\n        for layer in self.classifier:\n            x = layer(x)\n            if layer == targetlayer:\n                return x\n        msg = \"Target Layer not exists\"\n        raise ValueError(msg)\n"
  },
  {
    "path": "examples/common/networks/cifar10cnn/cifar_train.py",
    "content": "# Copyright 2024 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nTrain a CIFAR10CNN network model.\n\"\"\"\nimport os\n\nimport mindspore.nn as nn\nfrom mindspore import context\nfrom mindspore.nn.metrics import Accuracy\nfrom mindspore.train import Model\nfrom mindspore.train.callback import ModelCheckpoint, CheckpointConfig, LossMonitor\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\n\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.dataset.data_processing import create_dataset_cifar\nfrom examples.common.networks.cifar10cnn.cifar10cnn_net import CIFAR10CNN\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\n\nTAG = \"CIFAR10CNN_train\"\n\n\ndef cifar_train(epoch_size, lr, momentum):\n    \"\"\"\n    Generate Dataset and Train\n    \"\"\"\n    mnist_path = \"../../dataset/CIFAR10\"\n    # ds = create_dataset_cifar(os.path.join(mnist_path, \"train\"), 32, 32, repeat_num=1)\n    ds = create_dataset_cifar(mnist_path, 32, 32, repeat_num=1)\n\n    network = CIFAR10CNN()\n    net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction=\"mean\")\n    net_opt = nn.Momentum(network.trainable_params(), lr, momentum)\n    config_ck = CheckpointConfig(save_checkpoint_steps=1875,\n                                 keep_checkpoint_max=10)\n    ckpoint_cb = ModelCheckpoint(prefix=\"checkpoint_cifar\",\n                                 directory=\"./trained_ckpt_file/\",\n                                 config=config_ck)\n    model = Model(network, net_loss, net_opt, metrics={\"Accuracy\": Accuracy()})\n\n    LOGGER.info(TAG, \"============== Starting Training ==============\")\n    model.train(epoch_size, ds, callbacks=[ckpoint_cb, LossMonitor()],\n                dataset_sink_mode=False)\n\n    LOGGER.info(TAG, \"============== Starting Testing ==============\")\n    ckpt_file_name = \"trained_ckpt_file/checkpoint_cifar-10_1562.ckpt\"\n    param_dict = load_checkpoint(ckpt_file_name)\n    load_param_into_net(network, param_dict)\n    ds_eval = create_dataset_cifar(mnist_path, 32, 32, repeat_num=1, training=False)\n    acc = model.eval(ds_eval, dataset_sink_mode=False)\n    LOGGER.info(TAG, \"============== Accuracy: %s ==============\", acc)\n\n\nif __name__ == '__main__':\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    cifar_train(10, 0.01, 0.9)\n"
  },
  {
    "path": "examples/common/networks/lenet5/__init__.py",
    "content": ""
  },
  {
    "path": "examples/common/networks/lenet5/lenet5_net.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom mindspore import nn\nfrom mindspore.common.initializer import TruncatedNormal\n\n\ndef conv(in_channels, out_channels, kernel_size, stride=1, padding=0):\n    weight = weight_variable()\n    return nn.Conv2d(in_channels, out_channels,\n                     kernel_size=kernel_size, stride=stride, padding=padding,\n                     weight_init=weight, has_bias=False, pad_mode=\"valid\")\n\n\ndef fc_with_initialize(input_channels, out_channels):\n    weight = weight_variable()\n    bias = weight_variable()\n    return nn.Dense(input_channels, out_channels, weight, bias)\n\n\ndef weight_variable():\n    return TruncatedNormal(0.05)\n\n\nclass LeNet5(nn.Cell):\n    \"\"\"\n    Lenet network\n    \"\"\"\n    def __init__(self):\n        super(LeNet5, self).__init__()\n        self.conv1 = conv(1, 6, 5)\n        self.conv2 = conv(6, 16, 5)\n        self.fc1 = fc_with_initialize(16*5*5, 120)\n        self.fc2 = fc_with_initialize(120, 84)\n        self.fc3 = fc_with_initialize(84, 10)\n        self.relu = nn.ReLU()\n        self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.flatten = nn.Flatten()\n\n    def construct(self, x):\n        x = self.conv1(x)\n        x = self.relu(x)\n        x = self.max_pool2d(x)\n        x = self.conv2(x)\n        x = self.relu(x)\n        x = self.max_pool2d(x)\n        x = self.flatten(x)\n        x = self.fc1(x)\n        x = self.relu(x)\n        x = self.fc2(x)\n        x = self.relu(x)\n        x = self.fc3(x)\n        return x\n"
  },
  {
    "path": "examples/common/networks/lenet5/lenet5_net_for_fuzzing.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nlenet network with summary\n\"\"\"\nfrom mindspore import nn\nfrom mindspore.common.initializer import TruncatedNormal\nfrom mindspore.ops import TensorSummary\n\n\ndef conv(in_channels, out_channels, kernel_size, stride=1, padding=0):\n    \"\"\"Wrap conv.\"\"\"\n    weight = weight_variable()\n    return nn.Conv2d(in_channels, out_channels, kernel_size=kernel_size, stride=stride, padding=padding,\n                     weight_init=weight, has_bias=False, pad_mode=\"valid\")\n\n\ndef fc_with_initialize(input_channels, out_channels):\n    \"\"\"Wrap initialize method of full connection layer.\"\"\"\n    weight = weight_variable()\n    bias = weight_variable()\n    return nn.Dense(input_channels, out_channels, weight, bias)\n\n\ndef weight_variable():\n    \"\"\"Wrap initialize variable.\"\"\"\n    return TruncatedNormal(0.05)\n\n\nclass LeNet5(nn.Cell):\n    \"\"\"\n    Lenet network\n    \"\"\"\n    def __init__(self):\n        super(LeNet5, self).__init__()\n        self.conv1 = conv(1, 6, 5)\n        self.conv2 = conv(6, 16, 5)\n        self.fc1 = fc_with_initialize(16*5*5, 120)\n        self.fc2 = fc_with_initialize(120, 84)\n        self.fc3 = fc_with_initialize(84, 10)\n        self.relu = nn.ReLU()\n        self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.flatten = nn.Flatten()\n        self.summary = TensorSummary()\n\n    def construct(self, x):\n        \"\"\"\n        construct the network architecture\n        Returns:\n            x (tensor): network output\n        \"\"\"\n        x = self.conv1(x)\n        self.summary('1', x)\n\n        x = self.relu(x)\n        self.summary('2', x)\n\n        x = self.max_pool2d(x)\n        self.summary('3', x)\n\n        x = self.conv2(x)\n        self.summary('4', x)\n\n        x = self.relu(x)\n        self.summary('5', x)\n\n        x = self.max_pool2d(x)\n        self.summary('6', x)\n\n        x = self.flatten(x)\n        self.summary('7', x)\n\n        x = self.fc1(x)\n        self.summary('8', x)\n\n        x = self.relu(x)\n        self.summary('9', x)\n\n        x = self.fc2(x)\n        self.summary('10', x)\n\n        x = self.relu(x)\n        self.summary('11', x)\n\n        x = self.fc3(x)\n        self.summary('output', x)\n        return x\n"
  },
  {
    "path": "examples/common/networks/lenet5/mnist_train.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\n\nimport mindspore.nn as nn\nfrom mindspore import context\nfrom mindspore.nn.metrics import Accuracy\nfrom mindspore.train import Model\nfrom mindspore.train.callback import ModelCheckpoint, CheckpointConfig, LossMonitor\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\n\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\n\nTAG = \"Lenet5_train\"\n\n\ndef mnist_train(epoch_size, batch_size, lr, momentum):\n    mnist_path = \"../../dataset/MNIST\"\n    ds = generate_mnist_dataset(os.path.join(mnist_path, \"train\"),\n                                batch_size=batch_size, repeat_size=1)\n\n    network = LeNet5()\n    net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction=\"mean\")\n    net_opt = nn.Momentum(network.trainable_params(), lr, momentum)\n    config_ck = CheckpointConfig(save_checkpoint_steps=1875,\n                                 keep_checkpoint_max=10)\n    ckpoint_cb = ModelCheckpoint(prefix=\"checkpoint_lenet\",\n                                 directory=\"./trained_ckpt_file/\",\n                                 config=config_ck)\n    model = Model(network, net_loss, net_opt, metrics={\"Accuracy\": Accuracy()})\n\n    LOGGER.info(TAG, \"============== Starting Training ==============\")\n    model.train(epoch_size, ds, callbacks=[ckpoint_cb, LossMonitor()],\n                dataset_sink_mode=False)\n\n    LOGGER.info(TAG, \"============== Starting Testing ==============\")\n    ckpt_file_name = \"trained_ckpt_file/checkpoint_lenet-10_1875.ckpt\"\n    param_dict = load_checkpoint(ckpt_file_name)\n    load_param_into_net(network, param_dict)\n    ds_eval = generate_mnist_dataset(os.path.join(mnist_path, \"test\"),\n                                     batch_size=batch_size)\n    acc = model.eval(ds_eval, dataset_sink_mode=False)\n    LOGGER.info(TAG, \"============== Accuracy: %s ==============\", acc)\n\n\nif __name__ == '__main__':\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    mnist_train(10, 32, 0.01, 0.9)\n"
  },
  {
    "path": "examples/common/networks/resnet/__init__.py",
    "content": ""
  },
  {
    "path": "examples/common/networks/resnet/resnet.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\nimport numpy as np\nimport mindspore.nn as nn\nimport mindspore.common.dtype as mstype\nfrom mindspore.ops import operations as P\nfrom mindspore.ops import functional as F\nfrom mindspore.common.tensor import Tensor\nfrom scipy.stats import truncnorm\nfrom mindspore.ops import TensorSummary\n\n\ndef _conv_variance_scaling_initializer(in_channel, out_channel, kernel_size):\n    fan_in = in_channel * kernel_size * kernel_size\n    scale = 1.0\n    scale /= max(1., fan_in)\n    stddev = (scale ** 0.5) / .87962566103423978\n    mu, sigma = 0, stddev\n    weight = truncnorm(-2, 2, loc=mu, scale=sigma).rvs(out_channel * in_channel * kernel_size*kernel_size)\n    weight = np.reshape(weight, (out_channel, in_channel, kernel_size, kernel_size))\n    return Tensor(weight, dtype=mstype.float32)\n\ndef _weight_variable(shape, factor=0.01):\n    init_value = np.random.randn(*shape).astype(np.float32) * factor\n    return Tensor(init_value)\n\n\ndef _conv3x3(in_channel, out_channel, stride=1, use_se=False):\n    if use_se:\n        weight = _conv_variance_scaling_initializer(in_channel, out_channel, kernel_size=3)\n    else:\n        weight_shape = (out_channel, in_channel, 3, 3)\n        weight = _weight_variable(weight_shape)\n    return nn.Conv2d(in_channel, out_channel,\n                     kernel_size=3, stride=stride, padding=0, pad_mode='same', weight_init=weight)\n\n\ndef _conv1x1(in_channel, out_channel, stride=1, use_se=False):\n    if use_se:\n        weight = _conv_variance_scaling_initializer(in_channel, out_channel, kernel_size=1)\n    else:\n        weight_shape = (out_channel, in_channel, 1, 1)\n        weight = _weight_variable(weight_shape)\n    return nn.Conv2d(in_channel, out_channel,\n                     kernel_size=1, stride=stride, padding=0, pad_mode='same', weight_init=weight)\n\n\ndef _conv7x7(in_channel, out_channel, stride=1, use_se=False):\n    if use_se:\n        weight = _conv_variance_scaling_initializer(in_channel, out_channel, kernel_size=7)\n    else:\n        weight_shape = (out_channel, in_channel, 7, 7)\n        weight = _weight_variable(weight_shape)\n    return nn.Conv2d(in_channel, out_channel,\n                     kernel_size=7, stride=stride, padding=0, pad_mode='same', weight_init=weight)\n\n\ndef _bn(channel):\n    return nn.BatchNorm2d(channel, eps=1e-4, momentum=0.9,\n                          gamma_init=1, beta_init=0, moving_mean_init=0, moving_var_init=1)\n\n\ndef _bn_last(channel):\n    return nn.BatchNorm2d(channel, eps=1e-4, momentum=0.9,\n                          gamma_init=0, beta_init=0, moving_mean_init=0, moving_var_init=1)\n\n\ndef _fc(in_channel, out_channel, use_se=False):\n    if use_se:\n        weight = np.random.normal(loc=0, scale=0.01, size=out_channel*in_channel)\n        weight = Tensor(np.reshape(weight, (out_channel, in_channel)), dtype=mstype.float32)\n    else:\n        weight_shape = (out_channel, in_channel)\n        weight = _weight_variable(weight_shape)\n    return nn.Dense(in_channel, out_channel, has_bias=True, weight_init=weight, bias_init=0)\n\n\nclass ResidualBlock(nn.Cell):\n    \"\"\"\n    ResNet V1 residual block definition.\n\n    Args:\n        in_channel (int): Input channel.\n        out_channel (int): Output channel.\n        stride (int): Stride size for the first convolutional layer. Default: 1.\n        use_se (bool): enable SE-ResNet50 net. Default: False.\n        se_block (bool): use se block in SE-ResNet50 net. Default: False.\n\n    Returns:\n        Tensor, output tensor.\n\n    Examples:\n        >>> ResidualBlock(3, 256, stride=2)\n    \"\"\"\n    expansion = 4\n\n    def __init__(self,\n                 in_channel,\n                 out_channel,\n                 stride=1,\n                 use_se=False, se_block=False):\n        super(ResidualBlock, self).__init__()\n        self.summary = TensorSummary()\n        self.stride = stride\n        self.use_se = use_se\n        self.se_block = se_block\n        channel = out_channel // self.expansion\n        self.conv1 = _conv1x1(in_channel, channel, stride=1, use_se=self.use_se)\n        self.bn1 = _bn(channel)\n        if self.use_se and self.stride != 1:\n            self.e2 = nn.SequentialCell([_conv3x3(channel, channel, stride=1, use_se=True), _bn(channel),\n                                         nn.ReLU(), nn.MaxPool2d(kernel_size=2, stride=2, pad_mode='same')])\n        else:\n            self.conv2 = _conv3x3(channel, channel, stride=stride, use_se=self.use_se)\n            self.bn2 = _bn(channel)\n\n        self.conv3 = _conv1x1(channel, out_channel, stride=1, use_se=self.use_se)\n        self.bn3 = _bn_last(out_channel)\n        if self.se_block:\n            self.se_global_pool = P.ReduceMean(keep_dims=False)\n            self.se_dense_0 = _fc(out_channel, int(out_channel/4), use_se=self.use_se)\n            self.se_dense_1 = _fc(int(out_channel/4), out_channel, use_se=self.use_se)\n            self.se_sigmoid = nn.Sigmoid()\n            self.se_mul = P.Mul()\n        self.relu = nn.ReLU()\n\n        self.down_sample = False\n\n        if stride != 1 or in_channel != out_channel:\n            self.down_sample = True\n        self.down_sample_layer = None\n\n        if self.down_sample:\n            if self.use_se:\n                if stride == 1:\n                    self.down_sample_layer = nn.SequentialCell([_conv1x1(in_channel, out_channel,\n                                                                         stride, use_se=self.use_se), _bn(out_channel)])\n                else:\n                    self.down_sample_layer = nn.SequentialCell([nn.MaxPool2d(kernel_size=2, stride=2, pad_mode='same'),\n                                                                _conv1x1(in_channel, out_channel, 1,\n                                                                         use_se=self.use_se), _bn(out_channel)])\n            else:\n                self.down_sample_layer = nn.SequentialCell([_conv1x1(in_channel, out_channel, stride,\n                                                                     use_se=self.use_se), _bn(out_channel)])\n        self.add = P.TensorAdd()\n\n    def construct(self, x):\n        identity = x\n\n        out = self.conv1(x)\n        out = self.bn1(out)\n        out = self.relu(out)\n        if self.use_se and self.stride != 1:\n            out = self.e2(out)\n        else:\n            out = self.conv2(out)\n            out = self.bn2(out)\n            out = self.relu(out)\n        out = self.conv3(out)\n        out = self.bn3(out)\n        if self.se_block:\n            out_se = out\n            out = self.se_global_pool(out, (2, 3))\n            out = self.se_dense_0(out)\n            out = self.relu(out)\n            out = self.se_dense_1(out)\n            out = self.se_sigmoid(out)\n            out = F.reshape(out, F.shape(out) + (1, 1))\n            out = self.se_mul(out, out_se)\n\n        if self.down_sample:\n            identity = self.down_sample_layer(identity)\n\n        out = self.add(out, identity)\n        out = self.relu(out)\n\n        return out\n\n\nclass ResNet(nn.Cell):\n    \"\"\"\n    ResNet architecture.\n\n    Args:\n        block (Cell): Block for network.\n        layer_nums (list): Numbers of block in different layers.\n        in_channels (list): Input channel in each layer.\n        out_channels (list): Output channel in each layer.\n        strides (list):  Stride size in each layer.\n        num_classes (int): The number of classes that the training images are belonging to.\n        use_se (bool): enable SE-ResNet50 net. Default: False.\n        se_block (bool): use se block in SE-ResNet50 net in layer 3 and layer 4. Default: False.\n    Returns:\n        Tensor, output tensor.\n\n    Examples:\n        >>> ResNet(ResidualBlock,\n        >>>        [3, 4, 6, 3],\n        >>>        [64, 256, 512, 1024],\n        >>>        [256, 512, 1024, 2048],\n        >>>        [1, 2, 2, 2],\n        >>>        10)\n    \"\"\"\n\n    def __init__(self,\n                 block,\n                 layer_nums,\n                 in_channels,\n                 out_channels,\n                 strides,\n                 num_classes,\n                 use_se=False):\n        super(ResNet, self).__init__()\n\n        if not len(layer_nums) == len(in_channels) == len(out_channels) == 4:\n            raise ValueError(\"the length of layer_num, in_channels, out_channels list must be 4!\")\n        self.use_se = use_se\n        self.se_block = False\n        if self.use_se:\n            self.se_block = True\n\n        if self.use_se:\n            self.conv1_0 = _conv3x3(3, 32, stride=2, use_se=self.use_se)\n            self.bn1_0 = _bn(32)\n            self.conv1_1 = _conv3x3(32, 32, stride=1, use_se=self.use_se)\n            self.bn1_1 = _bn(32)\n            self.conv1_2 = _conv3x3(32, 64, stride=1, use_se=self.use_se)\n        else:\n            self.conv1 = _conv7x7(3, 64, stride=2)\n        self.bn1 = _bn(64)\n        self.relu = P.ReLU()\n        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, pad_mode=\"same\")\n        self.layer1 = self._make_layer(block,\n                                       layer_nums[0],\n                                       in_channel=in_channels[0],\n                                       out_channel=out_channels[0],\n                                       stride=strides[0],\n                                       use_se=self.use_se)\n        self.layer2 = self._make_layer(block,\n                                       layer_nums[1],\n                                       in_channel=in_channels[1],\n                                       out_channel=out_channels[1],\n                                       stride=strides[1],\n                                       use_se=self.use_se)\n        self.layer3 = self._make_layer(block,\n                                       layer_nums[2],\n                                       in_channel=in_channels[2],\n                                       out_channel=out_channels[2],\n                                       stride=strides[2],\n                                       use_se=self.use_se,\n                                       se_block=self.se_block)\n        self.layer4 = self._make_layer(block,\n                                       layer_nums[3],\n                                       in_channel=in_channels[3],\n                                       out_channel=out_channels[3],\n                                       stride=strides[3],\n                                       use_se=self.use_se,\n                                       se_block=self.se_block)\n\n        self.mean = P.ReduceMean(keep_dims=True)\n        self.flatten = nn.Flatten()\n        self.end_point = _fc(out_channels[3], num_classes, use_se=self.use_se)\n        self.summary = TensorSummary()\n\n    def _make_layer(self, block, layer_num, in_channel, out_channel, stride, use_se=False, se_block=False):\n        \"\"\"\n        Make stage network of ResNet.\n\n        Args:\n            block (Cell): Resnet block.\n            layer_num (int): Layer number.\n            in_channel (int): Input channel.\n            out_channel (int): Output channel.\n            stride (int): Stride size for the first convolutional layer.\n            se_block (bool): use se block in SE-ResNet50 net. Default: False.\n        Returns:\n            SequentialCell, the output layer.\n\n        Examples:\n            >>> _make_layer(ResidualBlock, 3, 128, 256, 2)\n        \"\"\"\n        layers = []\n\n        resnet_block = block(in_channel, out_channel, stride=stride, use_se=use_se)\n        layers.append(resnet_block)\n        if se_block:\n            for _ in range(1, layer_num - 1):\n                resnet_block = block(out_channel, out_channel, stride=1, use_se=use_se)\n                layers.append(resnet_block)\n            resnet_block = block(out_channel, out_channel, stride=1, use_se=use_se, se_block=se_block)\n            layers.append(resnet_block)\n        else:\n            for _ in range(1, layer_num):\n                resnet_block = block(out_channel, out_channel, stride=1, use_se=use_se)\n                layers.append(resnet_block)\n        return nn.SequentialCell(layers)\n\n    def construct(self, x):\n        if self.use_se:\n            x = self.conv1_0(x)\n            x = self.bn1_0(x)\n            x = self.relu(x)\n            x = self.conv1_1(x)\n            x = self.bn1_1(x)\n            x = self.relu(x)\n            x = self.conv1_2(x)\n        else:\n            x = self.conv1(x)\n        x = self.bn1(x)\n        x = self.relu(x)\n        c1 = self.maxpool(x)\n\n        c2 = self.layer1(c1)\n        c3 = self.layer2(c2)\n        c4 = self.layer3(c3)\n        c5 = self.layer4(c4)\n\n        out = self.mean(c5, (2, 3))\n        out = self.flatten(out)\n        self.summary('1', out)\n        out = self.end_point(out)\n        if self.training:\n            return out\n        self.summary('output', out)\n        return out\n\n\ndef resnet50(class_num=10):\n    \"\"\"\n    Get ResNet50 neural network.\n\n    Args:\n        class_num (int): Class number.\n\n    Returns:\n        Cell, cell instance of ResNet50 neural network.\n\n    Examples:\n        >>> net = resnet50(10)\n    \"\"\"\n    return ResNet(ResidualBlock,\n                  [3, 4, 6, 3],\n                  [64, 256, 512, 1024],\n                  [256, 512, 1024, 2048],\n                  [1, 2, 2, 2],\n                  class_num)\n\ndef se_resnet50(class_num=1001):\n    \"\"\"\n    Get SE-ResNet50 neural network.\n\n    Args:\n        class_num (int): Class number.\n\n    Returns:\n        Cell, cell instance of SE-ResNet50 neural network.\n\n    Examples:\n        >>> net = se-resnet50(1001)\n    \"\"\"\n    return ResNet(ResidualBlock,\n                  [3, 4, 6, 3],\n                  [64, 256, 512, 1024],\n                  [256, 512, 1024, 2048],\n                  [1, 2, 2, 2],\n                  class_num,\n                  use_se=True)\n\ndef resnet101(class_num=1001):\n    \"\"\"\n    Get ResNet101 neural network.\n\n    Args:\n        class_num (int): Class number.\n\n    Returns:\n        Cell, cell instance of ResNet101 neural network.\n\n    Examples:\n        >>> net = resnet101(1001)\n    \"\"\"\n    return ResNet(ResidualBlock,\n                  [3, 4, 23, 3],\n                  [64, 256, 512, 1024],\n                  [256, 512, 1024, 2048],\n                  [1, 2, 2, 2],\n                  class_num)\n\n"
  },
  {
    "path": "examples/common/networks/vgg/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the License);\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# httpwww.apache.orglicensesLICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an AS IS BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n"
  },
  {
    "path": "examples/common/networks/vgg/config.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nnetwork config setting, will be used in train.py and eval.py\n\"\"\"\nfrom easydict import EasyDict as edict\n\n# config for vgg16, cifar100\ncifar_cfg = edict({\n    \"num_classes\": 100,\n    \"lr\": 0.01,\n    \"lr_init\": 0.01,\n    \"lr_max\": 0.1,\n    \"lr_epochs\": '30,60,90,120',\n    \"lr_scheduler\": \"step\",\n    \"warmup_epochs\": 5,\n    \"batch_size\": 64,\n    \"max_epoch\": 100,\n    \"momentum\": 0.9,\n    \"weight_decay\": 5e-4,\n    \"loss_scale\": 1.0,\n    \"label_smooth\": 0,\n    \"label_smooth_factor\": 0,\n    \"buffer_size\": 10,\n    \"image_size\": '224,224',\n    \"pad_mode\": 'same',\n    \"padding\": 0,\n    \"has_bias\": False,\n    \"batch_norm\": True,\n    \"keep_checkpoint_max\": 10,\n    \"initialize_mode\": \"XavierUniform\",\n    \"has_dropout\": False\n})\n"
  },
  {
    "path": "examples/common/networks/vgg/crossentropy.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"define loss function for network\"\"\"\nfrom mindspore.nn.loss.loss import _Loss\nfrom mindspore.ops import operations as P\nfrom mindspore.ops import functional as F\nfrom mindspore import Tensor\nfrom mindspore.common import dtype as mstype\nimport mindspore.nn as nn\n\n\nclass CrossEntropy(_Loss):\n    \"\"\"the redefined loss function with SoftmaxCrossEntropyWithLogits\"\"\"\n\n    def __init__(self, smooth_factor=0., num_classes=1001):\n        super(CrossEntropy, self).__init__()\n        self.onehot = P.OneHot()\n        self.on_value = Tensor(1.0 - smooth_factor, mstype.float32)\n        self.off_value = Tensor(1.0 * smooth_factor / (num_classes - 1), mstype.float32)\n        self.ce = nn.SoftmaxCrossEntropyWithLogits()\n        self.mean = P.ReduceMean(False)\n\n    def construct(self, logit, label):\n        one_hot_label = self.onehot(label, F.shape(logit)[1], self.on_value, self.off_value)\n        loss = self.ce(logit, one_hot_label)\n        loss = self.mean(loss, 0)\n        return loss\n"
  },
  {
    "path": "examples/common/networks/vgg/linear_warmup.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nlinear warm up learning rate.\n\"\"\"\n\n\ndef linear_warmup_lr(current_step, warmup_steps, base_lr, init_lr):\n    lr_inc = (float(base_lr) - float(init_lr)) / float(warmup_steps)\n    lr = float(init_lr) + lr_inc*current_step\n    return lr\n"
  },
  {
    "path": "examples/common/networks/vgg/utils/__init__.py",
    "content": ""
  },
  {
    "path": "examples/common/networks/vgg/utils/util.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"Util class or function.\"\"\"\n\n\ndef get_param_groups(network):\n    \"\"\"Param groups for optimizer.\"\"\"\n    decay_params = []\n    no_decay_params = []\n    for x in network.trainable_params():\n        parameter_name = x.name\n        if parameter_name.endswith('.bias'):\n            # all bias not using weight decay\n            no_decay_params.append(x)\n        elif parameter_name.endswith('.gamma'):\n            # bn weight bias not using weight decay, be carefully for now x not include BN\n            no_decay_params.append(x)\n        elif parameter_name.endswith('.beta'):\n            # bn weight bias not using weight decay, be carefully for now x not include BN\n            no_decay_params.append(x)\n        else:\n            decay_params.append(x)\n\n    return [{'params': no_decay_params, 'weight_decay': 0.0}, {'params': decay_params}]\n"
  },
  {
    "path": "examples/common/networks/vgg/utils/var_init.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nInitialize.\n\"\"\"\nimport math\nfrom functools import reduce\nimport numpy as np\nimport mindspore.nn as nn\nfrom mindspore.common import initializer as init\n\n\ndef _calculate_gain(nonlinearity, param=None):\n    r\"\"\"\n    Return the recommended gain value for the given nonlinearity function.\n\n    The values are as follows:\n    ================= ====================================================\n    nonlinearity      gain\n    ================= ====================================================\n    Linear / Identity :math:`1`\n    Conv{1,2,3}D      :math:`1`\n    Sigmoid           :math:`1`\n    Tanh              :math:`\\frac{5}{3}`\n    ReLU              :math:`\\sqrt{2}`\n    Leaky Relu        :math:`\\sqrt{\\frac{2}{1 + \\text{negative\\_slope}^2}}`\n    ================= ====================================================\n\n    Args:\n        nonlinearity: the non-linear function\n        param: optional parameter for the non-linear function\n\n    Examples:\n        >>> gain = calculate_gain('leaky_relu', 0.2)  # leaky_relu with negative_slope=0.2\n    \"\"\"\n    linear_fns = ['linear', 'conv1d', 'conv2d', 'conv3d', 'conv_transpose1d', 'conv_transpose2d', 'conv_transpose3d']\n    if nonlinearity in linear_fns or nonlinearity == 'sigmoid':\n        return 1\n    if nonlinearity == 'tanh':\n        return 5.0 / 3\n    if nonlinearity == 'relu':\n        return math.sqrt(2.0)\n    if nonlinearity == 'leaky_relu':\n        if param is None:\n            negative_slope = 0.01\n        elif not isinstance(param, bool) and isinstance(param, int) or isinstance(param, float):\n            negative_slope = param\n        else:\n            raise ValueError(\"negative_slope {} not a valid number\".format(param))\n        return math.sqrt(2.0 / (1 + negative_slope**2))\n\n    raise ValueError(\"Unsupported nonlinearity {}\".format(nonlinearity))\n\n\ndef _assignment(arr, num):\n    \"\"\"Assign the value of `num` to `arr`.\"\"\"\n    if arr.shape == ():\n        arr = arr.reshape((1))\n        arr[:] = num\n        arr = arr.reshape(())\n    else:\n        if isinstance(num, np.ndarray):\n            arr[:] = num[:]\n        else:\n            arr[:] = num\n    return arr\n\n\ndef _calculate_in_and_out(arr):\n    \"\"\"\n    Calculate n_in and n_out.\n\n    Args:\n        arr (Array): Input array.\n\n    Returns:\n        Tuple, a tuple with two elements, the first element is `n_in` and the second element is `n_out`.\n    \"\"\"\n    dim = len(arr.shape)\n    if dim < 2:\n        raise ValueError(\"If initialize data with xavier uniform, the dimension of data must greater than 1.\")\n\n    n_in = arr.shape[1]\n    n_out = arr.shape[0]\n\n    if dim > 2:\n        counter = reduce(lambda x, y: x*y, arr.shape[2:])\n        n_in *= counter\n        n_out *= counter\n    return n_in, n_out\n\n\ndef _select_fan(array, mode):\n    mode = mode.lower()\n    valid_modes = ['fan_in', 'fan_out']\n    if mode not in valid_modes:\n        raise ValueError(\"Mode {} not supported, please use one of {}\".format(mode, valid_modes))\n\n    fan_in, fan_out = _calculate_in_and_out(array)\n    return fan_in if mode == 'fan_in' else fan_out\n\n\nclass KaimingInit(init.Initializer):\n    r\"\"\"\n    Base Class. Initialize the array with He kaiming algorithm.\n\n    Args:\n        a: the negative slope of the rectifier used after this layer (only\n            used with ``'leaky_relu'``)\n        mode: either ``'fan_in'`` (default) or ``'fan_out'``. Choosing ``'fan_in'``\n            preserves the magnitude of the variance of the weights in the\n            forward pass. Choosing ``'fan_out'`` preserves the magnitudes in the\n            backwards pass.\n        nonlinearity: the non-linear function, recommended to use only with\n            ``'relu'`` or ``'leaky_relu'`` (default).\n    \"\"\"\n    def __init__(self, a=0, mode='fan_in', nonlinearity='leaky_relu'):\n        super(KaimingInit, self).__init__()\n        self.mode = mode\n        self.gain = _calculate_gain(nonlinearity, a)\n    def _initialize(self, arr):\n        pass\n\n\nclass KaimingUniform(KaimingInit):\n    r\"\"\"\n    Initialize the array with He kaiming uniform algorithm. The resulting tensor will\n    have values sampled from :math:`\\mathcal{U}(-\\text{bound}, \\text{bound})` where\n\n    .. math::\n        \\text{bound} = \\text{gain} \\times \\sqrt{\\frac{3}{\\text{fan\\_mode}}}\n\n    Input:\n        arr (Array): The array to be assigned.\n\n    Returns:\n        Array, assigned array.\n\n    Examples:\n        >>> w = np.empty(3, 5)\n        >>> KaimingUniform(w, mode='fan_in', nonlinearity='relu')\n    \"\"\"\n\n    def _initialize(self, arr):\n        fan = _select_fan(arr, self.mode)\n        bound = math.sqrt(3.0)*self.gain / math.sqrt(fan)\n        np.random.seed(0)\n        data = np.random.uniform(-bound, bound, arr.shape)\n\n        _assignment(arr, data)\n\n\nclass KaimingNormal(KaimingInit):\n    r\"\"\"\n    Initialize the array with He kaiming normal algorithm. The resulting tensor will\n    have values sampled from :math:`\\mathcal{N}(0, \\text{std}^2)` where\n\n    .. math::\n        \\text{std} = \\frac{\\text{gain}}{\\sqrt{\\text{fan\\_mode}}}\n\n    Input:\n        arr (Array): The array to be assigned.\n\n    Returns:\n        Array, assigned array.\n\n    Examples:\n        >>> w = np.empty(3, 5)\n        >>> KaimingNormal(w, mode='fan_out', nonlinearity='relu')\n    \"\"\"\n\n    def _initialize(self, arr):\n        fan = _select_fan(arr, self.mode)\n        std = self.gain / math.sqrt(fan)\n        np.random.seed(0)\n        data = np.random.normal(0, std, arr.shape)\n\n        _assignment(arr, data)\n\n\ndef default_recurisive_init(custom_cell):\n    \"\"\"default_recurisive_init\"\"\"\n    for _, cell in custom_cell.cells_and_names():\n        if isinstance(cell, nn.Conv2d):\n            cell.weight.default_input = init.initializer(KaimingUniform(a=math.sqrt(5)),\n                                                         cell.weight.shape,\n                                                         cell.weight.dtype)\n            if cell.bias is not None:\n                fan_in, _ = _calculate_in_and_out(cell.weight)\n                bound = 1 / math.sqrt(fan_in)\n                np.random.seed(0)\n                cell.bias.default_input = init.initializer(init.Uniform(bound),\n                                                           cell.bias.shape,\n                                                           cell.bias.dtype)\n        elif isinstance(cell, nn.Dense):\n            cell.weight.default_input = init.initializer(KaimingUniform(a=math.sqrt(5)),\n                                                         cell.weight.shape,\n                                                         cell.weight.dtype)\n            if cell.bias is not None:\n                fan_in, _ = _calculate_in_and_out(cell.weight)\n                bound = 1 / math.sqrt(fan_in)\n                np.random.seed(0)\n                cell.bias.default_input = init.initializer(init.Uniform(bound),\n                                                           cell.bias.shape,\n                                                           cell.bias.dtype)\n        elif isinstance(cell, (nn.BatchNorm2d, nn.BatchNorm1d)):\n            pass\n"
  },
  {
    "path": "examples/common/networks/vgg/vgg.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nImage classifiation.\n\"\"\"\nimport math\nimport mindspore.nn as nn\nimport mindspore.common.dtype as mstype\nfrom mindspore.common import initializer as init\nfrom mindspore.common.initializer import initializer\nfrom .utils.var_init import default_recurisive_init, KaimingNormal\n\n\ndef _make_layer(base, args, batch_norm):\n    \"\"\"Make stage network of VGG.\"\"\"\n    layers = []\n    in_channels = 3\n    for v in base:\n        if v == 'M':\n            layers += [nn.MaxPool2d(kernel_size=2, stride=2)]\n        else:\n            weight_shape = (v, in_channels, 3, 3)\n            weight = initializer('XavierUniform', shape=weight_shape, dtype=mstype.float32).to_tensor()\n            if args.initialize_mode == \"KaimingNormal\":\n                weight = 'normal'\n            conv2d = nn.Conv2d(in_channels=in_channels,\n                               out_channels=v,\n                               kernel_size=3,\n                               padding=args.padding,\n                               pad_mode=args.pad_mode,\n                               has_bias=args.has_bias,\n                               weight_init=weight)\n            if batch_norm:\n                layers += [conv2d, nn.BatchNorm2d(v), nn.ReLU()]\n            else:\n                layers += [conv2d, nn.ReLU()]\n            in_channels = v\n    return nn.SequentialCell(layers)\n\n\nclass Vgg(nn.Cell):\n    \"\"\"\n    VGG network definition.\n\n    Args:\n        base (list): Configuration for different layers, mainly the channel number of Conv layer.\n        num_classes (int): Class numbers. Default: 1000.\n        batch_norm (bool): Whether to do the batchnorm. Default: False.\n        batch_size (int): Batch size. Default: 1.\n\n    Returns:\n        Tensor, infer output tensor.\n\n    Examples:\n        >>> Vgg([64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],\n        >>>     num_classes=1000, batch_norm=False, batch_size=1)\n    \"\"\"\n\n    def __init__(self, base, num_classes=1000, batch_norm=False, batch_size=1, args=None, phase=\"train\"):\n        super(Vgg, self).__init__()\n        _ = batch_size\n        self.layers = _make_layer(base, args, batch_norm=batch_norm)\n        self.flatten = nn.Flatten()\n        dropout_ratio = 0.5\n        if not args.has_dropout or phase == \"test\":\n            dropout_ratio = 1.0\n        self.classifier = nn.SequentialCell([\n            nn.Dense(512*7*7, 4096),\n            nn.ReLU(),\n            nn.Dropout(dropout_ratio),\n            nn.Dense(4096, 4096),\n            nn.ReLU(),\n            nn.Dropout(dropout_ratio),\n            nn.Dense(4096, num_classes)])\n        if args.initialize_mode == \"KaimingNormal\":\n            default_recurisive_init(self)\n            self.custom_init_weight()\n\n    def construct(self, x):\n        x = self.layers(x)\n        x = self.flatten(x)\n        x = self.classifier(x)\n        return x\n\n    def custom_init_weight(self):\n        \"\"\"\n        Init the weight of Conv2d and Dense in the net.\n        \"\"\"\n        for _, cell in self.cells_and_names():\n            if isinstance(cell, nn.Conv2d):\n                cell.weight.default_input = init.initializer(\n                    KaimingNormal(a=math.sqrt(5), mode='fan_out', nonlinearity='relu'),\n                    cell.weight.shape, cell.weight.dtype)\n                if cell.bias is not None:\n                    cell.bias.default_input = init.initializer(\n                        'zeros', cell.bias.shape, cell.bias.dtype)\n            elif isinstance(cell, nn.Dense):\n                cell.weight.default_input = init.initializer(\n                    init.Normal(0.01), cell.weight.shape, cell.weight.dtype)\n                if cell.bias is not None:\n                    cell.bias.default_input = init.initializer(\n                        'zeros', cell.bias.shape, cell.bias.dtype)\n\n\ncfg = {\n    '11': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],\n    '13': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],\n    '16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],\n    '19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'],\n}\n\n\ndef vgg16(num_classes=1000, args=None, phase=\"train\"):\n    \"\"\"\n    Get Vgg16 neural network with batch normalization.\n\n    Args:\n        num_classes (int): Class numbers. Default: 1000.\n        args(namespace): param for net init.\n        phase(str): train or test mode.\n\n    Returns:\n        Cell, cell instance of Vgg16 neural network with batch normalization.\n\n    Examples:\n        >>> vgg16(num_classes=1000, args=args)\n    \"\"\"\n\n    net = Vgg(cfg['16'], num_classes=num_classes, args=args, batch_norm=args.batch_norm, phase=phase)\n    return net\n"
  },
  {
    "path": "examples/common/networks/vgg/warmup_cosine_annealing_lr.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nwarm up cosine annealing learning rate.\n\"\"\"\nimport math\nimport numpy as np\n\nfrom .linear_warmup import linear_warmup_lr\n\n\ndef warmup_cosine_annealing_lr(lr, steps_per_epoch, warmup_epochs, max_epoch, t_max, eta_min=0):\n    \"\"\"warm up cosine annealing learning rate.\"\"\"\n    base_lr = lr\n    warmup_init_lr = 0\n    total_steps = int(max_epoch*steps_per_epoch)\n    warmup_steps = int(warmup_epochs*steps_per_epoch)\n\n    lr_each_step = []\n    for i in range(total_steps):\n        last_epoch = i // steps_per_epoch\n        if i < warmup_steps:\n            lr = linear_warmup_lr(i + 1, warmup_steps, base_lr, warmup_init_lr)\n        else:\n            lr = eta_min + (base_lr - eta_min)*(1. + math.cos(math.pi*last_epoch / t_max)) / 2\n        lr_each_step.append(lr)\n\n    return np.array(lr_each_step).astype(np.float32)\n"
  },
  {
    "path": "examples/common/networks/vgg/warmup_step_lr.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nwarm up step learning rate.\n\"\"\"\nfrom collections import Counter\nimport numpy as np\n\nfrom .linear_warmup import linear_warmup_lr\n\n\ndef lr_steps(global_step, lr_init, lr_max, warmup_epochs, total_epochs, steps_per_epoch):\n    \"\"\"Set learning rate.\"\"\"\n    lr_each_step = []\n    total_steps = steps_per_epoch*total_epochs\n    warmup_steps = steps_per_epoch*warmup_epochs\n    if warmup_steps != 0:\n        inc_each_step = (float(lr_max) - float(lr_init)) / float(warmup_steps)\n    else:\n        inc_each_step = 0\n    for i in range(total_steps):\n        if i < warmup_steps:\n            lr_value = float(lr_init) + inc_each_step*float(i)\n        else:\n            base = (1.0 - (float(i) - float(warmup_steps)) / (float(total_steps) - float(warmup_steps)))\n            lr_value = float(lr_max)*base*base\n            if lr_value < 0.0:\n                lr_value = 0.0\n        lr_each_step.append(lr_value)\n\n    current_step = global_step\n    lr_each_step = np.array(lr_each_step).astype(np.float32)\n    learning_rate = lr_each_step[current_step:]\n\n    return learning_rate\n\n\ndef warmup_step_lr(lr, lr_epochs, steps_per_epoch, warmup_epochs, max_epoch, gamma=0.1):\n    \"\"\"warmup_step_lr\"\"\"\n    base_lr = lr\n    warmup_init_lr = 0\n    total_steps = int(max_epoch*steps_per_epoch)\n    warmup_steps = int(warmup_epochs*steps_per_epoch)\n    milestones = lr_epochs\n    milestones_steps = []\n    for milestone in milestones:\n        milestones_step = milestone*steps_per_epoch\n        milestones_steps.append(milestones_step)\n\n    lr_each_step = []\n    lr = base_lr\n    milestones_steps_counter = Counter(milestones_steps)\n    for i in range(total_steps):\n        if i < warmup_steps:\n            lr = linear_warmup_lr(i + 1, warmup_steps, base_lr, warmup_init_lr)\n        else:\n            lr = lr*gamma**milestones_steps_counter[i]\n        lr_each_step.append(lr)\n\n    return np.array(lr_each_step).astype(np.float32)\n\n\ndef multi_step_lr(lr, milestones, steps_per_epoch, max_epoch, gamma=0.1):\n    return warmup_step_lr(lr, milestones, steps_per_epoch, 0, max_epoch, gamma=gamma)\n\n\ndef step_lr(lr, epoch_size, steps_per_epoch, max_epoch, gamma=0.1):\n    lr_epochs = []\n    for i in range(1, max_epoch):\n        if i % epoch_size == 0:\n            lr_epochs.append(i)\n    return multi_step_lr(lr, lr_epochs, steps_per_epoch, max_epoch, gamma=gamma)\n"
  },
  {
    "path": "examples/community/__init__.py",
    "content": ""
  },
  {
    "path": "examples/community/face_adversarial_attack/README.md",
    "content": "\n# 人脸识别物理对抗攻击\n\n## 描述\n\n本项目是基于MindSpore框架对人脸识别模型的物理对抗攻击，通过生成对抗口罩，使人脸佩戴后实现有目标攻击和非目标攻击。\n\n## 模型结构\n\n采用华为MindSpore官方训练的FaceRecognition模型\nhttps://www.mindspore.cn/resources/hub/details?MindSpore/1.7/facerecognition_ms1mv2\n\n## 环境要求\n\nmindspore>=1.7，硬件平台为GPU。\n\n## 脚本说明\n\n```markdown\n├── readme.md\n├── photos\n│   ├── adv_input //对抗图像\n│   ├── input //输入图像\n│   └── target //目标图像\n├── outputs //训练后的图像\n├── adversarial_attack.py  //训练脚本\n│── example_non_target_attack.py  //无目标攻击训练\n│── example_target_attack.py  //有目标攻击训练\n│── loss_design.py  //训练优化设置\n└── test.py  //评估攻击效果\n```\n\n## 模型调用\n\n方法一:\n\n```python\n#基于mindspore_hub库调用FaceRecognition模型\nimport mindspore_hub as mshub\nfrom mindspore import context\ndef get_model():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"GPU\", device_id=0)\n    model = \"mindspore/1.7/facerecognition_ms1mv2\"\n    network = mshub.load(model)\n    network.set_train(False)\n    return network\n```\n\n方法二:\n\n```text\n利用MindSpore代码仓中的 <https://gitee.com/mindspore/models/blob/master/research/cv/FaceRecognition/eval.py> 的get_model函数加载模型\n```\n\n## 训练过程\n\n有目标攻击:\n\n```shell\ncd face_adversarial_attack/\npython example_target_attack.py\n```\n\n非目标攻击:\n\n```shell\ncd face_adversarial_attack/\npython example_non_target_attack.py\n```\n\n## 默认训练参数\n\noptimizer=adam, learning rate=0.01, weight_decay=0.0001, epoch=2000\n\n## 评估过程\n\n评估方法一:\n\n```shell\nadversarial_attack.FaceAdversarialAttack.test_non_target_attack()\nadversarial_attack.FaceAdversarialAttack.test_target_attack()\n```\n\n评估方法二:\n\n```shell\ncd face_adversarial_attack/\npython test.py\n ```\n\n## 实验结果\n\n有目标攻击:\n\n```text\ninput_label: 60\ntarget_label: 345\nThe confidence of the input image on the input label: 26.67\nThe confidence of the input image on the target label: 0.95\n================================\nadversarial_label: 345\nThe confidence of the adversarial sample on the correct label: 1.82\nThe confidence of the adversarial sample on the target label: 10.96\ninput_label: 60, target_label: 345, adversarial_label: 345\n\nphotos中是有目标攻击的实验结果\n```\n\n非目标攻击:\n\n```text\ninput_label: 60\nThe confidence of the input image on the input label: 25.16\n================================\nadversarial_label: 251\nThe confidence of the adversarial sample on the correct label: 9.52\nThe confidence of the adversarial sample on the adversarial label: 60.96\ninput_label: 60, adversarial_label: 251\n```\n"
  },
  {
    "path": "examples/community/face_adversarial_attack/adversarial_attack.py",
    "content": "# Copyright 2022 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"Train set\"\"\"\nimport os\nimport re\nimport numpy as np\nimport face_recognition as fr\nimport face_recognition_models as frm\nimport dlib\nfrom PIL import Image, ImageDraw\nimport mindspore\nimport mindspore.dataset.vision.py_transforms as P\nfrom mindspore.dataset.vision.py_transforms import ToPIL as ToPILImage\nfrom mindspore.dataset.vision.py_transforms import ToTensor\nfrom mindspore import Parameter, ops, nn, Tensor\nfrom loss_design import MyTrainOneStepCell, MyWithLossCellTargetAttack, \\\n    MyWithLossCellNonTargetAttack, FaceLossTargetAttack, FaceLossNoTargetAttack\n\n\nclass FaceAdversarialAttack():\n    \"\"\"\n    Class used to create adversarial facial recognition attacks.\n\n    Args:\n        input_img (numpy.ndarray): The input image.\n        target_img (numpy.ndarray): The target image.\n        seed (int): optional Sets custom seed for reproducibility. Default is generated randomly.\n        net (mindspore.Model): face recognition model.\n    \"\"\"\n    def __init__(self, input_img, target_img, net, seed=None):\n        if seed is not None:\n            np.random.seed(seed)\n        self.mean = Tensor([0.485, 0.456, 0.406])\n        self.std = Tensor([0.229, 0.224, 0.225])\n        self.expand_dims = mindspore.ops.ExpandDims()\n        self.imageize = ToPILImage()\n        self.tensorize = ToTensor()\n        self.normalize = P.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n        self.resnet = net\n        self.input_tensor = Tensor(self.normalize(self.tensorize(input_img)))\n        self.target_tensor = Tensor(self.normalize(self.tensorize(target_img)))\n        self.input_emb = self.resnet(self.expand_dims(self.input_tensor, 0))\n        self.target_emb = self.resnet(self.expand_dims(self.target_tensor, 0))\n        self.adversarial_emb = None\n        self.mask_tensor = create_mask(input_img)\n        self.ref = self.mask_tensor\n        self.pm = Parameter(self.mask_tensor)\n        self.opt = nn.Adam([self.pm], learning_rate=0.01, weight_decay=0.0001)\n\n    def train(self, attack_method):\n        \"\"\"\n        Optimized adversarial image.\n\n        Args:\n            attack_method (String) : Including target attack and non_target attack.\n\n        Returns:\n            Tensor, adversarial image.\n            Tensor, mask image.\n        \"\"\"\n\n        if attack_method == \"non_target_attack\":\n            loss = FaceLossNoTargetAttack()\n            net_with_criterion = MyWithLossCellNonTargetAttack(self.resnet, loss, self.input_tensor)\n        if attack_method == \"target_attack\":\n            loss = FaceLossTargetAttack(self.target_emb)\n            net_with_criterion = MyWithLossCellTargetAttack(self.resnet, loss, self.input_tensor)\n\n        train_net = MyTrainOneStepCell(net_with_criterion, self.opt)\n\n        for i in range(2000):\n\n            self.mask_tensor = Tensor(self.pm)\n\n            loss = train_net(self.mask_tensor)\n\n            print(\"epoch %d ,loss: %f \\n \" % (i, loss.asnumpy().item()))\n\n            self.mask_tensor = ops.clip_by_value(\n                self.mask_tensor, Tensor(0, mindspore.float32), Tensor(1, mindspore.float32))\n\n        adversarial_tensor = apply(\n            self.input_tensor,\n            (self.mask_tensor - self.mean[:, None, None]) / self.std[:, None, None],\n            self.ref)\n\n        adversarial_tensor = self._reverse_norm(adversarial_tensor)\n        processed_input_tensor = self._reverse_norm(self.input_tensor)\n        processed_target_tensor = self._reverse_norm(self.target_tensor)\n\n        return {\n            \"adversarial_tensor\": adversarial_tensor,\n            \"mask_tensor\": self.mask_tensor,\n            \"processed_input_tensor\": processed_input_tensor,\n            \"processed_target_tensor\": processed_target_tensor\n        }\n\n    def test_target_attack(self):\n        \"\"\"\n        The model is used to test the recognition ability of adversarial images under target attack.\n        \"\"\"\n\n        adversarial_tensor = apply(\n            self.input_tensor,\n            (self.mask_tensor - self.mean[:, None, None]) / self.std[:, None, None],\n            self.ref)\n\n        self.adversarial_emb = self.resnet(self.expand_dims(adversarial_tensor, 0))\n        self.input_emb = self.resnet(self.expand_dims(self.input_tensor, 0))\n        self.target_emb = self.resnet(self.expand_dims(self.target_tensor, 0))\n\n        adversarial_index = np.argmax(self.adversarial_emb.asnumpy())\n        target_index = np.argmax(self.target_emb.asnumpy())\n        input_index = np.argmax(self.input_emb.asnumpy())\n\n        print(\"input_label:\", input_index)\n        print(\"target_label:\", target_index)\n        print(\"The confidence of the input image on the input label:\", self.input_emb.asnumpy()[0][input_index])\n        print(\"The confidence of the input image on the target label:\", self.input_emb.asnumpy()[0][target_index])\n        print(\"================================\")\n        print(\"adversarial_label:\", adversarial_index)\n        print(\"The confidence of the adversarial sample on the correct label:\",\n              self.adversarial_emb.asnumpy()[0][input_index])\n        print(\"The confidence of the adversarial sample on the target label:\",\n              self.adversarial_emb.asnumpy()[0][target_index])\n        print(\"input_label: %d, target_label: %d, adversarial_label: %d\"\n              % (input_index, target_index, adversarial_index))\n\n    def test_non_target_attack(self):\n        \"\"\"\n        The model is used to test the recognition ability of adversarial images under non_target attack.\n        \"\"\"\n\n        adversarial_tensor = apply(\n            self.input_tensor,\n            (self.mask_tensor - self.mean[:, None, None]) / self.std[:, None, None],\n            self.ref)\n\n        self.adversarial_emb = self.resnet(self.expand_dims(adversarial_tensor, 0))\n        self.input_emb = self.resnet(self.expand_dims(self.input_tensor, 0))\n\n        adversarial_index = np.argmax(self.adversarial_emb.asnumpy())\n        input_index = np.argmax(self.input_emb.asnumpy())\n\n        print(\"input_label:\", input_index)\n        print(\"The confidence of the input image on the input label:\", self.input_emb.asnumpy()[0][input_index])\n        print(\"================================\")\n        print(\"adversarial_label:\", adversarial_index)\n        print(\"The confidence of the adversarial sample on the correct label:\",\n              self.adversarial_emb.asnumpy()[0][input_index])\n        print(\"The confidence of the adversarial sample on the adversarial label:\",\n              self.adversarial_emb.asnumpy()[0][adversarial_index])\n        print(\n            \"input_label: %d, adversarial_label: %d\" % (input_index, adversarial_index))\n\n    def _reverse_norm(self, image_tensor):\n        \"\"\"\n        Reverses normalization for a given image_tensor.\n\n        Args:\n            image_tensor (Tensor): Tensor.\n\n        Returns:\n            Tensor, image.\n        \"\"\"\n        tensor = image_tensor * self.std[:, None, None] + self.mean[:, None, None]\n        return tensor\n\n\ndef apply(image_tensor, mask_tensor, reference_tensor):\n    \"\"\"\n    Apply a mask over an image.\n\n    Args:\n        image_tensor (Tensor): Canvas to be used to apply mask on.\n        mask_tensor (Tensor): Mask to apply over the image.\n        reference_tensor (Tensor): Used to reference mask boundaries\n\n    Returns:\n        Tensor, image.\n    \"\"\"\n    tensor = mindspore.numpy.where((reference_tensor == 0), image_tensor, mask_tensor)\n\n    return tensor\n\n\ndef create_mask(face_image):\n    \"\"\"\n    Create mask image.\n\n    Args:\n        face_image (PIL.Image): image of a detected face.\n\n    Returns:\n        mask_tensor : a mask image.\n    \"\"\"\n\n    mask = Image.new('RGB', face_image.size, color=(0, 0, 0))\n    d = ImageDraw.Draw(mask)\n    landmarks = fr.face_landmarks(np.array(face_image))\n    area = [landmark\n            for landmark in landmarks[0]['chin']\n            if landmark[1] > max(landmarks[0]['nose_tip'])[1]]\n    area.append(landmarks[0]['nose_bridge'][1])\n    d.polygon(area, fill=(255, 255, 255))\n    mask = np.array(mask)\n    mask = mask.astype(np.float32)\n\n    for i in range(mask.shape[0]):\n        for j in range(mask.shape[1]):\n            for k in range(mask.shape[2]):\n                if mask[i][j][k] == 255.:\n                    mask[i][j][k] = 0.5\n                else:\n                    mask[i][j][k] = 0\n\n    mask_tensor = Tensor(mask)\n    mask_tensor = mask_tensor.swapaxes(0, 2).swapaxes(1, 2)\n    mask_tensor.requires_grad = True\n    return mask_tensor\n\n\ndef detect_face(image):\n    \"\"\"\n    Face detection and alignment process using dlib library.\n\n    Args:\n        image (numpy.ndarray): image file location.\n\n    Returns:\n        face_image : Resized face image.\n    \"\"\"\n    dlib_detector = dlib.get_frontal_face_detector()\n    dlib_shape_predictor = dlib.shape_predictor(frm.pose_predictor_model_location())\n    dlib_image = dlib.load_rgb_image(image)\n    detections = dlib_detector(dlib_image, 1)\n\n    dlib_faces = dlib.full_object_detections()\n    for det in detections:\n        dlib_faces.append(dlib_shape_predictor(dlib_image, det))\n    face_image = Image.fromarray(dlib.get_face_chip(dlib_image, dlib_faces[0], size=112))\n\n    return face_image\n\n\ndef load_data(data):\n    \"\"\"\n    An auxiliary function that loads image data.\n\n    Args:\n        data (String): The path to the given data.\n\n    Returns:\n        list : Resize list of face images.\n    \"\"\"\n    image_files = [f for f in os.listdir(data) if re.search(r'.*\\.(jpe?g|png)', f)]\n    image_files_locs = [os.path.join(data, f) for f in image_files]\n\n    image_list = []\n    for img in image_files_locs:\n        image_list.append(detect_face(img))\n\n    return image_list\n"
  },
  {
    "path": "examples/community/face_adversarial_attack/example_non_target_attack.py",
    "content": "# Copyright 2022 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"non target attack\"\"\"\nimport numpy as np\nimport matplotlib.image as mp\nfrom mindspore import context\nimport adversarial_attack\nfrom FaceRecognition.eval import get_model\n\ncontext.set_context(mode=context.GRAPH_MODE, device_target=\"GPU\")\n\n\nif __name__ == '__main__':\n\n    inputs = adversarial_attack.load_data('photos/input/')\n    targets = adversarial_attack.load_data('photos/target/')\n\n    net = get_model()\n    adversarial = adversarial_attack.FaceAdversarialAttack(inputs[0], targets[0], net)\n    ATTACK_METHOD = \"non_target_attack\"\n\n    tensor_dict = adversarial.train(attack_method=ATTACK_METHOD)\n\n    mp.imsave('./outputs/adversarial_example.jpg',\n              np.transpose(tensor_dict.get(\"adversarial_tensor\").asnumpy(), (1, 2, 0)))\n    mp.imsave('./outputs/mask.jpg',\n              np.transpose(tensor_dict.get(\"mask_tensor\").asnumpy(), (1, 2, 0)))\n    mp.imsave('./outputs/input_image.jpg',\n              np.transpose(tensor_dict.get(\"processed_input_tensor\").asnumpy(), (1, 2, 0)))\n    mp.imsave('./outputs/target_image.jpg',\n              np.transpose(tensor_dict.get(\"processed_target_tensor\").asnumpy(), (1, 2, 0)))\n\n    adversarial.test_non_target_attack()\n"
  },
  {
    "path": "examples/community/face_adversarial_attack/example_target_attack.py",
    "content": "# Copyright 2022 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"target attack\"\"\"\nimport numpy as np\nimport matplotlib.image as mp\nfrom mindspore import context\nimport adversarial_attack\nfrom FaceRecognition.eval import get_model\n\ncontext.set_context(mode=context.GRAPH_MODE, device_target=\"GPU\")\n\n\nif __name__ == '__main__':\n\n    inputs = adversarial_attack.load_data('photos/input/')\n    targets = adversarial_attack.load_data('photos/target/')\n\n    net = get_model()\n    adversarial = adversarial_attack.FaceAdversarialAttack(inputs[0], targets[0], net)\n\n    ATTACK_METHOD = \"target_attack\"\n\n    tensor_dict = adversarial.train(attack_method=ATTACK_METHOD)\n\n    mp.imsave('./outputs/adversarial_example.jpg',\n              np.transpose(tensor_dict.get(\"adversarial_tensor\").asnumpy(), (1, 2, 0)))\n    mp.imsave('./outputs/mask.jpg',\n              np.transpose(tensor_dict.get(\"mask_tensor\").asnumpy(), (1, 2, 0)))\n    mp.imsave('./outputs/input_image.jpg',\n              np.transpose(tensor_dict.get(\"processed_input_tensor\").asnumpy(), (1, 2, 0)))\n    mp.imsave('./outputs/target_image.jpg',\n              np.transpose(tensor_dict.get(\"processed_target_tensor\").asnumpy(), (1, 2, 0)))\n\n    adversarial.test_target_attack()\n"
  },
  {
    "path": "examples/community/face_adversarial_attack/loss_design.py",
    "content": "# Copyright 2022 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"optimization Settings\"\"\"\nimport mindspore\nfrom mindspore import ops, nn, Tensor\nfrom mindspore.dataset.vision.py_transforms import ToTensor\nimport mindspore.dataset.vision.py_transforms as P\n\n\nclass MyTrainOneStepCell(nn.TrainOneStepCell):\n    \"\"\"\n    Encapsulation class of network training.\n\n    Append an optimizer to the training network after that the construct\n    function can be called to create the backward graph.\n\n    Args:\n        network (Cell): The training network. Note that loss function should have been added.\n        optimizer (Optimizer): Optimizer for updating the weights.\n        sens (Number): The adjust parameter. Default: 1.0.\n    \"\"\"\n\n    def __init__(self, network, optimizer, sens=1.0):\n        super(MyTrainOneStepCell, self).__init__(network, optimizer, sens)\n        self.grad = ops.composite.GradOperation(get_all=True, sens_param=False)\n\n    def construct(self, *inputs):\n        \"\"\"Defines the computation performed.\"\"\"\n        loss = self.network(*inputs)\n        grads = self.grad(self.network)(*inputs)\n        self.optimizer(grads)\n        return loss\n\n\nclass MyWithLossCellTargetAttack(nn.Cell):\n    \"\"\"The loss function defined by the target attack\"\"\"\n    def __init__(self, net, loss_fn, input_tensor):\n        super(MyWithLossCellTargetAttack, self).__init__(auto_prefix=False)\n        self.net = net\n        self._loss_fn = loss_fn\n        self.std = Tensor([0.229, 0.224, 0.225])\n        self.mean = Tensor([0.485, 0.456, 0.406])\n        self.expand_dims = mindspore.ops.ExpandDims()\n        self.normalize = P.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n        self.tensorize = ToTensor()\n        self.input_tensor = input_tensor\n        self.input_emb = self.net(self.expand_dims(self.input_tensor, 0))\n\n    @property\n    def backbone_network(self):\n        return self.net\n\n    def construct(self, mask_tensor):\n        ref = mask_tensor\n        adversarial_tensor = mindspore.numpy.where(\n            (ref == 0),\n            self.input_tensor,\n            (mask_tensor - self.mean[:, None, None]) / self.std[:, None, None])\n        adversarial_emb = self.net(self.expand_dims(adversarial_tensor, 0))\n        loss = self._loss_fn(adversarial_emb)\n        return loss\n\n\nclass MyWithLossCellNonTargetAttack(nn.Cell):\n    \"\"\"The loss function defined by the non target attack\"\"\"\n    def __init__(self, net, loss_fn, input_tensor):\n        super(MyWithLossCellNonTargetAttack, self).__init__(auto_prefix=False)\n        self.net = net\n        self._loss_fn = loss_fn\n        self.std = Tensor([0.229, 0.224, 0.225])\n        self.mean = Tensor([0.485, 0.456, 0.406])\n        self.expand_dims = mindspore.ops.ExpandDims()\n        self.normalize = P.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n        self.tensorize = ToTensor()\n        self.input_tensor = input_tensor\n        self.input_emb = self.net(self.expand_dims(self.input_tensor, 0))\n\n    @property\n    def backbone_network(self):\n        return self.net\n\n    def construct(self, mask_tensor):\n        ref = mask_tensor\n        adversarial_tensor = mindspore.numpy.where(\n            (ref == 0),\n            self.input_tensor,\n            (mask_tensor - self.mean[:, None, None]) / self.std[:, None, None])\n        adversarial_emb = self.net(self.expand_dims(adversarial_tensor, 0))\n        loss = self._loss_fn(adversarial_emb, self.input_emb)\n        return loss\n\n\nclass FaceLossTargetAttack(nn.Cell):\n    \"\"\"The loss function of the target attack\"\"\"\n\n    def __init__(self, target_emb):\n        super(FaceLossTargetAttack, self).__init__()\n        self.uniformreal = ops.UniformReal(seed=2)\n        self.sum = ops.ReduceSum(keep_dims=False)\n        self.norm = nn.Norm(keep_dims=True)\n        self.zeroslike = ops.ZerosLike()\n        self.concat_op1 = ops.Concat(1)\n        self.concat_op2 = ops.Concat(2)\n        self.pow = ops.Pow()\n        self.reduce_sum = ops.operations.ReduceSum()\n        self.target_emb = target_emb\n        self.abs = ops.Abs()\n        self.reduce_mean = ops.ReduceMean()\n\n    def construct(self, adversarial_emb):\n        prod_sum = self.reduce_sum(adversarial_emb * self.target_emb, (1,))\n        square1 = self.reduce_sum(ops.functional.square(adversarial_emb), (1,))\n        square2 = self.reduce_sum(ops.functional.square(self.target_emb), (1,))\n        denom = ops.functional.sqrt(square1) * ops.functional.sqrt(square2)\n        loss = -(prod_sum / denom)\n        return loss\n\n\nclass FaceLossNoTargetAttack(nn.Cell):\n    \"\"\"The loss function of the non-target attack\"\"\"\n\n    def __init__(self):\n        \"\"\"Initialization\"\"\"\n        super(FaceLossNoTargetAttack, self).__init__()\n        self.uniformreal = ops.UniformReal(seed=2)\n        self.sum = ops.ReduceSum(keep_dims=False)\n        self.norm = nn.Norm(keep_dims=True)\n        self.zeroslike = ops.ZerosLike()\n        self.concat_op1 = ops.Concat(1)\n        self.concat_op2 = ops.Concat(2)\n        self.pow = ops.Pow()\n        self.reduce_sum = ops.operations.ReduceSum()\n        self.abs = ops.Abs()\n        self.reduce_mean = ops.ReduceMean()\n\n    def construct(self, adversarial_emb, input_emb):\n        prod_sum = self.reduce_sum(adversarial_emb * input_emb, (1,))\n        square1 = self.reduce_sum(ops.functional.square(adversarial_emb), (1,))\n        square2 = self.reduce_sum(ops.functional.square(input_emb), (1,))\n        denom = ops.functional.sqrt(square1) * ops.functional.sqrt(square2)\n        loss = prod_sum / denom\n        return loss\n"
  },
  {
    "path": "examples/community/face_adversarial_attack/test.py",
    "content": "# Copyright 2022 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"test\"\"\"\nimport numpy as np\nfrom mindspore import context, Tensor\nimport mindspore\nfrom mindspore.dataset.vision.py_transforms import ToTensor\nimport mindspore.dataset.vision.py_transforms as P\nfrom FaceRecognition.eval import get_model\nimport adversarial_attack\n\ncontext.set_context(mode=context.GRAPH_MODE, device_target=\"GPU\")\n\nif __name__ == '__main__':\n\n    image = adversarial_attack.load_data('photos/adv_input/')\n    inputs = adversarial_attack.load_data('photos/input/')\n    targets = adversarial_attack.load_data('photos/target/')\n\n    tensorize = ToTensor()\n    normalize = P.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n    expand_dims = mindspore.ops.ExpandDims()\n    mean = Tensor([0.485, 0.456, 0.406])\n    std = Tensor([0.229, 0.224, 0.225])\n\n    resnet = get_model()\n\n    adv = Tensor(normalize(tensorize(image[0])))\n    input_tensor = Tensor(normalize(tensorize(inputs[0])))\n    target_tensor = Tensor(normalize(tensorize(targets[0])))\n\n    adversarial_emb = resnet(expand_dims(adv, 0))\n    input_emb = resnet(expand_dims(input_tensor, 0))\n    target_emb = resnet(expand_dims(target_tensor, 0))\n\n    adversarial_index = np.argmax(adversarial_emb.asnumpy())\n    target_index = np.argmax(target_emb.asnumpy())\n    input_index = np.argmax(input_emb.asnumpy())\n\n    print(\"input_label:\", input_index)\n    print(\"The confidence of the input image on the input label:\", input_emb.asnumpy()[0][input_index])\n    print(\"================================\")\n    print(\"adversarial_label:\", adversarial_index)\n    print(\"The confidence of the adversarial sample on the correct label:\", adversarial_emb.asnumpy()[0][input_index])\n    print(\"The confidence of the adversarial sample on the adversarial label:\",\n          adversarial_emb.asnumpy()[0][adversarial_index])\n    print(\"input_label:%d, adversarial_label:%d\" % (input_index, adversarial_index))\n"
  },
  {
    "path": "examples/community/query_attack_detector/README.md",
    "content": "# 基于相似度的对抗样本检测\r\n\r\n## 描述\r\n\r\n本算法主要针对黑盒查询攻击生成的对抗样本进行检测。由于攻击过程往往生成大量相似的查询图片，如果某个查询与之前的查询相似度大于一定阈值，则判定为攻击。\r\n\r\n## 环境要求\r\n\r\nMindspore >= 1.9，\r\n本算法为模型无关，不依赖于具体模型和框架。\r\n\r\n## 引入相关包\r\n\r\n```Python\r\nfrom query_detector import QueryDetector\r\nimport numpy as np\r\n```\r\n\r\n## 评估示例\r\n\r\n* 准备查询输入。随机初始化10张正常样本，在第1张正常样本上添加随机噪声生成20张相似样本（模拟黑盒查询攻击过程）。\r\n\r\n```Python\r\nnp.random.seed(5)\r\nbenign_queries = np.random.randint(0, 255, [10, 224, 224, 3], np.uint8)\r\nsuspicious_queries = benign_queries[1] + np.random.rand(20, 224, 224, 3)\r\nsuspicious_queries = suspicious_queries.astype(np.uint8)\r\n```\r\n\r\n* 新建QueryDetector，调用detect函数返回对抗样本id。从第2张查询图片开始，后续的查询图片均被判定为攻击。\r\n\r\n```Python\r\ndetector = QueryDetector(suspicious_queries[0])\r\nadv_ids = detector.detect(suspicious_queries)\r\n```\r\n\r\n## 实验结果\r\n\r\n[QueryDetector] Image: 0, max match: 0, attack_query: False<br>\r\n[QueryDetector] Image: 1, max match: 50, attack_query: True<br>\r\n[QueryDetector] Image: 2, max match: 50, attack_query: True<br>\r\n[QueryDetector] Image: 3, max match: 50, attack_query: True<br>\r\n[QueryDetector] Image: 4, max match: 50, attack_query: True<br>\r\n[QueryDetector] Image: 5, max match: 50, attack_query: True<br>\r\n[QueryDetector] Image: 6, max match: 50, attack_query: True<br>\r\n[QueryDetector] Image: 7, max match: 50, attack_query: True<br>\r\n[QueryDetector] Image: 8, max match: 50, attack_query: True<br>\r\n[QueryDetector] Image: 9, max match: 50, attack_query: True<br>\r\n[QueryDetector] Image: 10, max match: 50, attack_query: True<br>\r\n[QueryDetector] Image: 11, max match: 50, attack_query: True<br>\r\n[QueryDetector] Image: 12, max match: 50, attack_query: True<br>\r\n[QueryDetector] Image: 13, max match: 50, attack_query: True<br>\r\n[QueryDetector] Image: 14, max match: 50, attack_query: True<br>\r\n[QueryDetector] Image: 15, max match: 50, attack_query: True<br>\r\n[QueryDetector] Image: 16, max match: 50, attack_query: True<br>\r\n[QueryDetector] Image: 17, max match: 50, attack_query: True<br>\r\n[QueryDetector] Image: 18, max match: 50, attack_query: True<br>\r\n[QueryDetector] Image: 19, max match: 50, attack_query: True<br>\r\n[QueryDetector] positive num on test dataset: 19<br>\r\n[QueryDetector] positive rate: 0.95<br>\r\n检测出的对抗样本id：[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]<br>\r\n\r\n"
  },
  {
    "path": "examples/community/query_attack_detector/query_detector.py",
    "content": "# Copyright 2023 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n\"\"\"\r\nQuery Detector.\r\n\"\"\"\r\nimport hashlib\r\nfrom collections import Counter\r\nfrom multiprocessing import Pool\r\nimport numpy as np\r\nimport cv2\r\n\r\nfrom mindarmour.utils.logger import LogUtil\r\nfrom mindarmour import Detector\r\n\r\nnp.set_printoptions(threshold=np.inf)\r\n\r\nLOGGER = LogUtil.get_instance()\r\nTAG = 'QueryDetector'\r\n\r\n\r\nclass QueryDetector(Detector):\r\n    \"\"\"\r\n    QueryDetector detects highly similar queries generated by iterative optimization using probabilistic fingerprints,\r\n    a compact hash representation computed for each input query.\r\n\r\n    Reference: `Blacklight: Scalable Defense for Neural Networks against Query-Based Black-Box Attacks.\r\n    Huiying Li, Shawn Shan, Emily Wenger, Jiayun Zhang, Haitao Zheng, Ben Y. Zhao. 2022.\r\n    In Proceedings of 31th USENIX Security Symposium (USENIX Security'2022).`_\r\n\r\n    Args:\r\n        sample_query (numpy.ndarray): an example query. The received queries should be with\r\n         the same shape as sample_query.\r\n        window_size (int): the size of sliding window to split each query.\r\n            Default: 50.\r\n        step_size (int): the step between adjacent sliding windows.\r\n            Default: 1.\r\n        roundto (int): the quantization step of each hash.\r\n            Default: 50.\r\n        hash_kept (int): number of hash fingerprints kept to represent each query.\r\n            Default: 50.\r\n        threshold (int): number of matched hashes to decide a query is an attack.\r\n            Default: 25.\r\n        workers (int): number of processes to compute hash fingerprints for the input queries.\r\n            Default: 5.\r\n        salt (numpy.ndarray): a randomly generated salt image (of the same dimensions as sample_query),\r\n         to improves robustness against adaptive attacks.\r\n            Default: None.\r\n    Examples:\r\n        >>> from query_detector import QueryDetector\r\n        >>> import numpy as np\r\n        >>> np.random.seed(5)\r\n        >>> benign_queries = np.random.randint(0, 255, [10, 224, 224, 3], np.uint8)\r\n        >>> suspicious_queries = benign_queries[1] + np.random.rand(20, 224, 224, 3)\r\n        >>> suspicious_queries = suspicious_queries.astype(np.uint8)\r\n        >>> detector = QueryDetector(suspicious_queries[0])\r\n        >>> detector.detect(suspicious_queries)\r\n    \"\"\"\r\n\r\n    def __init__(self, sample_query, window_size=50, step_size=1, roundto=50, hash_kept=50, threshold=25,\r\n                 workers=5, salt=None):\r\n        super(QueryDetector, self).__init__()\r\n        self.window_size = window_size\r\n        self.step_size = step_size\r\n        self.roundto = roundto\r\n        self.num_hashes_keep = hash_kept\r\n        self.threshold = threshold\r\n        self.workers = workers\r\n        self._detected_queries = []\r\n\r\n        if salt is not None:\r\n            self.salt = salt\r\n        else:\r\n            self.salt = np.random.rand(*sample_query.shape) * 255.\r\n\r\n        self.hash_dict = {}\r\n        self.output = {}\r\n        self.input_idx = 0\r\n        self.pool = Pool(processes=workers)\r\n\r\n    def preprocess(self, array, roundto=1, normalized=False):\r\n        \"\"\"\r\n        Perform salted pixel quantization, converting continuous pixel values into a finite set of discrete values.\r\n        Quantization increases similarity between (attack) queries.\r\n        Args:\r\n            array (numpy.ndarray): an input query\r\n            roundto (int): the quantization step of each hash.\r\n            normalized (boolean): True for images within [0,1], False for iamges within [0,255]\r\n        Returns:\r\n            the query after quantization.\r\n        \"\"\"\r\n        if normalized:\r\n            array = np.array(array) * 255.\r\n        array = (array + self.salt) % 255.\r\n        array = array.reshape(-1)\r\n        array = np.around(array / roundto, decimals=0) * roundto\r\n        array = array.astype(np.int16)\r\n        return array\r\n\r\n    def hash_img(self, img, window_size, roundto, step_size, preprocess=True):\r\n        \"\"\"\r\n        Compute hash fingerprint for the query image.\r\n            Args:\r\n                img (numpy.ndarray): the query image.\r\n                window_size (int): the size of sliding window to split each query.\r\n                roundto (int): the quantization step of each hash.\r\n                step_size (int): the step between adjacent sliding windows.\r\n                preprocess (boolean): whether to perform salted pixel quantization.\r\n            Returns:\r\n                a list of hashes of the query image as its fingerprint.\r\n        \"\"\"\r\n        if preprocess:\r\n            img = self.preprocess(img, roundto)\r\n\r\n        total_len = int(len(img))\r\n        idx_ls = []\r\n        for el in range(int((total_len - window_size + 1) / step_size)):\r\n            idx_ls.append({\"idx\": el * step_size, \"img\": img, \"window_size\": window_size})\r\n        hash_list = self.pool.map(hash_helper, idx_ls)\r\n        hash_list = list(set(hash_list))\r\n        hash_list = [r[::-1] for r in hash_list]\r\n        hash_list.sort(reverse=True)\r\n        return hash_list\r\n\r\n    def check_img(self, hashes):\r\n        \"\"\"\r\n        Check the matched hashes of current query with all previous queries.\r\n            Args:\r\n                hashes (list): the hash list of a query image.\r\n            Returns:\r\n                the number of matched hashes of current query with all previous queries.\r\n        \"\"\"\r\n        sets = list(map(self.hash_dict.get, hashes))\r\n        sets = [i for i in sets if i is not None]\r\n        sets = [item for sublist in sets for item in sublist]\r\n        if not sets:\r\n            return 0\r\n        sets = Counter(sets)\r\n        cnt = sets.most_common(1)[0][1]\r\n        return cnt\r\n\r\n    def add_img(self, img):\r\n        \"\"\"\r\n        Add the hashes of current query to the dict recording all the hashes, and compute the matched hashes with\r\n        previous queries.\r\n            Args:\r\n                img (numpy.ndarray): the query image.\r\n            Returns:\r\n                the number of matched hashes of current query with all previous queries.\r\n        \"\"\"\r\n        self.input_idx += 1\r\n        hashes = self.hash_img(img, self.window_size, self.roundto, self.step_size)[:self.num_hashes_keep]\r\n        cnt = self.check_img(hashes)\r\n        for el in hashes:\r\n            if el not in self.hash_dict:\r\n                self.hash_dict[el] = [self.input_idx]\r\n            else:\r\n                self.hash_dict.get(el).append(self.input_idx)\r\n        return cnt\r\n\r\n    def fit(self, inputs, labels=None):\r\n        \"\"\"\r\n        Process input training data to calculate the threshold.\r\n        A proper threshold should make sure the false positive\r\n        rate is under a given value.\r\n\r\n        Args:\r\n            inputs (Union[numpy.ndarray, list, tuple]): Data been used as\r\n                references to create adversarial examples.\r\n        Raises:\r\n            NotImplementedError: This function is not available\r\n                in class `QueryDetector`.\r\n        \"\"\"\r\n        msg = 'The function fit() is not available in the class ' \\\r\n              '`QueryDetector`.'\r\n        LOGGER.error(TAG, msg)\r\n        raise NotImplementedError(msg)\r\n\r\n    def detect(self, queries):\r\n        \"\"\"\r\n        Process queries to detect black-box attack.\r\n        Args:\r\n             queries (numpy.ndarray): Query sequence.\r\n        Returns:\r\n             - list[int], ids of adversarial examples detected.\r\n        \"\"\"\r\n        queries = np.array(queries)\r\n        match_list = []\r\n        adv_ids = []\r\n        query_id = 0\r\n        for query in queries:\r\n            query = self.gaussian_filter(query)\r\n            match_num = self.add_img(query)\r\n            match_list.append(match_num)\r\n            LOGGER.info(TAG, 'Image: {}, max match: {}, attack_query: {}'.format(query_id, match_num,\r\n                                                                                 match_num > self.threshold))\r\n            if match_num > self.threshold:\r\n                adv_ids.append(query_id)\r\n            query_id += 1\r\n\r\n        num = np.sum([1 for i in match_list if i > self.threshold])\r\n        LOGGER.info(TAG, \"positive num on test dataset: {}\".format(num))\r\n        rate = num / float(len(queries))\r\n        LOGGER.info(TAG, \"positive rate: {}\".format(rate))\r\n        return adv_ids\r\n\r\n    def gaussian_filter(self, img):\r\n        \"\"\"\r\n        Filter the noise of query image before fed to the detector.\r\n            Args:\r\n                img (numpy.ndarray): the query image.\r\n            Returns:\r\n                the query filtered.\r\n        \"\"\"\r\n        img = cv2.GaussianBlur(src=img, ksize=(5, 5), sigmaX=0, sigmaY=1.0)\r\n        return img\r\n\r\n    def detect_diff(self, inputs):\r\n        \"\"\"\r\n        Detect adversarial samples from input samples, like the predict_proba function in common machine learning model.\r\n\r\n        Args:\r\n            inputs (Union[numpy.ndarray, list, tuple]): Data been used as\r\n                references to create adversarial examples.\r\n        Raises:\r\n            NotImplementedError: This function is not available\r\n                in class `QueryDetector`.\r\n        \"\"\"\r\n        msg = 'The function detect_diff() is not available in the class ' \\\r\n              '`QueryDetector`.'\r\n        LOGGER.error(TAG, msg)\r\n        raise NotImplementedError(msg)\r\n\r\n    def transform(self, inputs):\r\n        \"\"\"\r\n        Filter adversarial noises in input samples.\r\n        Args:\r\n            inputs (Union[numpy.ndarray, list, tuple]): Data been used as references to create adversarial examples.\r\n        Raises:\r\n            NotImplementedError: This function is not available in class `QueryDetector`.\r\n        \"\"\"\r\n        msg = 'The function transform() is not available in the class ' \\\r\n              '`QueryDetector`.'\r\n        LOGGER.error(TAG, msg)\r\n        raise NotImplementedError(msg)\r\n\r\n    def delete(self):\r\n        \"\"\"\r\n           Close the pool for computing hashes.\r\n        \"\"\"\r\n        self.pool.close()\r\n\r\n\r\ndef hash_helper(arguments):  # compute hashes\r\n    \"\"\"\r\n    Compute hash for a part of image split by the sliding window.\r\n        Args:\r\n            arguments (dict):  containing a specific window of a query image, the window id and the window size.\r\n        Returns:\r\n            the hash for the current part of query image.\r\n    \"\"\"\r\n    img = arguments['img']\r\n    idx = arguments['idx']\r\n    window_size = arguments['window_size']\r\n    return hashlib.sha256(img[idx:idx + window_size]).hexdigest()\r\n"
  },
  {
    "path": "examples/community/speech_adversarial_attack/README.md",
    "content": "# 音频识别对抗噪声生成\n\n## 描述\n\n本项目是基于MindSpore框架实现音频识别模型对抗噪声生成算法[PAT](https://arxiv.org/pdf/2211.10661.pdf)，通过生成基于音素的通用对抗噪声来干扰音频识别模型的正常运行。\n\n## 模型结构\n\n采用启智平台开源的基于MindSpore框架的[DeepSpeech2模型](https://openi.pcl.ac.cn/Yzx835/speech_adversarial_attack)，模型参数文件可以从 https://openi.pcl.ac.cn/Yzx835/speech_adversarial_attack/modelmanage/show_model 里面获取。\n\n## 环境要求\n\nmindspore>=2.0.0a0，硬件平台为GPU、CPU、Ascend。\n\n## 脚本说明\n\n```markdown\n├── attack.py //对抗噪声生成代码\n├── checkpoints\n│   └── DeepSpeech2_model.ckpt //DeepSpeech模型参数文件\n├── data //数据路径\n│   ├── libri_val_manifest.csv\n│   └── LibriSpeech_dataset\n│       └── val\n│           ├── txt\n│           └── wav\n├── dataset.py //数据加载相关代码\n├── labels.json //音频相关标签\n├── README.md\n├── requirements.txt\n├── source\n│   └── 100_test_audio_list.npy //固定的测试数据\n├── src //DeepSpeech模型相关代码\n│   ├── config.py\n│   ├── deepspeech2.py\n│   ├── greedydecoder.py\n│   ├── __init__.py\n└── stft.py //音频处理代码\n```\n\n## 训练依赖\n\n环境依赖：\n\n```python\nnumpy\neasydict\nlibrosa >= 0.8.1\nsoundfile >= 0.12.1\nLevenshtein >= 0.20.9\ng2p-en >= 2.1.0\nmindspore >= 2.0.0a0\n```\n\ng2p-en 可能需要 nltk 工具中的 cmudict。 g2p-en运行的时候，nltk会自动下载依赖数据，如果下载失败，需要在官网（https://www.nltk.org/nltk_data/ ）手动下载cmudict.zip和averaged_perceptron_tagger.zip，然后在运行环境的home目录下创建 nltk_data/corpora/ 目录和 nltk_data/taggers/目录，然后把 cmudict.zip放在nltk_data/corpora/，把averaged_perceptron_tagger.zip放在nltk_data/taggers/。\n\n模型：\n\n将模型参数文件放入`checkpoints/`路径内，或修改`attack.py`代码中的相关路径：\n\n```python\n87: param_dict = load_checkpoint('./checkpoints/DeepSpeech2_model.ckpt')\n```\n\n数据：\n\n将处理后的[librispeech](https://openi.pcl.ac.cn/Yzx835/speech_adversarial_attack/datasets)数据集存入`data/`路径内，具体参考`脚本说明`中的路径放置数据集，或修改`src/config.py`相关的路径参数：\n\n```python\n27:         \"train_manifest\": 'data/libri_train_manifest.csv',\n80:         \"test_manifest\": 'data/libri_val_manifest.csv',\n```\n\n## 训练过程\n\n噪声生成:\n\n```shell\npython attack.py\n```\n\n## 默认训练参数\n\n```python\nsample_rate = 16000\nwindow_size = 0.02\nwindow_stride = 0.01\nwindow = \"hamming\"\nadv_len=3200\neps=0.01\nstep=2467\niteration=30  # iteration=10 也可以达到攻击效果\nlr=2e-3\n```\n\n## 实验结果\n\n```text\n攻击前： 错误率很低\nSR = 0.0\nCER = 0.036993539852976084\n\n攻击后： 错误率提升\nSR = 0.98\nCER = 0.76\n```"
  },
  {
    "path": "examples/community/speech_adversarial_attack/attack.py",
    "content": "\"\"\"\nSpeech attack\n\"\"\"\nimport json\nimport datetime\nimport numpy as np\nfrom g2p_en import G2p\nfrom tqdm import tqdm\n\nimport mindspore as ms\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nfrom mindspore import context\nfrom mindspore.ops import operations as P\nimport mindspore.common.dtype as mstype\n\nfrom mindarmour.utils.logger import LogUtil\n\nimport stft\nfrom src.deepspeech2 import DeepSpeechModel, PredictWithSoftmax\nfrom src.greedydecoder import MSGreedyDecoder\nfrom src.config import eval_config\nfrom dataset import create_dataset\n\n\ncontext.set_context(mode=context.GRAPH_MODE, device_target=\"GPU\", save_graphs=False)\n\nLOGGER = LogUtil.get_instance()\nTAG = \"SpeechAttack\"\n\nSAMLE_RATE = 16000\nWINDOW_SIZE = 0.02\nWINDOW_STRIDE = 0.01\nWINDOW = \"hamming\"\nN_FFT = int(SAMLE_RATE * WINDOW_SIZE)\nWIN_LENGTH = N_FFT\nHOP_LENGTH = int(SAMLE_RATE * WINDOW_STRIDE)\nconfig = eval_config\n\nstft_fn = stft.STFT(\n    n_fft=N_FFT,\n    hop_length=HOP_LENGTH,\n    win_length=WIN_LENGTH,\n    window=\"hamming\",\n    center=True,\n    pad_mode=\"reflect\",\n)\n\nstft_fn.bprop_debug = True\n\nwith open(\"labels.json\") as label_file:\n    labels = json.load(label_file)\n\nmodel = DeepSpeechModel(\n    batch_size=config.DataConfig.batch_size,\n    rnn_hidden_size=config.ModelConfig.hidden_size,\n    nb_layers=config.ModelConfig.hidden_layers,\n    labels=labels,\n    rnn_type=config.ModelConfig.rnn_type,\n    audio_conf=config.DataConfig.SpectConfig,\n    bidirectional=True,\n)\nmodel_with_predict = PredictWithSoftmax(model)\ndecoder = MSGreedyDecoder(labels=labels, blank_index=labels.index(\"_\"))\ntarget_decoder = MSGreedyDecoder(labels, blank_index=labels.index(\"_\"))\n\nparam_dict = load_checkpoint(\"./checkpoints/DeepSpeech2_model.ckpt\")\nparam_dict_new = {}\nfor k, v in param_dict.items():\n    if \"rnn\" in k:\n        new_k = k.replace(\"rnn\", \"RNN\")\n        param_dict_new[new_k] = param_dict[k]\n    else:\n        param_dict_new[k] = param_dict[k]\nload_param_into_net(model, param_dict_new)\n\nLOGGER.info(TAG, \"Successfully loading the pre-trained model\")\n\nmodel.set_train(False)\nmodel.bprop_debug = True\n\nconcat_op = ms.ops.Concat(axis=1)\n\n\ndef superpose(audio, noise):\n    \"\"\"\n    Add noise into the audio.\n\n    Args:\n        audio : audio.\n        noise : noise.\n\n    Returns:\n        res: The attack audio.\n        start: The start position.\n    \"\"\"\n    audio_len = audio.shape[1]\n    noise_len = noise.shape[1]\n    start = np.random.randint(0, noise_len)\n    while noise_len < audio_len:\n        noise = np.concatenate((noise, noise), axis=1)\n        noise_len = noise.shape[1]\n    noise = np.concatenate((noise, noise), axis=1)\n    noise = noise[:, start : audio_len + start]\n\n    res = audio + noise\n    res = np.clip(res, -1, 1)\n    return res, start\n\n\ndef sr_and_cer(sound_data, noise):\n    \"\"\"\n    Calculate the attacking success rate (SR) and the character error rate (CER).\n    \"\"\"\n    i = 0\n    cer = 0.0\n    sound_len = len(sound_data)\n    for sound in tqdm(sound_data):\n        label = sound[\"label\"]\n        if noise is not None:\n            new_sound = superpose(np.array(sound[\"wave\"]), noise)[0]\n        else:\n            new_sound = np.array(sound[\"wave\"])\n\n        new_sound = stft.ms_spectrogram(ms.Tensor(new_sound), stft_fn)\n\n        input_size = new_sound.shape[-1]\n        input_size = ms.Tensor([input_size])\n\n        out, out_size = model_with_predict(new_sound, input_size)\n        decoded_output, _ = decoder.decode(out, out_size)\n\n        pred_cer = decoder.cer(decoded_output[0][0], label) / len(label)\n        cer += pred_cer\n        if pred_cer > 0.5:\n            i += 1\n    LOGGER.info(TAG, \"SR = \" + str(i / sound_len))\n    LOGGER.info(TAG, \"CER = \" + str(cer / sound_len))\n\n\ndef generate_data(num, alpha):\n    \"\"\"\n    Generate training dataset.\n    \"\"\"\n    g2p = G2p()\n\n    ds_eval = create_dataset(\n        audio_conf=config.DataConfig.SpectConfig,\n        manifest_filepath=config.DataConfig.test_manifest,\n        labels=labels,\n        normalize=True,\n        train_mode=False,\n        batch_size=1,\n        rank=0,\n        group_size=1,\n    )\n\n    LOGGER.info(TAG, str(ds_eval.get_dataset_size()))\n\n    train_data = []\n    index = 0\n    s_num_sum = 0\n    s_len_sum = 0\n    for data in ds_eval.create_dict_iterator():\n        sound, target_indices, targets = (\n            data[\"inputs\"],\n            data[\"target_indices\"],\n            data[\"label_values\"],\n        )\n        sound = sound.asnumpy()\n        target_indices, targets = target_indices.asnumpy(), targets.asnumpy()\n\n        label = target_decoder.convert_to_strings([list(targets)])\n\n        phoneme_list = g2p(label)\n        s_num_sum += len(phoneme_list)\n        s_len_sum += sound.shape[1] / SAMLE_RATE\n\n    density_mean = s_num_sum / s_len_sum\n\n    for data in ds_eval.create_dict_iterator():\n        sound, target_indices, targets = (\n            data[\"inputs\"],\n            data[\"target_indices\"],\n            data[\"label_values\"],\n        )\n        sound = sound.asnumpy()\n        target_indices, targets = target_indices.asnumpy(), targets.asnumpy()\n\n        label = target_decoder.convert_to_strings([list(targets)])\n\n        phoneme_list = g2p(label)\n        s_num = len(phoneme_list)\n        s_len = sound.shape[1] / SAMLE_RATE\n        density = s_num / s_len\n        if density < density_mean - alpha or density > density_mean + alpha:\n            continue\n        if index < num:\n            train_data.append(\n                {\n                    \"wave\": sound,\n                    \"target_indices\": data[\"target_indices\"],\n                    \"label_values\": data[\"label_values\"],\n                }\n            )\n            LOGGER.info(TAG, str(label))\n        else:\n            break\n        index += 1\n    return train_data\n\n\nclass MyAdam(ms.nn.Cell):\n    \"\"\"\n    Adam for Mindspore.\n    \"\"\"\n\n    def __init__(self, param):\n        super(MyAdam, self).__init__()\n        self.apply_adam = ms.ops.Adam()\n        self.param_m = ms.Parameter(\n            ms.Tensor(np.zeros(param.shape).astype(np.float32)), name=\"param_m\"\n        )\n        self.param_v = ms.Parameter(\n            ms.Tensor(np.zeros(param.shape).astype(np.float32)), name=\"param_v\"\n        )\n\n    def construct(\n            self, var, beta1_power, beta2_power, learning_rate, beta1, beta2, epsilon, grad\n    ):\n        \"\"\"\n        Run.\n        \"\"\"\n        val, self.param_m, self.param_v = self.apply_adam(\n            var,\n            self.param_m,\n            self.param_v,\n            beta1_power,\n            beta2_power,\n            learning_rate,\n            beta1,\n            beta2,\n            epsilon,\n            grad,\n        )\n        return val\n\n\ndef superpose_step(sound, noise, start):\n    \"\"\"\n    Add noise into the audio in the step.\n\n    Args:\n        audio : Audio.\n        noise : Noise.\n        start : Add noise in the step.\n\n    Returns:\n        res: The attack audio.\n        start: The start position.\n    \"\"\"\n    sound_len = sound.shape[1]\n    noise_len = noise.shape[1]\n    while noise_len < sound_len:\n        noise = concat_op((noise, noise))\n        noise_len = noise.shape[1]\n    noise = concat_op((noise, noise))\n    noise = noise[:, start : sound_len + start]\n\n    res = sound + noise\n    res = ms.ops.clip_by_value(res, -1, 1)\n    return res, start\n\n\ndef generate(\n        train_data,\n        epoch_size,\n        adv_len,\n        eps,\n        step,\n        iteration=100,\n        learning_rate=1e-1,\n):\n    \"\"\"\n    Generate speech attack noise.\n\n    Args:\n        train_data : Training data.\n        epoch_size : Training epochs.\n        adv_len : The attack noise length.\n        eps : Attack eps.\n        step : Attack steps.\n        iteration : Iteration steps.\n        learning_rate : Learning rate.\n\n    Returns:\n        res: The attack audio,\n        start: The start position.\n    \"\"\"\n    noise_init = train_data[0][\"wave\"][:, :adv_len]\n    noise = ms.Tensor(noise_init)\n\n    noise = ms.ops.clip_by_value(noise, -eps, eps)\n\n    myadam = MyAdam(noise)\n\n    data_length = len(train_data)\n\n    loss_fn = P.CTCLoss(ctc_merge_repeated=True)\n    reduce_mean_false = P.ReduceMean(keep_dims=False)\n    cast_op = P.Cast()\n    inference_softmax = P.Softmax(axis=-1)\n    transpose_op = P.Transpose()\n\n    for epoch in range(epoch_size):\n        for index, sound in enumerate(train_data):\n            one_sound = ms.Tensor(sound[\"wave\"])\n\n            target_indices, targets = sound[\"target_indices\"], sound[\"label_values\"]\n\n            def forward_fn(\n                    one_sound, noise, input_size, step_start, target_indices, label_values\n            ):\n                advs, _ = superpose_step(one_sound, noise, step_start)\n                advs = stft.ms_spectrogram(advs, stft_fn)\n                input_size[0] = advs.shape[-1]\n\n                predict, output_length = model(advs, input_size)\n\n                loss = loss_fn(\n                    predict,\n                    target_indices,\n                    label_values,\n                    cast_op(output_length, mstype.int32),\n                )\n                loss = -reduce_mean_false(loss[0])\n                return loss, predict, output_length\n\n            grad_fn = ms.value_and_grad(forward_fn, 1, None, has_aux=True)\n\n            step_start = 0\n            for cur_index in range(iteration):\n                input_size = ms.Tensor([one_sound.shape[-1]])\n\n                (loss, out, out_size), grads = grad_fn(\n                    one_sound, noise, input_size, step_start, target_indices, targets\n                )\n\n                noise = myadam(\n                    noise, 0.9, 0.999, learning_rate, 0.9, 0.999, 1e-8, grads\n                )\n\n                loss = ms.ops.depend(loss, noise)\n\n                noise = noise.clip(-eps, eps)\n\n                out = inference_softmax(out)\n                out = transpose_op(out, (1, 0, 2))\n\n                decoded_output, _ = decoder.decode(out, out_size)\n                label = target_decoder.convert_to_strings([list(targets.asnumpy())])\n\n                LOGGER.info(TAG, str(decoded_output))\n                LOGGER.info(TAG, str(label))\n\n                cer_inst = decoder.cer(decoded_output[0][0], label[0][0])\n                cer = cer_inst / len(label[0][0].replace(\" \", \"\"))\n                LOGGER.info(TAG, str(cer))\n\n                step_start += step\n                if step_start > adv_len:\n                    step_start -= adv_len\n\n                LOGGER.info(\n                    TAG,\n                    \"epoch = {}/{}; data = {}/{}; iter = {}/{}; loss = {};\"\n                    \" cur_cer = {:.4f}; decode_out = {}\".format(\n                        epoch + 1,\n                        epoch_size,\n                        index + 1,\n                        data_length,\n                        cur_index + 1,\n                        iteration,\n                        loss,\n                        cer,\n                        decoded_output[0][0],\n                    ),\n                )\n    return noise.asnumpy()\n\n\nif __name__ == \"__main__\":\n    if len(sys.argv) != 2:\n        print(\"Usage: python attack.py <test_dataset_path>\")\n        sys.exit(1)\n    test_dataset = np.load(sys.argv[1], allow_pickle=False)\n\n    sr_and_cer(test_dataset, None)\n    train_dataset = generate_data(10, 0.2)\n\n    start_time = datetime.datetime.now()\n    attack_noise = generate(\n        train_dataset,\n        epoch_size=3,\n        adv_len=3200,\n        eps=0.05,\n        step=2467,\n        iteration=30,\n        learning_rate=2e-3,\n    )\n    end_time = datetime.datetime.now()\n    time = end_time - start_time\n    LOGGER.info(TAG, \"Time = \" + str(end_time - start_time))\n\n    sr_and_cer(test_dataset, attack_noise)\n"
  },
  {
    "path": "examples/community/speech_adversarial_attack/checkpoints/.gitkeep",
    "content": ""
  },
  {
    "path": "examples/community/speech_adversarial_attack/data/.gitkeep",
    "content": ""
  },
  {
    "path": "examples/community/speech_adversarial_attack/dataset.py",
    "content": "# Copyright 2023 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nCreate train or eval dataset.\n\"\"\"\nimport math\n\nimport numpy as np\nimport mindspore.dataset.engine as de\nimport librosa\nimport soundfile as sf\n\nTRAIN_INPUT_PAD_LENGTH = 1250\nTRAIN_LABEL_PAD_LENGTH = 350\nTEST_INPUT_PAD_LENGTH = 3500\n\n\nclass LoadAudioAndTranscript:\n    \"\"\"\n    Parse audio and transcript.\n    \"\"\"\n\n    def __init__(self, audio_conf=None, normalize=False, labels=None):\n        super(LoadAudioAndTranscript, self).__init__()\n        self.window_stride = audio_conf.window_stride\n        self.window_size = audio_conf.window_size\n        self.sample_rate = audio_conf.sample_rate\n        self.window = audio_conf.window\n        self.is_normalization = normalize\n        self.labels = labels\n\n    @staticmethod\n    def load_audio(path):\n        \"\"\"\n        Load audio.\n        \"\"\"\n        sound, _ = sf.read(path, dtype=\"int16\")\n        sound = sound.astype(\"float32\") / 32767\n        if len(sound.shape) > 1:\n            if sound.shape[1] == 1:\n                sound = sound.squeeze()\n            else:\n                sound = sound.mean(axis=1)\n        return sound\n\n    def parse_audio(self, audio_path):\n        \"\"\"\n        Parse audio.\n        \"\"\"\n        audio = self.load_audio(audio_path)\n        n_fft = int(self.sample_rate * self.window_size)\n        win_length = n_fft\n        hop_length = int(self.sample_rate * self.window_stride)\n        d = librosa.stft(\n            y=audio,\n            n_fft=n_fft,\n            hop_length=hop_length,\n            win_length=win_length,\n            window=self.window,\n        )\n        mag, _ = librosa.magphase(d)\n        mag = np.log1p(mag)\n        if self.is_normalization:\n            mean = mag.mean()\n            std = mag.std()\n            mag = (mag - mean) / std\n        return mag\n\n    def parse_transcript(self, transcript_path):\n        \"\"\"\n        Parse_transcript.\n        \"\"\"\n        with open(transcript_path, \"r\", encoding=\"utf8\") as transcript_file:\n            transcript = transcript_file.read().replace(\"\\n\", \"\")\n        transcript = list(filter(None, [self.labels.get(x) for x in list(transcript)]))\n        return transcript\n\n\nclass ASRDataset(LoadAudioAndTranscript):\n    \"\"\"\n    Create ASRDataset.\n\n    Args:\n        audio_conf: Config containing the sample rate, window and the window length/stride in seconds.\n        manifest_filepath (str): Manifest_file path.\n        labels (list): List containing all the possible characters to map to.\n        normalize: Apply standard mean and deviation Normalization to audio tensor.\n        batch_size (int): Dataset batch size. Default: 32.\n    \"\"\"\n\n    def __init__(\n            self,\n            audio_conf=None,\n            manifest_filepath=\"\",\n            labels=None,\n            normalize=False,\n            batch_size=32,\n            is_training=True,\n    ):\n        with open(manifest_filepath) as f_i:\n            ids = f_i.readlines()\n\n        ids = [x.strip().split(\",\") for x in ids]\n        self.is_training = is_training\n        self.ids = ids\n        self.blank_id = int(labels.index(\"_\"))\n        self.bins = [ids[i : i + batch_size] for i in range(0, len(ids), batch_size)]\n        if len(self.ids) % batch_size != 0:\n            self.bins = self.bins[:-1]\n            self.bins.append(ids[-batch_size:])\n        self.size = len(self.bins)\n        self.batch_size = batch_size\n        self.labels_map = {labels[i]: i for i in range(len(labels))}\n        super(ASRDataset, self).__init__(audio_conf, normalize, self.labels_map)\n\n    def __getitem__(self, index):\n        batch_idx = self.bins[index]\n        batch_size = len(batch_idx)\n        batch_spect, batch_script, target_indices = [], [], []\n\n        for data in batch_idx:\n            audio_path, transcript_path = data[0], data[1]\n            audio = self.load_audio(audio_path)\n            transcript = self.parse_transcript(transcript_path)\n            batch_spect.append(audio)\n            batch_script.append(transcript)\n\n        targets = []\n        for k, scripts_ in zip(range(batch_size), batch_script):\n            targets.extend(scripts_)\n            for m in range(len(scripts_)):\n                target_indices.append([k, m])\n\n        return (\n            batch_spect,\n            np.array(target_indices, dtype=np.int64),\n            np.array(targets, dtype=np.int32),\n        )\n\n    def __len__(self):\n        return self.size\n\n\nclass DistributedSampler:\n    \"\"\"\n    Function to distribute and shuffle sample.\n    \"\"\"\n\n    def __init__(self, dataset, rank, group_size, shuffle=True, seed=0):\n        self.dataset = dataset\n        self.rank = rank\n        self.group_size = group_size\n        self.dataset_len = len(self.dataset)\n        self.num_samplers = int(math.ceil(self.dataset_len * 1.0 / self.group_size))\n        self.total_size = self.num_samplers * self.group_size\n        self.shuffle = shuffle\n        self.seed = seed\n\n    def __iter__(self):\n        if self.shuffle:\n            self.seed = (self.seed + 1) & 0xFFFFFFFF\n            np.random.seed(self.seed)\n            indices = np.random.permutation(self.dataset_len).tolist()\n        else:\n            indices = list(range(self.dataset_len))\n\n        indices += indices[: (self.total_size - len(indices))]\n        indices = indices[self.rank :: self.group_size]\n        return iter(indices)\n\n    def __len__(self):\n        return self.num_samplers\n\n\ndef create_dataset(\n        audio_conf,\n        manifest_filepath,\n        labels,\n        normalize,\n        batch_size,\n        train_mode=True,\n        rank=None,\n        group_size=None,\n):\n    \"\"\"\n    Create train dataset.\n\n    Args:\n        audio_conf: Config containing the sample rate, window and the window length/stride in seconds.\n        manifest_filepath (str): Manifest_file path.\n        labels (list): List containing all the possible characters to map to.\n        normalize: Apply standard mean and deviation Normalization to audio tensor.\n        train_mode (bool): Whether dataset is use for train or eval. Default: True.\n        batch_size (int): Dataset batch size\n        rank (int): The shard ID within num_shards. Default: None.\n        group_size (int): Number of shards that the dataset should be divided into. Default: None.\n\n    Returns:\n        Dataset.\n    \"\"\"\n\n    dataset = ASRDataset(\n        audio_conf=audio_conf,\n        manifest_filepath=manifest_filepath,\n        labels=labels,\n        normalize=normalize,\n        batch_size=batch_size,\n        is_training=train_mode,\n    )\n\n    sampler = DistributedSampler(dataset, rank, group_size, shuffle=False)\n\n    dataset = de.GeneratorDataset(\n        dataset, [\"inputs\", \"target_indices\", \"label_values\"], sampler=sampler\n    )\n    dataset = dataset.repeat(1)\n    return dataset\n"
  },
  {
    "path": "examples/community/speech_adversarial_attack/labels.json",
    "content": "[\n  \"'\",\n  \"A\",\n  \"B\",\n  \"C\",\n  \"D\",\n  \"E\",\n  \"F\",\n  \"G\",\n  \"H\",\n  \"I\",\n  \"J\",\n  \"K\",\n  \"L\",\n  \"M\",\n  \"N\",\n  \"O\",\n  \"P\",\n  \"Q\",\n  \"R\",\n  \"S\",\n  \"T\",\n  \"U\",\n  \"V\",\n  \"W\",\n  \"X\",\n  \"Y\",\n  \"Z\",\n  \" \",\n  \"_\"\n]"
  },
  {
    "path": "examples/community/speech_adversarial_attack/requirements.txt",
    "content": "numpy >= 1.17.0\neasydict >= 1.9\nlibrosa >= 0.8.1\nsoundfile >= 0.11.0\nLevenshtein >= 0.20.9\ng2p-en >= 2.1.0"
  },
  {
    "path": "examples/community/speech_adversarial_attack/src/__init__.py",
    "content": "# Copyright 2023 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the License);\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# httpwww.apache.orglicensesLICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an AS IS BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n"
  },
  {
    "path": "examples/community/speech_adversarial_attack/src/config.py",
    "content": "# Copyright 2023 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ===========================================================================\n\"\"\"\nnetwork config setting, will be used in train.py and eval.py\n\"\"\"\nfrom easydict import EasyDict as ed\n\ntrain_config = ed(\n    {\n        \"TrainingConfig\": {\n            \"epochs\": 70,\n        },\n        \"DataConfig\": {\n            \"train_manifest\": \"data/libri_train_manifest.csv\",\n            \"val_manifest\": \"data/libri_val_manifest.csv\",\n            \"batch_size\": 20,\n            \"labels_path\": \"labels.json\",\n            \"SpectConfig\": {\n                \"sample_rate\": 16000,\n                \"window_size\": 0.02,\n                \"window_stride\": 0.01,\n                \"window\": \"hamming\",\n            },\n            \"AugmentationConfig\": {\n                \"speed_volume_perturb\": False,\n                \"spec_augment\": False,\n                \"noise_dir\": \"\",\n                \"noise_prob\": 0.4,\n                \"noise_min\": 0.0,\n                \"noise_max\": 0.5,\n            },\n        },\n        \"ModelConfig\": {\n            \"rnn_type\": \"LSTM\",\n            \"hidden_size\": 1024,\n            \"hidden_layers\": 5,\n            \"lookahead_context\": 20,\n        },\n        \"OptimConfig\": {\n            \"learning_rate\": 3e-4,\n            \"learning_anneal\": 1.1,\n            \"weight_decay\": 1e-5,\n            \"momentum\": 0.9,\n            \"eps\": 1e-8,\n            \"betas\": (0.9, 0.999),\n            \"loss_scale\": 1024,\n            \"epsilon\": 0.00001,\n        },\n        \"CheckpointConfig\": {\n            \"ckpt_file_name_prefix\": \"DeepSpeech\",\n            \"ckpt_path\": \"./checkpoint\",\n            \"keep_checkpoint_max\": 10,\n        },\n    }\n)\n\neval_config = ed(\n    {\n        \"save_output\": \"librispeech_val_output\",\n        \"verbose\": True,\n        \"DataConfig\": {\n            \"test_manifest\": \"data/libri_val_manifest.csv\",\n            \"batch_size\": 20,\n            \"labels_path\": \"labels.json\",\n            \"SpectConfig\": {\n                \"sample_rate\": 16000,\n                \"window_size\": 0.02,\n                \"window_stride\": 0.01,\n                \"window\": \"hamming\",\n            },\n        },\n        \"ModelConfig\": {\n            \"rnn_type\": \"LSTM\",\n            \"hidden_size\": 1024,\n            \"hidden_layers\": 5,\n            \"lookahead_context\": 20,\n        },\n        \"LMConfig\": {\n            \"decoder_type\": \"greedy\",\n            \"lm_path\": \"./3-gram.pruned.3e-7.arpa\",\n            \"top_paths\": 1,\n            \"alpha\": 1.818182,\n            \"beta\": 0,\n            \"cutoff_top_n\": 40,\n            \"cutoff_prob\": 1.0,\n            \"beam_width\": 1024,\n            \"lm_workers\": 4,\n        },\n    }\n)\n"
  },
  {
    "path": "examples/community/speech_adversarial_attack/src/deepspeech2.py",
    "content": "# Copyright 2023 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nDeepSpeech2 model\n\"\"\"\n\nimport math\nimport numpy as np\nimport mindspore.common.dtype as mstype\nfrom mindspore.ops import operations as P\nfrom mindspore import nn, Tensor\n\n\nclass SequenceWise(nn.Cell):\n    \"\"\"\n    SequenceWise FC Layers.\n    \"\"\"\n\n    def __init__(self, module):\n        super(SequenceWise, self).__init__()\n        self.module = module\n        self.reshape_op = P.Reshape()\n        self.shape_op = P.Shape()\n        self._initialize_weights()\n\n    def construct(self, x):\n        sizes = self.shape_op(x)\n        size_t, size_n = sizes[0], sizes[1]\n        x = self.reshape_op(x, (size_t * size_n, -1))\n        x = self.module(x)\n        x = self.reshape_op(x, (size_t, size_n, -1))\n        return x\n\n    def _initialize_weights(self):\n        \"\"\"\n        Initialize_weights.\n        \"\"\"\n        self.init_parameters_data()\n        for _, module in self.cells_and_names():\n            if isinstance(module, nn.Dense):\n                module.weight.set_data(\n                    Tensor(\n                        np.random.uniform(\n                            -1.0 / module.in_channels,\n                            1.0 / module.in_channels,\n                            module.weight.data.shape,\n                        ).astype(\"float32\")\n                    )\n                )\n                if module.bias is not None:\n                    module.bias.set_data(\n                        Tensor(\n                            np.random.uniform(\n                                -1.0 / module.in_channels,\n                                1.0 / module.in_channels,\n                                module.bias.data.shape,\n                            ).astype(\"float32\")\n                        )\n                    )\n\n\nclass MaskConv(nn.Cell):\n    \"\"\"\n    MaskConv architecture. MaskConv is actually not implemented in this part because some operation in MindSpore\n    is not supported. lengths is kept for future use.\n    \"\"\"\n\n    def __init__(self):\n        super(MaskConv, self).__init__()\n        self.zeros = P.ZerosLike()\n        self.conv1 = nn.Conv2d(\n            1,\n            32,\n            kernel_size=(41, 11),\n            stride=(2, 2),\n            pad_mode=\"pad\",\n            padding=(20, 20, 5, 5),\n        )\n        self.bn1 = nn.BatchNorm2d(num_features=32)\n        self.conv2 = nn.Conv2d(\n            32,\n            32,\n            kernel_size=(21, 11),\n            stride=(2, 1),\n            pad_mode=\"pad\",\n            padding=(10, 10, 5, 5),\n        )\n        self.bn2 = nn.BatchNorm2d(num_features=32)\n        self.tanh = nn.Tanh()\n        self._initialize_weights()\n        self.module_list = nn.CellList(\n            [self.conv1, self.bn1, self.tanh, self.conv2, self.bn2, self.tanh]\n        )\n\n    def construct(self, x, lengths):\n        lengths = lengths\n        for module in self.module_list:\n            x = module(x)\n        return x\n\n    def _initialize_weights(self):\n        \"\"\"\n        Parameter initialization.\n        \"\"\"\n        self.init_parameters_data()\n        for _, module in self.cells_and_names():\n            if isinstance(module, nn.Conv2d):\n                size_n = (\n                    module.kernel_size[0] * module.kernel_size[1] * module.out_channels\n                )\n                module.weight.set_data(\n                    Tensor(\n                        np.random.normal(\n                            0, np.sqrt(2.0 / size_n), module.weight.data.shape\n                        ).astype(\"float32\")\n                    )\n                )\n                if module.bias is not None:\n                    module.bias.set_data(\n                        Tensor(np.zeros(module.bias.data.shape, dtype=\"float32\"))\n                    )\n            elif isinstance(module, nn.BatchNorm2d):\n                module.gamma.set_data(\n                    Tensor(np.ones(module.gamma.data.shape, dtype=\"float32\"))\n                )\n                module.beta.set_data(\n                    Tensor(np.zeros(module.beta.data.shape, dtype=\"float32\"))\n                )\n\n\nclass BatchRNN(nn.Cell):\n    \"\"\"\n    BatchRNN architecture.\n    Args:\n        batch_size(int):  Smaple_number of per step in training.\n        input_size (int):  Dimension of input tensor.\n        hidden_size(int):  Rnn hidden size.\n        num_layers(int):  Rnn layers.\n        bidirectional(bool): Use bidirectional rnn. Default: True. Currently, only bidirectional rnn is implemented.\n        batch_norm(bool): Whether to use batchnorm in RNN. Currently, GPU does not support batch_norm1D. Default: False.\n        rnn_type (str):  Rnn type to use. Default: 'LSTM'. Currently, only LSTM is supported.\n    \"\"\"\n\n    def __init__(\n            self,\n            batch_size,\n            input_size,\n            hidden_size,\n            num_layers,\n            bidirectional=False,\n            batch_norm=False,\n            rnn_type=\"LSTM\",\n            device_target=\"GPU\",\n    ):\n        super(BatchRNN, self).__init__()\n        self.batch_size = batch_size\n        self.input_size = input_size\n        self.hidden_size = hidden_size\n        self.num_layers = num_layers\n        self.rnn_type = rnn_type\n        self.bidirectional = bidirectional\n        self.has_bias = True\n        self.is_batch_norm = batch_norm\n        self.num_directions = 2 if bidirectional else 1\n        self.reshape_op = P.Reshape()\n        self.shape_op = P.Shape()\n        self.sum_op = P.ReduceSum()\n        self.device_target = device_target\n\n        input_size_list = [input_size]\n        for i in range(num_layers - 1):\n            input_size_list.append(hidden_size)\n        layers = []\n\n        for i in range(num_layers):\n            layers.append(\n                nn.LSTM(\n                    input_size=input_size_list[i],\n                    hidden_size=hidden_size,\n                    bidirectional=bidirectional,\n                    has_bias=self.has_bias,\n                )\n            )\n        self.lstms = nn.CellList(layers)\n\n        if batch_norm:\n            batch_norm_layer = []\n            for i in range(num_layers - 1):\n                batch_norm_layer.append(nn.BatchNorm1d(hidden_size))\n            self.batch_norm_list = batch_norm_layer\n\n    def construct(self, x):\n        for i in range(self.num_layers):\n            if self.is_batch_norm and i > 0:\n                x = self.batch_norm_list[i - 1](x)\n            x, _ = self.lstms[i](x)\n            if self.bidirectional:\n                size = self.shape_op(x)\n                x = self.reshape_op(x, (size[0], size[1], 2, -1))\n                x = self.sum_op(x, 2)\n        return x\n\n\nclass DeepSpeechModel(nn.Cell):\n    \"\"\"\n    ResNet architecture.\n    Args:\n        batch_size(int):  Smaple_number of per step in training. Default: 128.\n        rnn_type (str):  Rnn type to use. Default: \"LSTM\".\n        labels (list):  List containing all the possible characters to map to.\n        rnn_hidden_size(int):  Rnn hidden size.\n        nb_layers(int):  Number of rnn layers.\n        audio_conf: Config containing the sample rate, window and the window length/stride in seconds.\n        bidirectional(bool): Use bidirectional rnn. Default: True.\n    \"\"\"\n\n    def __init__(\n            self,\n            batch_size,\n            labels,\n            rnn_hidden_size,\n            nb_layers,\n            audio_conf,\n            rnn_type=\"LSTM\",\n            bidirectional=True,\n            device_target=\"GPU\",\n    ):\n        super(DeepSpeechModel, self).__init__()\n        self.batch_size = batch_size\n        self.hidden_size = rnn_hidden_size\n        self.hidden_layers = nb_layers\n        self.rnn_type = rnn_type\n        self.audio_conf = audio_conf\n        self.labels = labels\n        self.bidirectional = bidirectional\n        self.reshape_op = P.Reshape()\n        self.shape_op = P.Shape()\n        self.transpose_op = P.Transpose()\n        self.add = P.Add()\n        self.div = P.Div()\n\n        sample_rate = self.audio_conf.sample_rate\n        window_size = self.audio_conf.window_size\n        num_classes = len(self.labels)\n\n        self.conv = MaskConv()\n        # This is to calculate\n        self.pre, self.stride = self.get_conv_num()\n\n        # Based on above convolutions and spectrogram size using conv formula (W - F + 2P)/ S+1\n        rnn_input_size = int(math.floor((sample_rate * window_size) / 2) + 1)\n        rnn_input_size = int(math.floor(rnn_input_size + 2 * 20 - 41) / 2 + 1)\n        rnn_input_size = int(math.floor(rnn_input_size + 2 * 10 - 21) / 2 + 1)\n        rnn_input_size *= 32\n\n        self.RNN = BatchRNN(\n            batch_size=self.batch_size,\n            input_size=rnn_input_size,\n            num_layers=nb_layers,\n            hidden_size=rnn_hidden_size,\n            bidirectional=bidirectional,\n            batch_norm=False,\n            rnn_type=self.rnn_type,\n            device_target=device_target,\n        )\n        fully_connected = nn.Dense(rnn_hidden_size, num_classes, has_bias=False)\n        self.fc = SequenceWise(fully_connected)\n\n    def construct(self, x, lengths):\n        \"\"\"\n        Lengths is actually not used in this part since Mindspore does not support dynamic shape.\n        \"\"\"\n        output_lengths = self.get_seq_lens(lengths)\n        x = self.conv(x, lengths)\n        sizes = self.shape_op(x)\n        x = self.reshape_op(x, (sizes[0], sizes[1] * sizes[2], sizes[3]))\n        x = self.transpose_op(x, (2, 0, 1))\n        x = self.RNN(x)\n        x = self.fc(x)\n        return x, output_lengths\n\n    def get_seq_lens(self, seq_len):\n        \"\"\"\n        Given a 1D Tensor or Variable containing integer sequence lengths, return a 1D tensor or variable\n        containing the size sequences that will be output by the network.\n        \"\"\"\n        for i in range(len(self.stride)):\n            seq_len = self.add(\n                self.div(self.add(seq_len, self.pre[i]), self.stride[i]), 1\n            )\n        return seq_len\n\n    def get_conv_num(self):\n        \"\"\"\n        Get_conv_num.\n        \"\"\"\n        p, s = [], []\n        for _, cell in self.conv.cells_and_names():\n            if isinstance(cell, nn.Conv2d):\n                kernel_size = cell.kernel_size\n                padding_1 = int((kernel_size[1] - 1) / 2)\n                temp = 2 * padding_1 - cell.dilation[1] * (cell.kernel_size[1] - 1) - 1\n                p.append(temp)\n                s.append(cell.stride[1])\n        return p, s\n\n\nclass NetWithLossClass(nn.Cell):\n    \"\"\"\n    NetWithLossClass definition.\n    \"\"\"\n\n    def __init__(self, network):\n        super(NetWithLossClass, self).__init__(auto_prefix=False)\n        self.loss = P.CTCLoss(ctc_merge_repeated=True)\n        self.network = network\n        self.reduce_mean_false = P.ReduceMean(keep_dims=False)\n        self.squeeze_op = P.Squeeze(0)\n        self.cast_op = P.Cast()\n\n    def construct(self, inputs, input_length, target_indices, label_values):\n        predict, output_length = self.network(inputs, input_length)\n        loss = self.loss(\n            predict,\n            target_indices,\n            label_values,\n            self.cast_op(output_length, mstype.int32),\n        )\n        return self.reduce_mean_false(loss[0])\n\n\nclass PredictWithSoftmax(nn.Cell):\n    \"\"\"\n    PredictWithSoftmax.\n    \"\"\"\n\n    def __init__(self, network):\n        super(PredictWithSoftmax, self).__init__(auto_prefix=False)\n        self.network = network\n        self.inference_softmax = P.Softmax(axis=-1)\n        self.transpose_op = P.Transpose()\n        self.cast_op = P.Cast()\n\n    def construct(self, inputs, input_length):\n        out, output_sizes = self.network(\n            inputs, self.cast_op(input_length, mstype.int32)\n        )\n        out = self.inference_softmax(out)\n        out = self.transpose_op(out, (1, 0, 2))\n        return out, output_sizes\n"
  },
  {
    "path": "examples/community/speech_adversarial_attack/src/greedydecoder.py",
    "content": "# Copyright 2023 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nmodify GreedyDecoder to adapt to MindSpore\n\"\"\"\nimport abc\nimport numpy as np\n\nimport Levenshtein as Lev\n\n\nclass Decoder:\n    \"\"\"\n    Basic decoder class from which all other decoders inherit. Implements several\n    helper functions. Subclasses should implement the decode() method.\n\n    Arguments:\n        labels (list): Mapping from integers to characters.\n        blank_index (int, optional): Index for the blank '_' character. Defaults to 0.\n    \"\"\"\n\n    def __init__(self, labels, blank_index=0):\n        self.labels = labels\n        self.int_to_char = {i: c for (i, c) in enumerate(labels)}\n        self.blank_index = blank_index\n        # To prevent errors in decode, we add an out of bounds index for the space\n        space_index = len(labels)\n        if \" \" in labels:\n            space_index = labels.index(\" \")\n        self.space_index = space_index\n\n    @staticmethod\n    def wer(str_1, str_2):\n        \"\"\"\n        Computes the Word Error Rate, defined as the edit distance between the\n        two provided sentences after tokenizing to words.\n        Arguments:\n            str_1 (string): Space-separated sentence.\n            str_2 (string): Space-separated sentence.\n        \"\"\"\n\n        # build mapping of words to integers\n        b = set(str_1.split() + str_2.split())\n        word2char = dict(zip(b, range(len(b))))\n\n        # map the words to a char array (Levenshtein packages only accepts\n        # strings)\n        w_1 = [chr(word2char[w]) for w in str_1.split()]\n        w_2 = [chr(word2char[w]) for w in str_2.split()]\n\n        return Lev.distance(\"\".join(w_1), \"\".join(w_2))\n\n    @staticmethod\n    def cer(str_1, str_2):\n        \"\"\"\n        Computes the Character Error Rate, defined as the edit distance.\n\n        Arguments:\n            str_1 (string): Space-separated sentence.\n            str_2 (string): Space-separated sentence.\n        \"\"\"\n        (\n            str_1,\n            str_2,\n        ) = str_1.replace(\n            \" \", \"\"\n        ), str_2.replace(\" \", \"\")\n        return Lev.distance(str_1, str_2)\n\n    @abc.abstractmethod\n    def decode(self, probs, sizes=None):\n        \"\"\"\n        Given a matrix of character probabilities, returns the decoder's\n        best guess of the transcription.\n\n        Arguments:\n            probs: Tensor of character probabilities, where probs[c,t]\n                            is the probability of character c at time t.\n            sizes(optional): Size of each sequence in the mini-batch.\n        Returns:\n            string: Sequence of the model's best guess for the transcription.\n        \"\"\"\n        raise NotImplementedError\n\n\nclass MSGreedyDecoder(Decoder):\n    \"\"\"\n    GreedyDecoder used for MindSpore\n    \"\"\"\n\n    def convert_to_strings(\n            self, sequences, sizes=None, remove_repetitions=False, return_offsets=False\n    ):\n        \"\"\"Given a list of numeric sequences, returns the corresponding strings.\"\"\"\n        strings = []\n        offsets = [] if return_offsets else None\n        for idx, _ in enumerate(sequences):\n            seq_len = sizes[idx] if sizes is not None else len(sequences[idx])\n            string, string_offsets = self.process_string(\n                sequences[idx], seq_len, remove_repetitions\n            )\n            strings.append([string])  # We only return one path\n            if return_offsets:\n                offsets.append([string_offsets])\n        if return_offsets:\n            return strings, offsets\n        return strings\n\n    def process_string(self, sequence, size, remove_repetitions=False):\n        \"\"\"\n        Process string.\n        \"\"\"\n        string = \"\"\n        offsets = []\n        for i in range(size):\n            char = self.int_to_char[sequence[i].item()]\n            if char != self.int_to_char[self.blank_index]:\n                if (\n                        remove_repetitions\n                        and i != 0\n                        and char == self.int_to_char[sequence[i - 1].item()]\n                ):\n                    pass\n                elif char == self.labels[self.space_index]:\n                    string += \" \"\n                    offsets.append(i)\n                else:\n                    string = string + char\n                    offsets.append(i)\n        return string, offsets\n\n    def decode(self, probs, sizes=None):\n        probs = probs.asnumpy()\n        sizes = sizes.asnumpy()\n\n        max_probs = np.argmax(probs, axis=-1)\n        strings, offsets = self.convert_to_strings(\n            max_probs, sizes, remove_repetitions=True, return_offsets=True\n        )\n        return strings, offsets\n"
  },
  {
    "path": "examples/community/speech_adversarial_attack/stft.py",
    "content": "\"\"\"\nThe short-time Fourier transform (STFT).\n\"\"\"\n\nimport numpy as np\nimport mindspore as ms\nfrom mindspore import nn, ops\nimport librosa\n\n\nclass DFTBase(nn.Cell):\n    \"\"\"\n    Base class for DFT and IDFT matrix.\n    \"\"\"\n\n    def dft_matrix(self, num):\n        \"\"\"\n        The discrete Fourier transform (DFT) matrix.\n        \"\"\"\n        (x, y) = np.meshgrid(np.arange(num), np.arange(num))\n        omega = np.exp(-2 * np.pi * 1j / num)\n        w = np.power(omega, x * y)\n        return w\n\n    def idft_matrix(self, num):\n        \"\"\"\n        The inverse discrete Fourier transform (IDFT) matrix.\n        \"\"\"\n        (x, y) = np.meshgrid(np.arange(num), np.arange(num))\n        omega = np.exp(2 * np.pi * 1j / num)\n        w = np.power(omega, x * y)\n        return w\n\n\nclass STFT(DFTBase):\n    \"\"\"\n    The short-time Fourier transform (STFT).\n    \"\"\"\n\n    def __init__(\n            self,\n            n_fft=2048,\n            hop_length=None,\n            win_length=None,\n            window=\"hann\",\n            center=True,\n            pad_mode=\"reflect\",\n    ):\n        \"\"\"\n        Implementation of STFT with Conv1d. The function has the same output\n        of librosa.core.stft.\n        \"\"\"\n        super(STFT, self).__init__()\n\n        assert pad_mode in [\"constant\", \"reflect\"]\n\n        self.n_fft = n_fft\n        self.hop_length = hop_length\n        self.win_length = win_length\n        self.window = window\n        self.center = center\n        self.pad_mode = pad_mode\n\n        # By default, use the entire frame\n        if self.win_length is None:\n            self.win_length = n_fft\n\n        # Set the default hop, if it's not already specified\n        if self.hop_length is None:\n            self.hop_length = int(self.win_length // 4)\n\n        fft_window = librosa.filters.get_window(window, self.win_length, fftbins=True)\n\n        # Pad the window out to n_fft size\n        fft_window = librosa.util.pad_center(fft_window, n_fft)\n\n        # DFT & IDFT matrix\n        self.w = self.dft_matrix(n_fft)\n\n        out_channels = n_fft // 2 + 1\n\n        self.conv_real = nn.Conv1d(\n            in_channels=1,\n            out_channels=out_channels,\n            kernel_size=n_fft,\n            stride=self.hop_length,\n            padding=0,\n            dilation=1,\n            group=1,\n            has_bias=False,\n        )\n\n        self.conv_imag = nn.Conv1d(\n            in_channels=1,\n            out_channels=out_channels,\n            kernel_size=n_fft,\n            stride=self.hop_length,\n            padding=0,\n            dilation=1,\n            group=1,\n            has_bias=False,\n        )\n\n        conv_real_weight = ms.Parameter(\n            np.float32(np.real(self.w[:, 0:out_channels] * fft_window[:, None])).T,\n            requires_grad=False,\n        )[:, None, None, :]\n        self.conv_real.weight = conv_real_weight\n\n        self.conv_imag.weight = ms.Parameter(\n            np.float32(np.imag(self.w[:, 0:out_channels] * fft_window[:, None])).T,\n            requires_grad=False,\n        )[:, None, None, :]\n\n    def construct(self, input_x):\n        \"\"\"\n        input: (batch_size, data_length).\n        Returns:\n          real: (batch_size, n_fft // 2 + 1, time_steps).\n          imag: (batch_size, n_fft // 2 + 1, time_steps).\n        \"\"\"\n\n        out = input_x[:, None, :]\n\n        if self.center:\n            out = ops.pad(\n                out, padding=(self.n_fft // 2, self.n_fft // 2), mode=self.pad_mode\n            )\n\n        real = self.conv_real(out)\n        imag = self.conv_imag(out)\n\n        real = real[:, None, :, :].transpose((0, 1, 3, 2))\n        imag = imag[:, None, :, :].transpose((0, 1, 3, 2))\n\n        return real, imag\n\n\ndef magphase(real, imag):\n    \"\"\"\n    Separate a complex-valued spectrogram into its magnitude and phase components.\n    \"\"\"\n    mag = (real**2 + imag**2) ** 0.5\n    cos = real / ops.clip_by_value(mag, 1e-10, np.inf)\n    sin = imag / ops.clip_by_value(mag, 1e-10, np.inf)\n    return mag, cos, sin\n\n\ndef ms_spectrogram(sound, ms_stft):\n    \"\"\"\n    Convert sound to spectrogram.\n    \"\"\"\n    real, imag = ms_stft(sound)\n    mag, _, _ = magphase(real, imag)\n    mag = ops.log1p(mag)\n\n    mean = ops.mean(mag, axis=[1, 2, 3], keep_dims=True)\n    std = ops.sqrt(ops.mean(ops.abs(mag - mean) ** 2))\n\n    mag = mag - mean\n    mag = mag / std\n\n    mag = ops.permute(mag, (0, 1, 3, 2))\n    return mag\n"
  },
  {
    "path": "examples/model_protection/qwen2_5/README.md",
    "content": "# Qwen2_5_7B_Instruct模型混淆\n\n提供Qwen2_5_7B_Instruct模型的混淆和推理脚本。用户分别传入模型文件的路径和推理数据，返回混淆后的模型和推理结果。\n\n## 环境准备\n\n硬件环境：Atlas 800I A2推理服务器，或Atlas 800T A2推理服务器，已安装必要的驱动程序，并可连接至互联网\n\n操作系统：openEuler或Ubuntu Linux\n\n软件环境：\n\n1. Python >= 3.9, < 3.12\n\n2. CANN >= 8.0.0.beta1\n\n3. 安装vllm-MindSpore可以参考[vllm-MindSpore安装页面](https://gitee.com/mindspore/docs/blob/master/docs/vllm_mindspore/docs/source_zh_cn/getting_started/installation/installation.md)\n\n\n4. 安装MindArmour:\n\n   - 从Gitee下载源码\n\n     `git clone https://gitee.com/mindspore/mindarmour.git`\n\n   - 编译并安装MindArmour\n\n     `python setup.py install`\n\n### 文件结构说明\n\n```bash\nqwen2_5\n├── obfuscation\n│   ├── qwen2_5_7b_instruct_weight_obfuscation.py # 模型文件混淆脚本\n│   └── config\n│       ├── qwen2_5_7b_instruct_obf_config.yaml   # 混淆策略配置文件1\n│       └── qwen2_5_7b_instruct_obf_config_emb.yaml # 混淆策略配置文件2\n└── infer\n    ├── qwen2_5_7b_instruct_obfuscate_inference.py # 混淆模型推理脚本\n    └── network_patch\n        ├── qwen2_5_7b_instruct_ms_network_obfuscate.py   # 模型结构修改脚本1\n        └── qwen2_5_7b_instruct_ms_network_obfuscate_emb.py # 模型结构修改脚本2\n```\n\n## 脚本说明及使用\n\n### Qwen2_5_7b_instruct模型混淆\n\n1. #### 模型权重文件混淆。\n\n   脚本`qwen2_5_7b_instruct_weight_obfuscate.py`对外提供qwen2_5_7b_instruct的混淆能力。\n\n   **脚本使用方式：**\n\n   ```python\n   python qwen2_5_7b_instruct_weight_obfuscate.py <src_model_path> <saved_model_path> <obf_config_path>\n   ```\n\n   **脚本输入参数：**\n\n   - src_model_path：需要混淆的模型文件路径。\n   - saved_model_path：混淆后的模型文件保存路径。\n   - obf_config_path：模型混淆策略配置文件。\n\n\n2. #### 混淆态模型文件推理。\n\n   脚本`qwen2_5_7b_instruct_obfuscate_inference.py`对外提供qwen2_5_7b_instruct模型混淆态推理能力。\n\n   **脚本使用方式：**\n\n   ```python\n   python qwen2_5_7b_instruct_obfuscate_inference.py <model_path>\n   ```\n   \n   **脚本输入参数：**\n\n   - model_path：模型文件路径。\n   \n   在`qwen2_5_7b_instruct_obfuscate_inference.py`脚本中，通过一行代码实现qwen2_5模型结构修改：\n\n   ```python\n   from network_patch import qwen2_5_7b_instruct_ms_network_obfuscate_emb\n   ```"
  },
  {
    "path": "examples/model_protection/qwen2_5/infer/network_patch/__init__.py",
    "content": ""
  },
  {
    "path": "examples/model_protection/qwen2_5/infer/network_patch/qwen2_5_7b_instruct_ms_network_obfuscate.py",
    "content": "# Copyright 2025 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport numpy as np\nimport mindspore as ms\nimport mindspore.common.dtype as mstype\nfrom mindspore import Parameter, Tensor, mint, nn, ops\nfrom mindspore.ops import operations as P\nfrom mindspore.common.initializer import initializer\n\nfrom mindformers.experimental.infer.core.transformer import ParallelTransformer\nfrom vllm_mindspore.model_executor.models.mf_models.qwen2_weight_processor import Qwen2WeightProcessor\n\n\n_orig_init = ParallelTransformer.__init__\n\n\nclass VocabEmbedding(nn.Cell):\n    \"\"\"\n    Embedding Layer.\n\n    Args:\n            - **num_embeddings** (int): Size of the dictionary of embeddings.\n            - **embedding_dim** (int): The size of each embedding vector.\n            - **param_init_type** (mstype): The param init type, default mstype.float32.\n            - **param_init** (Union[Tensor, str, Initializer, numbers.Number]): Initializer for the embedding_table.\n                Refer to class `initializer` for the values of string when a string\n                is specified. Default: 'normal'.\n    Inputs:\n            - **input_ids** (Tensor) - The tokenized inputs with datatype int32 with shape (batch_size, seq_length)\n\n    Outputs:\n            - **output** (Tensor) - The embedding vector for the input with shape (batch_size,\n              seq_length, embedding_size).\n    \"\"\"\n\n    def __init__(self, num_embeddings, embedding_dim, param_init_type=mstype.float32, param_init='normal',\n                 parallel_optimizer=False):\n        super().__init__()\n        self.num_embeddings = num_embeddings\n        self.embedding_dim = embedding_dim\n        self.embedding_weight = Parameter(\n            initializer(param_init, [self.num_embeddings, self.embedding_dim], dtype=mstype.float16),\n            name='embedding_weight', parallel_optimizer=parallel_optimizer)\n        self.gather = ops.Gather().set_device('CPU')\n\n    def construct(self, input_ids):\n        \"\"\"Forward of vocab embedding.\"\"\"\n        # 'embedding' has dynamic shape issue, use gather instead now.\n        output = self.gather(self.embedding_weight, input_ids, 0)\n        return output\n\ndef _patched_init(self, config, *args, **kwargs):\n    _orig_init(self, config, *args, **kwargs)\n    self.tok_embeddings = VocabEmbedding(\n                num_embeddings=config.vocab_size,\n                embedding_dim=config.hidden_size,\n                param_init_type=config.param_init_dtype,\n                param_init=\"normal\",\n        )\n    self.p = Parameter(Tensor(np.arange(config.hidden_size), mstype.int32),\n                       name='p', parallel_optimizer=False)\n    self.p_inv = Parameter(Tensor(np.arange(config.hidden_size), mstype.int32),\n                           name='p_inv', parallel_optimizer=False)\n    self.permute = ops.Gather().set_device('CPU')\n    self.recover = ops.Gather().set_device('CPU')\n\nParallelTransformer.__init__ = _patched_init\n\n\ndef _patched_construct(self, tokens: Tensor, batch_valid_length=None, batch_index=None, zactivate_len=None,\n                      block_tables=None, slot_mapping=None, prefix_keys_values=None, position_ids=None, attention_mask=None,\n                      q_seq_lens=None, key_cache=None, value_cache=None):\n        \"\"\"\n        Forward of ParallelTransformer.\n\n        Args:\n            tokens: the tokenized inputs with datatype int32\n            batch_valid_length(Tensor): the past calculated the index with datatype int32, used for incremental\n                prediction. Tensor of shape :math:`(batch_size,)`. Default None.\n            block_tables (Tensor[int64]): Store mapping tables for each sequence.\n            slot_mapping (Tensor[int32]): Store token cache physical slot index.\n        Returns:\n            output: Tensor, the output of ParallelTransformer\n        \"\"\"\n        # preprocess\n        mask = attention_mask\n        if self.use_past:\n            if self.is_first_iteration:\n                freqs_cis = self.freqs_mgr.prefill()\n\n                if prefix_keys_values is not None:\n                    bs, seq_len = self.shape(tokens)\n                    if mask is None:\n                        mask = self.casual_mask(tokens)\n                    prefix_length = prefix_keys_values[0].shape[2]\n                    prefix_mask = Tensor(np.zeros((bs, 1, seq_len, prefix_length)), dtype=mask.dtype)\n                    mask = self.concat((prefix_mask, mask))\n            else:\n                freqs_cis = self.freqs_mgr.chunk_with_decode(position_ids)\n        else:\n            bs, seq_len = self.shape(tokens)\n            mask = self.casual_mask(tokens)\n            freqs_cis = self.freqs_mgr(seq_len)\n            if prefix_keys_values is not None:\n                prefix_length = prefix_keys_values[0].shape[2]\n                prefix_mask = Tensor(np.zeros((bs, 1, seq_len, prefix_length)), dtype=mask.dtype)\n                mask = self.concat((prefix_mask, mask))\n\n        # tokens: [bs, seq/1]\n        hidden_states = self.cast(self.tok_embeddings(tokens), mstype.float16)\n        hidden_states = self.permute(hidden_states, self.p, axis=1)\n        hidden_states = self.cast(hidden_states, self.compute_dtype)\n        # h: [bs, seq/1, hidden_dim]\n        for i in range(self.num_layers):\n            prefix_kv = prefix_keys_values[i] if prefix_keys_values is not None else None\n            key_cache_i = key_cache[i] if key_cache is not None else None\n            value_cache_i = value_cache[i] if value_cache is not None else None\n            hidden_states = self.layers[i](hidden_states, freqs_cis, mask, batch_valid_length=batch_valid_length,\n                                           block_tables=block_tables, slot_mapping=slot_mapping,\n                                           prefix_keys_values=prefix_kv, q_seq_lens=q_seq_lens,\n                                           key_cache=key_cache_i, value_cache=value_cache_i)\n        hidden_states = self.cast(hidden_states, mstype.float16)\n        hidden_states = self.recover(hidden_states, self.p_inv, axis=1)\n        hidden_states = self.cast(hidden_states, self.compute_dtype)\n        if self.post_norm:\n            hidden_states = self.norm_out(hidden_states)\n        return hidden_states\n\n\nParallelTransformer.construct = _patched_construct\n\n\n_orig_infer_convert_outer_weight = Qwen2WeightProcessor.infer_convert_outer_weight\n\ndef _patched_infer_convert_outer_weight(self, src_hf_dir, hf_weight_map):\n    \"\"\"convert weight not in model\"\"\"\n    _orig_infer_convert_outer_weight(self, src_hf_dir, hf_weight_map)\n    p_hf_name = \"model.p\"\n    p_ms_name = self.convert_weight_name(p_hf_name)\n    np_data, _ = self.get_safetensor_from_file(p_hf_name, src_hf_dir, hf_weight_map)\n    self.parameter_dict[p_ms_name] = ms.Parameter(ms.from_numpy(np_data).astype(ms.int32),\n                                                  name=p_ms_name,\n                                                  requires_grad=False)\n    p_inv_hf_name = \"model.p_inv\"\n    p_inv_ms_name = self.convert_weight_name(p_inv_hf_name)\n    np_data, _ = self.get_safetensor_from_file(p_inv_hf_name, src_hf_dir, hf_weight_map)\n    self.parameter_dict[p_inv_ms_name] = ms.Parameter(ms.from_numpy(np_data).astype(ms.int32),\n                                                      name=p_inv_ms_name,\n                                                      requires_grad=False)\n    # Do not split_tp_group\n    embed_tokens_hf_name = \"model.embed_tokens.weight\"\n    embed_tokens_ms_name = self.convert_weight_name(embed_tokens_hf_name)\n    np_data, _ = self.get_safetensor_from_file(embed_tokens_hf_name, src_hf_dir, hf_weight_map)\n    self.parameter_dict[embed_tokens_ms_name] = ms.Parameter(ms.from_numpy(np_data).astype(ms.bfloat16),\n                                                            name=embed_tokens_ms_name,\n                                                            requires_grad=False)\n\nQwen2WeightProcessor.infer_convert_outer_weight = _patched_infer_convert_outer_weight\n\n\n_orig_convert_weight_name = Qwen2WeightProcessor.convert_weight_name\n\ndef _patched_convert_weight_name(self, weight_name: str):\n    \"\"\"replace weight name\"\"\"\n    weight_name = _orig_convert_weight_name(self, weight_name)\n    weight_name = weight_name.replace('self_attn.kv_p', 'attention.kv_p')\n    weight_name = weight_name.replace('self_attn.kv_p_inv', 'attention.kv_p_inv')\n    weight_name = weight_name.replace('self_attn.p', 'attention.p')\n    weight_name = weight_name.replace('self_attn.p_inv', 'attention.p_inv')\n    return weight_name\n\nQwen2WeightProcessor.convert_weight_name = _patched_convert_weight_name\n"
  },
  {
    "path": "examples/model_protection/qwen2_5/infer/network_patch/qwen2_5_7b_instruct_ms_network_obfuscate_emb.py",
    "content": "# Copyright 2025 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport numpy as np\nimport mindspore as ms\nimport mindspore.common.dtype as mstype\nfrom mindspore import Parameter, Tensor, mint, nn, ops\nfrom mindspore.ops import operations as P\nfrom mindspore.common.initializer import initializer\n\nfrom mindformers.experimental.infer.core.transformer import ParallelTransformer\nfrom vllm_mindspore.model_executor.models.mf_models.qwen2_weight_processor import Qwen2WeightProcessor\n\n\n_orig_init = ParallelTransformer.__init__\n\ndef _patched_init(self, config, *args, **kwargs):\n    _orig_init(self, config, *args, **kwargs)\n    self.p_inv = Parameter(Tensor(np.arange(config.hidden_size), mstype.int32),\n                        name='p_inv', parallel_optimizer=False)\n    self.emb_p_inv = Parameter(Tensor(np.arange(config.vocab_size), mstype.int32),\n                           name='emb_p_inv', parallel_optimizer=False)\n    self.permute = ops.Gather().set_device('CPU')\n    self.recover = ops.Gather().set_device('CPU')\n\nParallelTransformer.__init__ = _patched_init\n\n\ndef _patched_construct(self, tokens: Tensor, batch_valid_length=None, batch_index=None, zactivate_len=None,\n                      block_tables=None, slot_mapping=None, prefix_keys_values=None, position_ids=None, attention_mask=None,\n                      q_seq_lens=None, key_cache=None, value_cache=None):\n        \"\"\"\n        Forward of ParallelTransformer.\n\n        Args:\n            tokens: the tokenized inputs with datatype int32\n            batch_valid_length(Tensor): the past calculated the index with datatype int32, used for incremental\n                prediction. Tensor of shape :math:`(batch_size,)`. Default None.\n            block_tables (Tensor[int64]): Store mapping tables for each sequence.\n            slot_mapping (Tensor[int32]): Store token cache physical slot index.\n        Returns:\n            output: Tensor, the output of ParallelTransformer\n        \"\"\"\n        # preprocess\n        mask = attention_mask\n        if self.use_past:\n            if self.is_first_iteration:\n                freqs_cis = self.freqs_mgr.prefill()\n\n                if prefix_keys_values is not None:\n                    bs, seq_len = self.shape(tokens)\n                    if mask is None:\n                        mask = self.casual_mask(tokens)\n                    prefix_length = prefix_keys_values[0].shape[2]\n                    prefix_mask = Tensor(np.zeros((bs, 1, seq_len, prefix_length)), dtype=mask.dtype)\n                    mask = self.concat((prefix_mask, mask))\n            else:\n                freqs_cis = self.freqs_mgr.chunk_with_decode(position_ids)\n        else:\n            bs, seq_len = self.shape(tokens)\n            mask = self.casual_mask(tokens)\n            freqs_cis = self.freqs_mgr(seq_len)\n            if prefix_keys_values is not None:\n                prefix_length = prefix_keys_values[0].shape[2]\n                prefix_mask = Tensor(np.zeros((bs, 1, seq_len, prefix_length)), dtype=mask.dtype)\n                mask = self.concat((prefix_mask, mask))\n\n        # tokens: [bs, seq/1]\n        tokens = self.permute(self.emb_p_inv, tokens, 0)\n        hidden_states = self.cast(self.tok_embeddings(tokens), self.compute_dtype)\n        # h: [bs, seq/1, hidden_dim]\n        for i in range(self.num_layers):\n            prefix_kv = prefix_keys_values[i] if prefix_keys_values is not None else None\n            key_cache_i = key_cache[i] if key_cache is not None else None\n            value_cache_i = value_cache[i] if value_cache is not None else None\n            hidden_states = self.layers[i](hidden_states, freqs_cis, mask, batch_valid_length=batch_valid_length,\n                                           block_tables=block_tables, slot_mapping=slot_mapping,\n                                           prefix_keys_values=prefix_kv, q_seq_lens=q_seq_lens,\n                                           key_cache=key_cache_i, value_cache=value_cache_i)\n        hidden_states = self.cast(hidden_states, mstype.float16)\n        hidden_states = self.recover(hidden_states, self.p_inv, axis=1)\n        hidden_states = self.cast(hidden_states, self.compute_dtype)\n        if self.post_norm:\n            hidden_states = self.norm_out(hidden_states)\n        return hidden_states\n\nParallelTransformer.construct = _patched_construct\n\n\n_orig_infer_convert_outer_weight = Qwen2WeightProcessor.infer_convert_outer_weight\n\ndef _patched_infer_convert_outer_weight(self, src_hf_dir, hf_weight_map):\n    \"\"\"convert weight not in model\"\"\"\n    _orig_infer_convert_outer_weight(self, src_hf_dir, hf_weight_map)\n \n    p_inv_hf_name = \"model.p_inv\"\n    p_inv_ms_name = self.convert_weight_name(p_inv_hf_name)\n    np_data, _ = self.get_safetensor_from_file(p_inv_hf_name, src_hf_dir, hf_weight_map)\n    self.parameter_dict[p_inv_ms_name] = ms.Parameter(ms.from_numpy(np_data).astype(ms.int32),\n                                                      name=p_inv_ms_name,\n                                                      requires_grad=False)\n    emb_p_hf_name = \"model.emb_p_inv\"\n    emb_p_ms_name = self.convert_weight_name(emb_p_hf_name)\n    np_data, _ = self.get_safetensor_from_file(emb_p_hf_name, src_hf_dir, hf_weight_map)\n    self.parameter_dict[emb_p_ms_name] = ms.Parameter(ms.from_numpy(np_data).astype(ms.int32),\n                                                      name=emb_p_ms_name,\n                                                      requires_grad=False)\n\n\nQwen2WeightProcessor.infer_convert_outer_weight = _patched_infer_convert_outer_weight\n\n\n_orig_convert_weight_name = Qwen2WeightProcessor.convert_weight_name\n\ndef _patched_convert_weight_name(self, weight_name: str):\n    \"\"\"replace weight name\"\"\"\n    weight_name = _orig_convert_weight_name(self, weight_name)\n    weight_name = weight_name.replace('self_attn.kv_p', 'attention.kv_p')\n    weight_name = weight_name.replace('self_attn.kv_p_inv', 'attention.kv_p_inv')\n    weight_name = weight_name.replace('self_attn.p', 'attention.p')\n    weight_name = weight_name.replace('self_attn.p_inv', 'attention.p_inv')\n    return weight_name\n\nQwen2WeightProcessor.convert_weight_name = _patched_convert_weight_name"
  },
  {
    "path": "examples/model_protection/qwen2_5/infer/qwen2_5_7b_instruct_obfuscate_inference.py",
    "content": "# Copyright 2025 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom network_patch import qwen2_5_7b_instruct_ms_network_obfuscate_emb # Add this line on the top of script.\n# from network_patch import qwen2_5_7b_instruct_ms_network_obfuscate\nimport time\nimport sys\nimport vllm_mindspore\nfrom vllm import LLM, SamplingParams\n\n# Sample prompts.\nprompts = [\n   \"I am\",\n   \"Today is\",\n   \"Llama is\"\n]\n\ndef test_qwen2_5_obfuscate_inference(model_path):\n    # Create a sampling params object.\n    sampling_params = SamplingParams(temperature=0.0, top_p=0.95, max_tokens=50)\n\n    # Create a LLM\n    llm = LLM(model=model_path, tensor_parallel_size=2) # Path of the obfuscated weight files\n    # Generate texts from the prompts. The output is a list of RequestOutput objects\n    # that contain the prompt, generated text, and other information.\n    start_time = time.perf_counter()\n    outputs = llm.generate(prompts, sampling_params)\n    end_time = time.perf_counter()\n    elapsed_time = end_time - start_time\n    # Print the outputs.\n    for output in outputs:\n        prompt = output.prompt\n        generated_text = output.outputs[0].text\n        print(f\"Prompt: {prompt!r}. Generated text: {generated_text!r}\")\n    print(f\"Infernce time: {elapsed_time} seconds\")\n\nif __name__ == '__main__':\n    if len(sys.argv) != 2:\n        print(\"Usage: python qwen2_5_7b_instruct_obfuscate_inference.py <model_path>\")\n        sys.exit(1)\n    model_path = sys.argv[1]\n    test_qwen2_5_obfuscate_inference(model_path)"
  },
  {
    "path": "examples/model_protection/qwen2_5/obfuscation/config/qwen2_5_7b_instruct_obf_config.yaml",
    "content": "obf_metadata_config:\n- name: attn_pi\n  shape: [3584, ]\n  type: rearrange\n  save_metadata: True\n- name: attn_kv_pi\n  shape: [512, ]\n  type: rearrange\n  save_metadata: False\n- name: attn_pi_inv\n  shape: [3584, ]\n  type: rearrange\n  save_metadata: True\n- name: attn_kv_pi_inv\n  shape: [512, ]\n  type: rearrange\n  save_metadata: False\n- name: mlp_pi\n  shape: [18944, ]\n  type: rearrange\n  save_metadata: False\n- name: alpha_q\n  shape: [1, ]\n  type: random\n  save_metadata: False\n- name: alpha_k\n  shape: [1, ]\n  type: random\n  save_metadata: False\nweight_obf_config:\n- target: model/layers/${layer}/input_layernorm/weight\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 0\n- target: model/layers/${layer}/post_attention_layernorm/weight\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 0\n- target: model/layers/${layer}/self_attn/k_proj/weight\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 1\n  - name: mul\n    input_x: weight\n    input_y: alpha_k\n- target: model/layers/${layer}/self_attn/k_proj/bias\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: mul\n    input_x: weight\n    input_y: alpha_k\n- target: model/layers/${layer}/self_attn/v_proj/weight\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: attn_kv_pi\n    axis: 0\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 1\n- target: model/layers/${layer}/self_attn/v_proj/bias\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: bias\n    input_y: attn_kv_pi\n    axis: 0\n- target: model/layers/${layer}/self_attn/q_proj/weight\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 1\n  - name: mul\n    input_x: weight\n    input_y: alpha_q\n- target: model/layers/${layer}/self_attn/q_proj/bias\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: mul\n    input_x: weight\n    input_y: alpha_q\n- target: model/layers/${layer}/self_attn/o_proj/weight\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 0\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 1\n- target: model/layers/${layer}/mlp/down_proj/weight\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 0\n  - name: permuate\n    input_x: weight\n    input_y: mlp_pi\n    axis: 1\n- target: model/layers/${layer}/mlp/gate_proj/weight\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: mlp_pi\n    axis: 0\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 1\n- target: model/layers/${layer}/mlp/up_proj/weight\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: mlp_pi\n    axis: 0\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 1"
  },
  {
    "path": "examples/model_protection/qwen2_5/obfuscation/config/qwen2_5_7b_instruct_obf_config_emb.yaml",
    "content": "obf_metadata_config:\n- name: emb_pi\n  shape: [152064, ]\n  type: rearrange\n  save_metadata: False\n- name: emb_pi_inv\n  shape: [152064, ]\n  type: rearrange\n  save_metadata: True\n- name: attn_pi\n  shape: [3584, ]\n  type: rearrange\n  save_metadata: True\n- name: attn_kv_pi\n  shape: [512, ]\n  type: rearrange\n  save_metadata: False\n- name: attn_pi_inv\n  shape: [3584, ]\n  type: rearrange\n  save_metadata: True\n- name: attn_kv_pi_inv\n  shape: [512, ]\n  type: rearrange\n  save_metadata: False\n- name: mlp_pi\n  shape: [18944, ]\n  type: rearrange\n  save_metadata: False\n- name: alpha_q\n  shape: [1, ]\n  type: random\n  save_metadata: False\n- name: alpha_k\n  shape: [1, ]\n  type: random\n  save_metadata: False\nweight_obf_config:\n- target: model/embed_tokens/weight\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: emb_pi\n    axis: 0\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 1\n- target: model/layers/${layer}/input_layernorm/weight\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 0\n- target: model/layers/${layer}/post_attention_layernorm/weight\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 0\n- target: model/layers/${layer}/self_attn/k_proj/weight\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 1\n  - name: mul\n    input_x: weight\n    input_y: alpha_k\n- target: model/layers/${layer}/self_attn/k_proj/bias\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: mul\n    input_x: weight\n    input_y: alpha_k\n- target: model/layers/${layer}/self_attn/v_proj/weight\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: attn_kv_pi\n    axis: 0\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 1\n- target: model/layers/${layer}/self_attn/v_proj/bias\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: bias\n    input_y: attn_kv_pi\n    axis: 0\n- target: model/layers/${layer}/self_attn/q_proj/weight\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 1\n  - name: mul\n    input_x: weight\n    input_y: alpha_q\n- target: model/layers/${layer}/self_attn/q_proj/bias\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: mul\n    input_x: weight\n    input_y: alpha_q\n- target: model/layers/${layer}/self_attn/o_proj/weight\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 0\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 1\n- target: model/layers/${layer}/mlp/down_proj/weight\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 0\n  - name: permuate\n    input_x: weight\n    input_y: mlp_pi\n    axis: 1\n- target: model/layers/${layer}/mlp/gate_proj/weight\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: mlp_pi\n    axis: 0\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 1\n- target: model/layers/${layer}/mlp/up_proj/weight\n  layers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]\n  weight_obf_ops:\n  - name: permuate\n    input_x: weight\n    input_y: mlp_pi\n    axis: 0\n  - name: permuate\n    input_x: weight\n    input_y: attn_pi\n    axis: 1"
  },
  {
    "path": "examples/model_protection/qwen2_5/obfuscation/qwen2_5_7b_instruct_weight_obfuscate.py",
    "content": "# Copyright 2025 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport sys\nimport yaml\nimport numpy as np\nfrom mindarmour import ModelObfuscator\n\ndef inv_permutation(p):\n    inv_p = [0]*len(p)\n    for old_idx, new_idx in enumerate(p):\n        inv_p[new_idx] = old_idx\n    return inv_p\n\ndef gen_colums_permuate_list(hidden_size, num_heads=None, kv_num_heads=None, use_gqa=False):\n    if num_heads is None:\n        pi = np.random.permutation(np.arange(hidden_size)).tolist()\n        return pi, None\n    \n    if hidden_size % num_heads != 0:\n        return None, None\n    \n    head_dims = int(hidden_size / num_heads)\n    pi = []\n    kv_pi = []\n    if use_gqa and kv_num_heads is not None:\n        repeat_num = int(num_heads / kv_num_heads)\n        for i in range(kv_num_heads):\n            one_head_pi = np.random.permutation(np.arange(0, head_dims))\n            kv_head_pi = (one_head_pi + i * head_dims).tolist()\n            kv_pi += kv_head_pi\n            for j in range(repeat_num):\n                q_head_pi = (one_head_pi + (i * repeat_num + j) * head_dims).tolist()\n                pi += q_head_pi\n    else:\n        for i in range(num_heads):\n            pi += np.random.permutation(np.arange(i * head_dims, (i + 1) * head_dims)).tolist()\n        kv_pi = None\n    return pi, kv_pi\n\n# not obfuscate embedding layer and put embedding layer in CPU\ndef test_qwen2_5_weight_obfuscate(src_path, saved_path, obf_config_path):\n    with open(obf_config_path, 'r') as f:\n        obf_config = yaml.safe_load(f)\n    obf = ModelObfuscator(obf_config, obfuscate_scale=100)\n    hidden_size = 3584\n    num_heads = 28\n    layers = 28\n    num_key_value_heads = 4\n    p, kv_p = gen_colums_permuate_list(hidden_size, num_heads, num_key_value_heads, True)\n    p_inv = inv_permutation(p)\n    kv_p_inv = inv_permutation(kv_p)\n    alpha_k = np.random.randint(1, 100, size=[1, ]).astype(np.float16)\n    alpha_q = 1 / alpha_k\n\n    obf_metadata = {\"attn_pi\": np.array(p), \"attn_kv_pi\" : np.array(kv_p), \"attn_kv_pi_inv\" : np.array(kv_p_inv), \"attn_pi_inv\" : np.array(p_inv), \"alpha_q\" : alpha_q, \"alpha_k\" : alpha_k}\n    obf.set_metadata(obf_metadata)\n    metadata_mapping = {}\n    metadata_mapping['model.p'] = \"attn_pi\"\n    metadata_mapping['model.p_inv'] = \"attn_pi_inv\"\n    obf.set_save_metadata_mapping(metadata_mapping)\n    obf.obfuscate_weight_files(src_path, saved_path=saved_path)\n\n# obfuscate embedding layer and put embedding layer in NPU\ndef test_qwen2_5_weight_obfuscate_emb(src_path, saved_path, obf_config_path):\n    with open(obf_config_path, 'r') as f:\n        obf_config = yaml.safe_load(f)\n    obf = ModelObfuscator(obf_config, obfuscate_scale=100)\n    hidden_size = 3584\n    num_heads = 28\n    layers = 28\n    num_key_value_heads = 4\n    vocab_size = 152064\n    emb_p, _ = gen_colums_permuate_list(vocab_size)\n    emb_p_inv = inv_permutation(emb_p)\n    p, kv_p = gen_colums_permuate_list(hidden_size, num_heads, num_key_value_heads, True)\n    p_inv = inv_permutation(p)\n    kv_p_inv = inv_permutation(kv_p)\n    alpha_k = np.random.randint(1, 100, size=[1, ]).astype(np.float16)\n    alpha_q = 1 / alpha_k\n\n    obf_metadata = {\"attn_pi\": np.array(p), \"attn_kv_pi\" : np.array(kv_p), \"attn_kv_pi_inv\" : np.array(kv_p_inv), \"attn_pi_inv\" : np.array(p_inv), \"alpha_q\" : alpha_q, \"alpha_k\" : alpha_k, \"emb_pi\" :np.array(emb_p), \"emb_pi_inv\" : np.array(emb_p_inv)}\n\n    obf.set_metadata(obf_metadata)\n    metadata_mapping = {}\n    metadata_mapping['model.p_inv'] = \"attn_pi_inv\"\n    metadata_mapping['model.emb_p_inv'] = \"emb_pi_inv\"\n    obf.set_save_metadata_mapping(metadata_mapping)\n    obf.obfuscate_weight_files(src_path, saved_path=saved_path)\n\nif __name__ == '__main__':\n    if len(sys.argv) != 4:\n        print(\"Usage: python qwen2_5_7b_instruct_weight_obfuscate_emb.py <src_model_path> <saved_model_path> <obf_config_path>\")\n        sys.exit(1)\n    src_path, saved_path, obf_config_path = sys.argv[1], sys.argv[2], sys.argv[3]\n    test_qwen2_5_weight_obfuscate_emb(src_path, saved_path, obf_config_path)\n"
  },
  {
    "path": "examples/model_security/README.md",
    "content": "# Application demos of model security\n## Introduction\nIt has been proved that AI models are vulnerable to adversarial noise that invisible to human eye. Through those\n demos in this package, you will learn to use the tools provided by MindArmour to generate adversarial samples and\n  also improve the robustness of your model.\n\n## 1. Generate adversarial samples (Attack method)\nAttack methods can be classified into white box attack and black box attack. White-box attack means that the attacker\n is accessible to the model structure and its parameters. Black-box means that the attacker can only obtain the predict\n  results of the\n  target model.\n### white-box attack\nRunning the classical attack method: FGSM-Attack.\n```sh\n$ cd examples/model_security/model_attacks/white-box\n$ python mnist_attack_fgsm.py\n```\n### black-box attack\nRunning the classical black method: PSO-Attack.\n```sh\n$ cd examples/model_security/model_attacks/black-box\n$ python mnist_attack_pso.py\n```\n## 2. Improve the robustness of models\n### adversarial training\nAdversarial training is an effective method to enhance the model's robustness to attacks, in which generated\n adversarial samples are fed into the model for retraining.\n ```sh\n$ cd examples/model_security/model_defenses\n$ python mnist_defense_nad.py\n```\n### adversarial detection\nBesides adversarial training, there is another type of defense method: adversarial detection. This method is mainly\n for black-box attack. The reason is that black-box attacks usually require frequent queries to the model, and the\n  difference between adjacent queries input is small. The detection algorithm could analyze the similarity of a series\n   of queries and recognize the attack.\n ```sh\n$ cd examples/model_security/model_defenses\n$ python mnist_similarity_detector.py\n```"
  },
  {
    "path": "examples/model_security/__init__.py",
    "content": ""
  },
  {
    "path": "examples/model_security/model_attacks/__init__.py",
    "content": ""
  },
  {
    "path": "examples/model_security/model_attacks/black_box/__init__.py",
    "content": ""
  },
  {
    "path": "examples/model_security/model_attacks/black_box/mnist_attack_genetic.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport time\nfrom scipy.special import softmax\nimport numpy as np\n\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\n\nfrom mindarmour.adv_robustness.attacks.black.black_model import BlackModel\nfrom mindarmour.adv_robustness.attacks.black.genetic_attack import GeneticAttack\nfrom mindarmour.adv_robustness.evaluations import AttackEvaluate\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'Genetic_Attack'\n\n\nclass ModelToBeAttacked(BlackModel):\n    \"\"\"model to be attack\"\"\"\n\n    def __init__(self, network):\n        super(ModelToBeAttacked, self).__init__()\n        self._network = network\n\n    def predict(self, inputs):\n        \"\"\"predict\"\"\"\n        # Adapt to the input shape requirements of the target network if inputs is only one image.\n        if len(inputs.shape) == 3:\n            inputs = np.expand_dims(inputs, axis=0)\n        result = self._network(Tensor(inputs.astype(np.float32)))\n        return result.asnumpy()\n\n\ndef test_genetic_attack_on_mnist():\n    \"\"\"\n    Genetic-Attack test\n    \"\"\"\n    # upload trained network\n    ckpt_path = '../../../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get test data\n    data_list = \"../../../common/dataset/MNIST/test\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size=batch_size)\n\n    # prediction accuracy before attack\n    model = ModelToBeAttacked(net)\n    batch_num = 3  # the number of batches of attacking samples\n    test_images = []\n    test_labels = []\n    predict_labels = []\n    i = 0\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        i += 1\n        images = data[0].astype(np.float32)\n        labels = data[1]\n        test_images.append(images)\n        test_labels.append(labels)\n        pred_labels = np.argmax(model.predict(images), axis=1)\n        predict_labels.append(pred_labels)\n        if i >= batch_num:\n            break\n    predict_labels = np.concatenate(predict_labels)\n    true_labels = np.concatenate(test_labels)\n    accuracy = np.mean(np.equal(predict_labels, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %g\", accuracy)\n\n    # attacking\n    attack = GeneticAttack(model=model, pop_size=6, mutation_rate=0.05,\n                           per_bounds=0.4, step_size=0.25, temp=0.1,\n                           sparse=True)\n    targeted_labels = np.random.randint(0, 10, size=len(true_labels))\n    for i, true_l in enumerate(true_labels):\n        if targeted_labels[i] == true_l:\n            targeted_labels[i] = (targeted_labels[i] + 1) % 10\n    start_time = time.clock()\n    success_list, adv_data, query_list = attack.generate(\n        np.concatenate(test_images), targeted_labels)\n    stop_time = time.clock()\n    LOGGER.info(TAG, 'success_list: %s', success_list)\n    LOGGER.info(TAG, 'average of query times is : %s', np.mean(query_list))\n    pred_logits_adv = model.predict(adv_data)\n    # rescale predict confidences into (0, 1).\n    pred_logits_adv = softmax(pred_logits_adv, axis=1)\n    pred_lables_adv = np.argmax(pred_logits_adv, axis=1)\n    accuracy_adv = np.mean(np.equal(pred_lables_adv, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy after attacking is : %g\",\n                accuracy_adv)\n    test_labels_onehot = np.eye(10)[true_labels]\n    attack_evaluate = AttackEvaluate(np.concatenate(test_images),\n                                     test_labels_onehot, adv_data,\n                                     pred_logits_adv, targeted=True,\n                                     target_label=targeted_labels)\n    LOGGER.info(TAG, 'mis-classification rate of adversaries is : %s',\n                attack_evaluate.mis_classification_rate())\n    LOGGER.info(TAG, 'The average confidence of adversarial class is : %s',\n                attack_evaluate.avg_conf_adv_class())\n    LOGGER.info(TAG, 'The average confidence of true class is : %s',\n                attack_evaluate.avg_conf_true_class())\n    LOGGER.info(TAG, 'The average distance (l0, l2, linf) between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_lp_distance())\n    LOGGER.info(TAG, 'The average structural similarity between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_ssim())\n    LOGGER.info(TAG, 'The average costing time is %s',\n                (stop_time - start_time)/(batch_num*batch_size))\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    test_genetic_attack_on_mnist()\n"
  },
  {
    "path": "examples/model_security/model_attacks/black_box/mnist_attack_hsja.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy as np\n\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\n\nfrom mindarmour import BlackModel\nfrom mindarmour.adv_robustness.attacks import HopSkipJumpAttack\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'HopSkipJumpAttack'\n\n\nclass ModelToBeAttacked(BlackModel):\n    \"\"\"model to be attack\"\"\"\n\n    def __init__(self, network):\n        super(ModelToBeAttacked, self).__init__()\n        self._network = network\n\n    def predict(self, inputs):\n        \"\"\"predict\"\"\"\n        if len(inputs.shape) == 3:\n            inputs = inputs[np.newaxis, :]\n        result = self._network(Tensor(inputs.astype(np.float32)))\n        return result.asnumpy()\n\n\ndef random_target_labels(true_labels):\n    target_labels = []\n    for label in true_labels:\n        while True:\n            target_label = np.random.randint(0, 10)\n            if target_label != label:\n                target_labels.append(target_label)\n                break\n    return target_labels\n\n\ndef create_target_images(dataset, data_labels, target_labels):\n    res = []\n    for label in target_labels:\n        for data_label, data in zip(data_labels, dataset):\n            if data_label == label:\n                res.append(data)\n                break\n    return np.array(res)\n\n\ndef test_hsja_mnist_attack():\n    \"\"\"\n    hsja-Attack test\n    \"\"\"\n    # upload trained network\n    ckpt_path = '../../../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n    net.set_train(False)\n\n    # get test data\n    data_list = \"../../../common/dataset/MNIST/test\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size=batch_size)\n\n    # prediction accuracy before attack\n    model = ModelToBeAttacked(net)\n    batch_num = 5  # the number of batches of attacking samples\n    test_images = []\n    test_labels = []\n    predict_labels = []\n    i = 0\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        i += 1\n        images = data[0].astype(np.float32)\n        labels = data[1]\n        test_images.append(images)\n        test_labels.append(labels)\n        pred_labels = np.argmax(model.predict(images), axis=1)\n        predict_labels.append(pred_labels)\n        if i >= batch_num:\n            break\n    predict_labels = np.concatenate(predict_labels)\n    true_labels = np.concatenate(test_labels)\n    accuracy = np.mean(np.equal(predict_labels, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %s\",\n                accuracy)\n    test_images = np.concatenate(test_images)\n\n    # attacking\n    norm = 'l2'\n    search = 'grid_search'\n    target = False\n    attack = HopSkipJumpAttack(model, constraint=norm, stepsize_search=search)\n    if target:\n        target_labels = random_target_labels(true_labels)\n        target_images = create_target_images(test_images, predict_labels,\n                                             target_labels)\n        attack.set_target_images(target_images)\n        success_list, adv_data, _ = attack.generate(test_images, target_labels)\n    else:\n        success_list, adv_data, _ = attack.generate(test_images, None)\n\n    adv_datas = []\n    gts = []\n    for success, adv, gt in zip(success_list, adv_data, true_labels):\n        if success:\n            adv_datas.append(adv)\n            gts.append(gt)\n    if gts:\n        adv_datas = np.concatenate(np.asarray(adv_datas), axis=0)\n        gts = np.asarray(gts)\n        pred_logits_adv = model.predict(adv_datas)\n        pred_lables_adv = np.argmax(pred_logits_adv, axis=1)\n        accuracy_adv = np.mean(np.equal(pred_lables_adv, gts))\n        mis_rate = (1 - accuracy_adv)*(len(adv_datas) / len(success_list))\n        LOGGER.info(TAG, 'mis-classification rate of adversaries is : %s',\n                    mis_rate)\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    test_hsja_mnist_attack()\n"
  },
  {
    "path": "examples/model_security/model_attacks/black_box/mnist_attack_nes.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy as np\n\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\n\nfrom mindarmour import BlackModel\nfrom mindarmour.adv_robustness.attacks import NES\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'HopSkipJumpAttack'\n\n\nclass ModelToBeAttacked(BlackModel):\n    \"\"\"model to be attack\"\"\"\n\n    def __init__(self, network):\n        super(ModelToBeAttacked, self).__init__()\n        self._network = network\n\n    def predict(self, inputs):\n        \"\"\"predict\"\"\"\n        if len(inputs.shape) == 3:\n            inputs = inputs[np.newaxis, :]\n        result = self._network(Tensor(inputs.astype(np.float32)))\n        return result.asnumpy()\n\n\ndef random_target_labels(true_labels, labels_list):\n    target_labels = []\n    for label in true_labels:\n        while True:\n            target_label = np.random.choice(labels_list)\n            if target_label != label:\n                target_labels.append(target_label)\n                break\n    return target_labels\n\n\ndef _pseudorandom_target(index, total_indices, true_class):\n    \"\"\" pseudo random_target \"\"\"\n    rng = np.random.RandomState(index)\n    target = true_class\n    while target == true_class:\n        target = rng.randint(0, total_indices)\n    return target\n\n\ndef create_target_images(dataset, data_labels, target_labels):\n    res = []\n    for label in target_labels:\n        for data_label, data in zip(data_labels, dataset):\n            if data_label == label:\n                res.append(data)\n                break\n    return np.array(res)\n\n\ndef test_nes_mnist_attack():\n    \"\"\"\n    hsja-Attack test\n    \"\"\"\n    # upload trained network\n    ckpt_path = '../../../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n    net.set_train(False)\n\n    # get test data\n    data_list = \"../../../common/dataset/MNIST/test\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size=batch_size)\n\n    # prediction accuracy before attack\n    model = ModelToBeAttacked(net)\n    # the number of batches of attacking samples\n    batch_num = 5\n    test_images = []\n    test_labels = []\n    predict_labels = []\n    i = 0\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        i += 1\n        images = data[0].astype(np.float32)\n        labels = data[1]\n        test_images.append(images)\n        test_labels.append(labels)\n        pred_labels = np.argmax(model.predict(images), axis=1)\n        predict_labels.append(pred_labels)\n        if i >= batch_num:\n            break\n    predict_labels = np.concatenate(predict_labels)\n    true_labels = np.concatenate(test_labels)\n\n    accuracy = np.mean(np.equal(predict_labels, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %s\",\n                accuracy)\n    test_images = np.concatenate(test_images)\n\n    # attacking\n    scene = 'Query_Limit'\n    if scene == 'Query_Limit':\n        top_k = -1\n    elif scene == 'Partial_Info':\n        top_k = 5\n    elif scene == 'Label_Only':\n        top_k = 5\n\n    success = 0\n    queries_num = 0\n\n    nes_instance = NES(model, scene, top_k=top_k)\n    test_length = 32\n    advs = []\n    for img_index in range(test_length):\n        # Initial image and class selection\n        initial_img = test_images[img_index]\n        orig_class = true_labels[img_index]\n        initial_img = [initial_img]\n        target_class = random_target_labels([orig_class], true_labels)\n        target_image = create_target_images(test_images, true_labels,\n                                            target_class)\n        nes_instance.set_target_images(target_image)\n        tag, adv, queries = nes_instance.generate(np.array(initial_img), np.array(target_class))\n        if tag[0]:\n            success += 1\n        queries_num += queries[0]\n        advs.append(adv)\n\n    advs = np.reshape(advs, (len(advs), 1, 32, 32))\n    adv_pred = np.argmax(model.predict(advs), axis=1)\n    adv_accuracy = np.mean(np.equal(adv_pred, true_labels[:test_length]))\n    LOGGER.info(TAG, \"prediction accuracy after attacking is : %s\",\n                adv_accuracy)\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    test_nes_mnist_attack()\n"
  },
  {
    "path": "examples/model_security/model_attacks/black_box/mnist_attack_pointwise.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy as np\nfrom scipy.special import softmax\n\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\n\nfrom mindarmour import BlackModel\nfrom mindarmour.adv_robustness.attacks import PointWiseAttack\nfrom mindarmour.adv_robustness.evaluations import AttackEvaluate\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Pointwise_Attack'\nLOGGER.set_level('INFO')\n\n\nclass ModelToBeAttacked(BlackModel):\n    \"\"\"model to be attack\"\"\"\n\n    def __init__(self, network):\n        super(ModelToBeAttacked, self).__init__()\n        self._network = network\n\n    def predict(self, inputs):\n        \"\"\"predict\"\"\"\n        if len(inputs.shape) == 3:\n            inputs = inputs[np.newaxis, :]\n        result = self._network(Tensor(inputs.astype(np.float32)))\n        return result.asnumpy()\n\n\ndef test_pointwise_attack_on_mnist():\n    \"\"\"\n    Salt-and-Pepper-Attack test\n    \"\"\"\n    # upload trained network\n    ckpt_path = '../../../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get test data\n    data_list = \"../../../common/dataset/MNIST/test\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size=batch_size)\n\n    # prediction accuracy before attack\n    model = ModelToBeAttacked(net)\n    batch_num = 3  # the number of batches of attacking samples\n    test_images = []\n    test_labels = []\n    predict_labels = []\n    i = 0\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        i += 1\n        images = data[0].astype(np.float32)\n        labels = data[1]\n        test_images.append(images)\n        test_labels.append(labels)\n        pred_labels = np.argmax(model.predict(images), axis=1)\n        predict_labels.append(pred_labels)\n        if i >= batch_num:\n            break\n    predict_labels = np.concatenate(predict_labels)\n    true_labels = np.concatenate(test_labels)\n    accuracy = np.mean(np.equal(predict_labels, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %g\", accuracy)\n\n    # attacking\n    is_target = False\n    attack = PointWiseAttack(model=model, is_targeted=is_target)\n    if is_target:\n        targeted_labels = np.random.randint(0, 10, size=len(true_labels))\n        for i, true_l in enumerate(true_labels):\n            if targeted_labels[i] == true_l:\n                targeted_labels[i] = (targeted_labels[i] + 1) % 10\n    else:\n        targeted_labels = true_labels\n    success_list, adv_data, query_list = attack.generate(\n        np.concatenate(test_images), targeted_labels)\n    success_list = np.arange(success_list.shape[0])[success_list]\n    LOGGER.info(TAG, 'success_list: %s', success_list)\n    LOGGER.info(TAG, 'average of query times is : %s', np.mean(query_list))\n    adv_preds = []\n    for ite_data in adv_data:\n        pred_logits_adv = model.predict(ite_data)\n        # rescale predict confidences into (0, 1).\n        pred_logits_adv = softmax(pred_logits_adv, axis=1)\n        adv_preds.extend(pred_logits_adv)\n    accuracy_adv = np.mean(np.equal(np.max(adv_preds, axis=1), true_labels))\n    LOGGER.info(TAG, \"prediction accuracy after attacking is : %g\",\n                accuracy_adv)\n    test_labels_onehot = np.eye(10)[true_labels]\n    attack_evaluate = AttackEvaluate(np.concatenate(test_images),\n                                     test_labels_onehot, adv_data,\n                                     np.array(adv_preds), targeted=is_target,\n                                     target_label=targeted_labels)\n    LOGGER.info(TAG, 'mis-classification rate of adversaries is : %s',\n                attack_evaluate.mis_classification_rate())\n    LOGGER.info(TAG, 'The average confidence of adversarial class is : %s',\n                attack_evaluate.avg_conf_adv_class())\n    LOGGER.info(TAG, 'The average confidence of true class is : %s',\n                attack_evaluate.avg_conf_true_class())\n    LOGGER.info(TAG, 'The average distance (l0, l2, linf) between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_lp_distance())\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    test_pointwise_attack_on_mnist()\n"
  },
  {
    "path": "examples/model_security/model_attacks/black_box/mnist_attack_pso.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport time\nimport numpy as np\nfrom scipy.special import softmax\n\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\n\nfrom mindarmour import BlackModel\nfrom mindarmour.adv_robustness.attacks.black.pso_attack import PSOAttack\nfrom mindarmour.adv_robustness.evaluations import AttackEvaluate\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'PSO_Attack'\n\n\nclass ModelToBeAttacked(BlackModel):\n    \"\"\"model to be attack\"\"\"\n\n    def __init__(self, network):\n        super(ModelToBeAttacked, self).__init__()\n        self._network = network\n\n    def predict(self, inputs):\n        \"\"\"predict\"\"\"\n        # Adapt to the input shape requirements of the target network if inputs is only one image.\n        if len(inputs.shape) == 3:\n            inputs = np.expand_dims(inputs, axis=0)\n        result = self._network(Tensor(inputs.astype(np.float32)))\n        return result.asnumpy()\n\n\ndef test_pso_attack_on_mnist():\n    \"\"\"\n    PSO-Attack test\n    \"\"\"\n    # upload trained network\n    ckpt_path = '../../../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get test data\n    data_list = \"../../../common/dataset/MNIST/test\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size=batch_size)\n\n    # prediction accuracy before attack\n    model = ModelToBeAttacked(net)\n    batch_num = 3  # the number of batches of attacking samples\n    test_images = []\n    test_labels = []\n    predict_labels = []\n    i = 0\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        i += 1\n        images = data[0].astype(np.float32)\n        labels = data[1]\n        test_images.append(images)\n        test_labels.append(labels)\n        pred_labels = np.argmax(model.predict(images), axis=1)\n        predict_labels.append(pred_labels)\n        if i >= batch_num:\n            break\n    predict_labels = np.concatenate(predict_labels)\n    true_labels = np.concatenate(test_labels)\n    accuracy = np.mean(np.equal(predict_labels, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %s\", accuracy)\n\n    # attacking\n    attack = PSOAttack(model, bounds=(0.0, 1.0), pm=0.5, sparse=True)\n    start_time = time.clock()\n    success_list, adv_data, query_list = attack.generate(\n        np.concatenate(test_images), np.concatenate(test_labels))\n    stop_time = time.clock()\n    LOGGER.info(TAG, 'success_list: %s', success_list)\n    LOGGER.info(TAG, 'average of query times is : %s', np.mean(query_list))\n    pred_logits_adv = model.predict(adv_data)\n    # rescale predict confidences into (0, 1).\n    pred_logits_adv = softmax(pred_logits_adv, axis=1)\n    pred_labels_adv = np.argmax(pred_logits_adv, axis=1)\n    accuracy_adv = np.mean(np.equal(pred_labels_adv, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy after attacking is : %s\",\n                accuracy_adv)\n    test_labels_onehot = np.eye(10)[np.concatenate(test_labels)]\n    attack_evaluate = AttackEvaluate(np.concatenate(test_images),\n                                     test_labels_onehot, adv_data,\n                                     pred_logits_adv)\n    LOGGER.info(TAG, 'mis-classification rate of adversaries is : %s',\n                attack_evaluate.mis_classification_rate())\n    LOGGER.info(TAG, 'The average confidence of adversarial class is : %s',\n                attack_evaluate.avg_conf_adv_class())\n    LOGGER.info(TAG, 'The average confidence of true class is : %s',\n                attack_evaluate.avg_conf_true_class())\n    LOGGER.info(TAG, 'The average distance (l0, l2, linf) between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_lp_distance())\n    LOGGER.info(TAG, 'The average structural similarity between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_ssim())\n    LOGGER.info(TAG, 'The average costing time is %s',\n                (stop_time - start_time)/(batch_num*batch_size))\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    test_pso_attack_on_mnist()\n"
  },
  {
    "path": "examples/model_security/model_attacks/black_box/mnist_attack_salt_and_pepper.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy as np\nfrom scipy.special import softmax\n\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\n\nfrom mindarmour import BlackModel\nfrom mindarmour.adv_robustness.attacks import SaltAndPepperNoiseAttack\nfrom mindarmour.adv_robustness.evaluations import AttackEvaluate\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Salt_and_Pepper_Attack'\nLOGGER.set_level('DEBUG')\n\n\nclass ModelToBeAttacked(BlackModel):\n    \"\"\"model to be attack\"\"\"\n\n    def __init__(self, network):\n        super(ModelToBeAttacked, self).__init__()\n        self._network = network\n\n    def predict(self, inputs):\n        \"\"\"predict\"\"\"\n        if len(inputs.shape) == 3:\n            inputs = inputs[np.newaxis, :]\n        result = self._network(Tensor(inputs.astype(np.float32)))\n        return result.asnumpy()\n\n\ndef test_salt_and_pepper_attack_on_mnist():\n    \"\"\"\n    Salt-and-Pepper-Attack test\n    \"\"\"\n    # upload trained network\n    ckpt_path = '../../../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get test data\n    data_list = \"../../../common/dataset/MNIST/test\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size=batch_size)\n\n    # prediction accuracy before attack\n    model = ModelToBeAttacked(net)\n    batch_num = 3  # the number of batches of attacking samples\n    test_images = []\n    test_labels = []\n    predict_labels = []\n    i = 0\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        i += 1\n        images = data[0].astype(np.float32)\n        labels = data[1]\n        test_images.append(images)\n        test_labels.append(labels)\n        pred_labels = np.argmax(model.predict(images), axis=1)\n        predict_labels.append(pred_labels)\n        if i >= batch_num:\n            break\n    LOGGER.debug(TAG, 'model input image shape is: {}'.format(np.array(test_images).shape))\n    predict_labels = np.concatenate(predict_labels)\n    true_labels = np.concatenate(test_labels)\n    accuracy = np.mean(np.equal(predict_labels, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %g\", accuracy)\n\n    # attacking\n    is_target = False\n    attack = SaltAndPepperNoiseAttack(model=model, is_targeted=is_target, sparse=True)\n    if is_target:\n        targeted_labels = np.random.randint(0, 10, size=len(true_labels))\n        for i, true_l in enumerate(true_labels):\n            if targeted_labels[i] == true_l:\n                targeted_labels[i] = (targeted_labels[i] + 1) % 10\n    else:\n        targeted_labels = true_labels\n    LOGGER.debug(TAG, 'input shape is: {}'.format(np.concatenate(test_images).shape))\n    success_list, adv_data, query_list = attack.generate(np.concatenate(test_images), targeted_labels)\n    success_list = np.arange(success_list.shape[0])[success_list]\n    LOGGER.info(TAG, 'success_list: %s', success_list)\n    LOGGER.info(TAG, 'average of query times is : %s', np.mean(query_list))\n    adv_preds = []\n    for ite_data in adv_data:\n        pred_logits_adv = model.predict(ite_data)\n        # rescale predict confidences into (0, 1).\n        pred_logits_adv = softmax(pred_logits_adv, axis=1)\n        adv_preds.extend(pred_logits_adv)\n    adv_preds = np.array(adv_preds)\n    accuracy_adv = np.mean(np.equal(np.max(adv_preds, axis=1), true_labels))\n    LOGGER.info(TAG, \"prediction accuracy after attacking is : %g\", accuracy_adv)\n    test_labels_onehot = np.eye(10)[true_labels]\n    attack_evaluate = AttackEvaluate(np.concatenate(test_images),\n                                     test_labels_onehot, adv_data,\n                                     adv_preds, targeted=is_target,\n                                     target_label=targeted_labels)\n    LOGGER.info(TAG, 'mis-classification rate of adversaries is : %s', attack_evaluate.mis_classification_rate())\n    LOGGER.info(TAG, 'The average confidence of adversarial class is : %s', attack_evaluate.avg_conf_adv_class())\n    LOGGER.info(TAG, 'The average confidence of true class is : %s', attack_evaluate.avg_conf_true_class())\n    LOGGER.info(TAG, 'The average distance (l0, l2, linf) between original samples and adversarial samples are: %s',\n                attack_evaluate.avg_lp_distance())\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    test_salt_and_pepper_attack_on_mnist()\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/README.md",
    "content": "# Dataset\n\nDataset used: [COCO2017](<https://cocodataset.org/>) \n\n- Dataset size：19G\n  - Train：18G，118000 images  \n  - Val：1G，5000 images \n  - Annotations：241M，instances，captions，person_keypoints etc\n- Data format：image and json files\n  - Note：Data will be processed in dataset.py\n\n# Environment Requirements\n\n- Install [MindSpore](https://www.mindspore.cn/install/en).\n\n- Download the dataset COCO2017.\n\n- We use COCO2017 as dataset in this example.\n\n    Install Cython and pycocotool, and you can also install mmcv to process data.\n\n    ```\n    pip install Cython\n\n    pip install pycocotools\n\n    pip install mmcv==0.2.14\n    ```\n\n    And change the COCO_ROOT and other settings you need in `config.py`. The directory structure is as follows:\n\n    ```\n    .\n    └─cocodataset\n      ├─annotations\n        ├─instance_train2017.json\n        └─instance_val2017.json\n      ├─val2017\n      └─train2017    \n    ```\n\n# Quick start\nYou can download the pre-trained model checkpoint file [here](<https://www.mindspore.cn/resources/hub/details?2505/MindSpore/ascend/0.7/fasterrcnn_v1.0_coco2017>).\n```\npython coco_attack_pgd.py --pre_trained [PRETRAINED_CHECKPOINT_FILE] \n```\n> Adversarial samples will be generated.\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/coco_attack_genetic.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n\"\"\"PSO attack for Faster R-CNN\"\"\"\r\nimport os\r\nimport numpy as np\r\n\r\nfrom mindspore import context\r\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\r\nfrom mindspore.common import set_seed\r\nfrom mindspore import Tensor\r\n\r\nfrom mindarmour import BlackModel\r\nfrom mindarmour.adv_robustness.attacks.black.genetic_attack import GeneticAttack\r\nfrom mindarmour.utils.logger import LogUtil\r\n\r\nfrom src.FasterRcnn.faster_rcnn_r50 import Faster_Rcnn_Resnet50\r\nfrom src.config import config\r\nfrom src.dataset import data_to_mindrecord_byte_image, create_fasterrcnn_dataset\r\n\r\n# pylint: disable=locally-disabled, unused-argument, redefined-outer-name\r\nLOGGER = LogUtil.get_instance()\r\nLOGGER.set_level('INFO')\r\n\r\nset_seed(1)\r\n\r\ncontext.set_context(mode=context.GRAPH_MODE, device_target='Ascend', device_id=1)\r\n\r\n\r\nclass ModelToBeAttacked(BlackModel):\r\n    \"\"\"model to be attack\"\"\"\r\n\r\n    def __init__(self, network):\r\n        super(ModelToBeAttacked, self).__init__()\r\n        self._network = network\r\n\r\n    def predict(self, images, img_metas, gt_boxes, gt_labels, gt_num):\r\n        \"\"\"predict\"\"\"\r\n        # Adapt to the input shape requirements of the target network if inputs is only one image.\r\n        if len(images.shape) == 3:\r\n            inputs_num = 1\r\n            images = np.expand_dims(images, axis=0)\r\n        else:\r\n            inputs_num = images.shape[0]\r\n        box_and_confi = []\r\n        pred_labels = []\r\n        gt_number = np.sum(gt_num)\r\n\r\n        for i in range(inputs_num):\r\n            inputs_i = np.expand_dims(images[i], axis=0)\r\n            output = self._network(Tensor(inputs_i.astype(np.float16)), Tensor(img_metas),\r\n                                   Tensor(gt_boxes), Tensor(gt_labels), Tensor(gt_num))\r\n            all_bbox = output[0]\r\n            all_labels = output[1]\r\n            all_mask = output[2]\r\n            all_bbox_squee = np.squeeze(all_bbox.asnumpy())\r\n            all_labels_squee = np.squeeze(all_labels.asnumpy())\r\n            all_mask_squee = np.squeeze(all_mask.asnumpy())\r\n            all_bboxes_tmp_mask = all_bbox_squee[all_mask_squee, :]\r\n            all_labels_tmp_mask = all_labels_squee[all_mask_squee]\r\n\r\n            if all_bboxes_tmp_mask.shape[0] > gt_number + 1:\r\n                inds = np.argsort(-all_bboxes_tmp_mask[:, -1])\r\n                inds = inds[:gt_number+1]\r\n                all_bboxes_tmp_mask = all_bboxes_tmp_mask[inds]\r\n                all_labels_tmp_mask = all_labels_tmp_mask[inds]\r\n            box_and_confi.append(all_bboxes_tmp_mask)\r\n            pred_labels.append(all_labels_tmp_mask)\r\n        return np.array(box_and_confi), np.array(pred_labels)\r\n\r\n\r\nif __name__ == '__main__':\r\n    prefix = 'FasterRcnn_eval.mindrecord'\r\n    mindrecord_dir = config.mindrecord_dir\r\n    mindrecord_file = os.path.join(mindrecord_dir, prefix)\r\n    pre_trained = '/ckpt_path'\r\n    print(\"CHECKING MINDRECORD FILES ...\")\r\n    if not os.path.exists(mindrecord_file):\r\n        if not os.path.isdir(mindrecord_dir):\r\n            os.makedirs(mindrecord_dir)\r\n        if os.path.isdir(config.coco_root):\r\n            print(\"Create Mindrecord. It may take some time.\")\r\n            data_to_mindrecord_byte_image(\"coco\", False, prefix, file_num=1)\r\n            print(\"Create Mindrecord Done, at {}\".format(mindrecord_dir))\r\n        else:\r\n            print(\"coco_root not exits.\")\r\n\r\n    print('Start generate adversarial samples.')\r\n\r\n    # build network and dataset\r\n    ds = create_fasterrcnn_dataset(mindrecord_file, batch_size=config.test_batch_size, \\\r\n                                    repeat_num=1, is_training=False)\r\n    net = Faster_Rcnn_Resnet50(config)\r\n    param_dict = load_checkpoint(pre_trained)\r\n    load_param_into_net(net, param_dict)\r\n    net = net.set_train(False)\r\n\r\n    # build attacker\r\n    model = ModelToBeAttacked(net)\r\n    attack = GeneticAttack(model, model_type='detection', max_steps=50, reserve_ratio=0.3, mutation_rate=0.05,\r\n                           per_bounds=0.5, step_size=0.25, temp=0.1)\r\n\r\n    # generate adversarial samples\r\n    sample_num = 5\r\n    ori_imagess = []\r\n    adv_imgs = []\r\n    ori_meta = []\r\n    ori_box = []\r\n    ori_labels = []\r\n    ori_gt_num = []\r\n    idx = 0\r\n    for data in ds.create_dict_iterator():\r\n        if idx > sample_num:\r\n            break\r\n        img_data = data['image']\r\n        img_metas = data['image_shape']\r\n        gt_bboxes = data['box']\r\n        gt_labels = data['label']\r\n        gt_num = data['valid_num']\r\n\r\n        ori_imagess.append(img_data.asnumpy())\r\n        ori_meta.append(img_metas.asnumpy())\r\n        ori_box.append(gt_bboxes.asnumpy())\r\n        ori_labels.append(gt_labels.asnumpy())\r\n        ori_gt_num.append(gt_num.asnumpy())\r\n\r\n        all_inputs = (img_data.asnumpy(), img_metas.asnumpy(), gt_bboxes.asnumpy(),\r\n                      gt_labels.asnumpy(), gt_num.asnumpy())\r\n\r\n        pre_gt_boxes, pre_gt_label = model.predict(*all_inputs)\r\n        success_flags, adv_img, query_times = attack.generate(all_inputs, (pre_gt_boxes, pre_gt_label))\r\n        adv_imgs.append(adv_img)\r\n        idx += 1\r\n    np.save('ori_imagess.npy', ori_imagess)\r\n    np.save('ori_meta.npy', ori_meta)\r\n    np.save('ori_box.npy', ori_box)\r\n    np.save('ori_labels.npy', ori_labels)\r\n    np.save('ori_gt_num.npy', ori_gt_num)\r\n    np.save('adv_imgs.npy', adv_imgs)\r\n    print('Generate adversarial samples complete.')\r\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/coco_attack_pgd.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"PGD attack for faster rcnn\"\"\"\nimport os\nimport argparse\n\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nfrom mindspore.common import set_seed\nfrom mindspore.nn import Cell\nfrom mindspore.ops.composite import GradOperation\n\nfrom mindarmour.adv_robustness.attacks import ProjectedGradientDescent\n\nfrom src.FasterRcnn.faster_rcnn_r50 import Faster_Rcnn_Resnet50\nfrom src.config import config\nfrom src.dataset import data_to_mindrecord_byte_image, create_fasterrcnn_dataset\n\n# pylint: disable=locally-disabled, unused-argument, redefined-outer-name\n\nset_seed(1)\n\nparser = argparse.ArgumentParser(description='FasterRCNN attack')\nparser.add_argument('--pre_trained', type=str, required=True, help='pre-trained ckpt file path for target model.')\nparser.add_argument('--device_id', type=int, default=0, help='Device id, default is 0.')\nparser.add_argument('--num', type=int, default=5, help='Number of adversarial examples.')\nargs = parser.parse_args()\n\ncontext.set_context(mode=context.GRAPH_MODE, device_target='Ascend', device_id=args.device_id)\n\n\nclass LossNet(Cell):\n    \"\"\"loss function.\"\"\"\n    def construct(self, x1, x2, x3, x4, x5, x6):\n        return x4 + x6\n\n\nclass WithLossCell(Cell):\n    \"\"\"Wrap the network with loss function.\"\"\"\n    def __init__(self, backbone, loss_fn):\n        super(WithLossCell, self).__init__(auto_prefix=False)\n        self._backbone = backbone\n        self._loss_fn = loss_fn\n\n    def construct(self, img_data, img_metas, gt_bboxes, gt_labels, gt_num, *labels):\n        loss1, loss2, loss3, loss4, loss5, loss6 = self._backbone(img_data, img_metas, gt_bboxes, gt_labels, gt_num)\n        return self._loss_fn(loss1, loss2, loss3, loss4, loss5, loss6)\n\n    @property\n    def backbone_network(self):\n        return self._backbone\n\n\nclass GradWrapWithLoss(Cell):\n    \"\"\"\n    Construct a network to compute the gradient of loss function in \\\n    input space and weighted by `weight`.\n    \"\"\"\n    def __init__(self, network):\n        super(GradWrapWithLoss, self).__init__()\n        self._grad_all = GradOperation(get_all=True, sens_param=False)\n        self._network = network\n\n    def construct(self, *inputs):\n        gout = self._grad_all(self._network)(*inputs)\n        return gout[0]\n\n\nif __name__ == '__main__':\n    prefix = 'FasterRcnn_eval.mindrecord'\n    mindrecord_dir = config.mindrecord_dir\n    mindrecord_file = os.path.join(mindrecord_dir, prefix)\n    pre_trained = args.pre_trained\n\n    print(\"CHECKING MINDRECORD FILES ...\")\n    if not os.path.exists(mindrecord_file):\n        if not os.path.isdir(mindrecord_dir):\n            os.makedirs(mindrecord_dir)\n        if os.path.isdir(config.coco_root):\n            print(\"Create Mindrecord. It may take some time.\")\n            data_to_mindrecord_byte_image(\"coco\", False, prefix, file_num=1)\n            print(\"Create Mindrecord Done, at {}\".format(mindrecord_dir))\n        else:\n            print(\"coco_root not exits.\")\n\n    print('Start generate adversarial samples.')\n\n    # build network and dataset\n    ds = create_fasterrcnn_dataset(mindrecord_file, batch_size=config.test_batch_size, \\\n                                    repeat_num=1, is_training=True)\n    net = Faster_Rcnn_Resnet50(config)\n    param_dict = load_checkpoint(pre_trained)\n    load_param_into_net(net, param_dict)\n    net = net.set_train()\n\n    # build attacker\n    with_loss_cell = WithLossCell(net, LossNet())\n    grad_with_loss_net = GradWrapWithLoss(with_loss_cell)\n    attack = ProjectedGradientDescent(grad_with_loss_net, bounds=None, eps=0.1)\n\n    # generate adversarial samples\n    num = args.num\n    num_batches = num // config.test_batch_size\n    channel = 3\n    adv_samples = [0]*(num_batches*config.test_batch_size)\n    adv_id = 0\n    for data in ds.create_dict_iterator(num_epochs=num_batches):\n        img_data = data['image']\n        img_metas = data['image_shape']\n        gt_bboxes = data['box']\n        gt_labels = data['label']\n        gt_num = data['valid_num']\n\n        adv_img = attack.generate((img_data.asnumpy(), \\\n            img_metas.asnumpy(), gt_bboxes.asnumpy(), gt_labels.asnumpy(), gt_num.asnumpy()), gt_labels.asnumpy())\n        for item in adv_img:\n            adv_samples[adv_id] = item\n            adv_id += 1\n        if adv_id >= num_batches*config.test_batch_size:\n            break\n    print('Generate adversarial samples complete.')\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/coco_attack_pso.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n\"\"\"PSO attack for Faster R-CNN\"\"\"\r\nimport os\r\nimport numpy as np\r\n\r\nfrom mindspore import context\r\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\r\nfrom mindspore.common import set_seed\r\nfrom mindspore import Tensor\r\n\r\nfrom mindarmour import BlackModel\r\nfrom mindarmour.adv_robustness.attacks.black.pso_attack import PSOAttack\r\nfrom mindarmour.utils.logger import LogUtil\r\n\r\nfrom src.FasterRcnn.faster_rcnn_r50 import Faster_Rcnn_Resnet50\r\nfrom src.config import config\r\nfrom src.dataset import data_to_mindrecord_byte_image, create_fasterrcnn_dataset\r\n\r\n# pylint: disable=locally-disabled, unused-argument, redefined-outer-name\r\nLOGGER = LogUtil.get_instance()\r\nLOGGER.set_level('INFO')\r\n\r\nset_seed(1)\r\n\r\ncontext.set_context(mode=context.GRAPH_MODE, device_target='Ascend', device_id=1)\r\n\r\n\r\nclass ModelToBeAttacked(BlackModel):\r\n    \"\"\"model to be attack\"\"\"\r\n\r\n    def __init__(self, network):\r\n        super(ModelToBeAttacked, self).__init__()\r\n        self._network = network\r\n\r\n    def predict(self, images, img_metas, gt_boxes, gt_labels, gt_num):\r\n        \"\"\"predict\"\"\"\r\n        # Adapt to the input shape requirements of the target network if inputs is only one image.\r\n        if len(images.shape) == 3:\r\n            inputs_num = 1\r\n            images = np.expand_dims(images, axis=0)\r\n        else:\r\n            inputs_num = images.shape[0]\r\n        box_and_confi = []\r\n        pred_labels = []\r\n        gt_number = np.sum(gt_num)\r\n\r\n        for i in range(inputs_num):\r\n            inputs_i = np.expand_dims(images[i], axis=0)\r\n            output = self._network(Tensor(inputs_i.astype(np.float16)), Tensor(img_metas),\r\n                                   Tensor(gt_boxes), Tensor(gt_labels), Tensor(gt_num))\r\n            all_bbox = output[0]\r\n            all_labels = output[1]\r\n            all_mask = output[2]\r\n            all_bbox_squee = np.squeeze(all_bbox.asnumpy())\r\n            all_labels_squee = np.squeeze(all_labels.asnumpy())\r\n            all_mask_squee = np.squeeze(all_mask.asnumpy())\r\n            all_bboxes_tmp_mask = all_bbox_squee[all_mask_squee, :]\r\n            all_labels_tmp_mask = all_labels_squee[all_mask_squee]\r\n\r\n            if all_bboxes_tmp_mask.shape[0] > gt_number + 1:\r\n                inds = np.argsort(-all_bboxes_tmp_mask[:, -1])\r\n                inds = inds[:gt_number+1]\r\n                all_bboxes_tmp_mask = all_bboxes_tmp_mask[inds]\r\n                all_labels_tmp_mask = all_labels_tmp_mask[inds]\r\n            box_and_confi.append(all_bboxes_tmp_mask)\r\n            pred_labels.append(all_labels_tmp_mask)\r\n        return np.array(box_and_confi), np.array(pred_labels)\r\n\r\n\r\nif __name__ == '__main__':\r\n    prefix = 'FasterRcnn_eval.mindrecord'\r\n    mindrecord_dir = config.mindrecord_dir\r\n    mindrecord_file = os.path.join(mindrecord_dir, prefix)\r\n    pre_trained = '/ckpt_path'\r\n    print(\"CHECKING MINDRECORD FILES ...\")\r\n    if not os.path.exists(mindrecord_file):\r\n        if not os.path.isdir(mindrecord_dir):\r\n            os.makedirs(mindrecord_dir)\r\n        if os.path.isdir(config.coco_root):\r\n            print(\"Create Mindrecord. It may take some time.\")\r\n            data_to_mindrecord_byte_image(\"coco\", False, prefix, file_num=1)\r\n            print(\"Create Mindrecord Done, at {}\".format(mindrecord_dir))\r\n        else:\r\n            print(\"coco_root not exits.\")\r\n\r\n    print('Start generate adversarial samples.')\r\n\r\n    # build network and dataset\r\n    ds = create_fasterrcnn_dataset(mindrecord_file, batch_size=config.test_batch_size, \\\r\n                                    repeat_num=1, is_training=False)\r\n    net = Faster_Rcnn_Resnet50(config)\r\n    param_dict = load_checkpoint(pre_trained)\r\n    load_param_into_net(net, param_dict)\r\n    net = net.set_train(False)\r\n\r\n    # build attacker\r\n    model = ModelToBeAttacked(net)\r\n    attack = PSOAttack(model, c=0.2, t_max=50, pm=0.5, model_type='detection', reserve_ratio=0.3)\r\n\r\n    # generate adversarial samples\r\n    sample_num = 5\r\n    ori_imagess = []\r\n    adv_imgs = []\r\n    ori_meta = []\r\n    ori_box = []\r\n    ori_labels = []\r\n    ori_gt_num = []\r\n    idx = 0\r\n    for data in ds.create_dict_iterator():\r\n        if idx > sample_num:\r\n            break\r\n        img_data = data['image']\r\n        img_metas = data['image_shape']\r\n        gt_bboxes = data['box']\r\n        gt_labels = data['label']\r\n        gt_num = data['valid_num']\r\n\r\n        ori_imagess.append(img_data.asnumpy())\r\n        ori_meta.append(img_metas.asnumpy())\r\n        ori_box.append(gt_bboxes.asnumpy())\r\n        ori_labels.append(gt_labels.asnumpy())\r\n        ori_gt_num.append(gt_num.asnumpy())\r\n\r\n        all_inputs = (img_data.asnumpy(), img_metas.asnumpy(), gt_bboxes.asnumpy(),\r\n                      gt_labels.asnumpy(), gt_num.asnumpy())\r\n\r\n        pre_gt_boxes, pre_gt_label = model.predict(*all_inputs)\r\n        success_flags, adv_img, query_times = attack.generate(all_inputs, (pre_gt_boxes, pre_gt_label))\r\n        adv_imgs.append(adv_img)\r\n        idx += 1\r\n    np.save('ori_imagess.npy', ori_imagess)\r\n    np.save('ori_meta.npy', ori_meta)\r\n    np.save('ori_box.npy', ori_box)\r\n    np.save('ori_labels.npy', ori_labels)\r\n    np.save('ori_gt_num.npy', ori_gt_num)\r\n    np.save('adv_imgs.npy', adv_imgs)\r\n    print('Generate adversarial samples complete.')\r\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/src/FasterRcnn/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"FasterRcnn Init.\"\"\"\n\nfrom .resnet50 import ResNetFea, ResidualBlockUsing\nfrom .bbox_assign_sample import BboxAssignSample\nfrom .bbox_assign_sample_stage2 import BboxAssignSampleForRcnn\nfrom .fpn_neck import FeatPyramidNeck\nfrom .proposal_generator import Proposal\nfrom .rcnn import Rcnn\nfrom .rpn import RPN\nfrom .roi_align import SingleRoIExtractor\nfrom .anchor_generator import AnchorGenerator\n\n__all__ = [\n    \"ResNetFea\", \"BboxAssignSample\", \"BboxAssignSampleForRcnn\",\n    \"FeatPyramidNeck\", \"Proposal\", \"Rcnn\",\n    \"RPN\", \"SingleRoIExtractor\", \"AnchorGenerator\", \"ResidualBlockUsing\"\n]\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/src/FasterRcnn/anchor_generator.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"FasterRcnn anchor generator.\"\"\"\n\nimport numpy as np\n\nclass AnchorGenerator():\n    \"\"\"Anchor generator for FasterRcnn.\"\"\"\n    def __init__(self, base_size, scales, ratios, scale_major=True, ctr=None):\n        \"\"\"Anchor generator init method.\"\"\"\n        self.base_size = base_size\n        self.scales = np.array(scales)\n        self.ratios = np.array(ratios)\n        self.scale_major = scale_major\n        self.ctr = ctr\n        self.base_anchors = self.gen_base_anchors()\n\n    def gen_base_anchors(self):\n        \"\"\"Generate a single anchor.\"\"\"\n        w = self.base_size\n        h = self.base_size\n        if self.ctr is None:\n            x_ctr = 0.5 * (w - 1)\n            y_ctr = 0.5 * (h - 1)\n        else:\n            x_ctr, y_ctr = self.ctr\n\n        h_ratios = np.sqrt(self.ratios)\n        w_ratios = 1 / h_ratios\n        if self.scale_major:\n            ws = (w * w_ratios[:, None] * self.scales[None, :]).reshape(-1)\n            hs = (h * h_ratios[:, None] * self.scales[None, :]).reshape(-1)\n        else:\n            ws = (w * self.scales[:, None] * w_ratios[None, :]).reshape(-1)\n            hs = (h * self.scales[:, None] * h_ratios[None, :]).reshape(-1)\n\n        base_anchors = np.stack(\n            [\n                x_ctr - 0.5 * (ws - 1), y_ctr - 0.5 * (hs - 1),\n                x_ctr + 0.5 * (ws - 1), y_ctr + 0.5 * (hs - 1)\n            ],\n            axis=-1).round()\n\n        return base_anchors\n\n    def _meshgrid(self, x, y, row_major=True):\n        \"\"\"Generate grid.\"\"\"\n        xx = np.repeat(x.reshape(1, len(x)), len(y), axis=0).reshape(-1)\n        yy = np.repeat(y, len(x))\n        if row_major:\n            return xx, yy\n\n        return yy, xx\n\n    def grid_anchors(self, featmap_size, stride=16):\n        \"\"\"Generate anchor list.\"\"\"\n        base_anchors = self.base_anchors\n\n        feat_h, feat_w = featmap_size\n        shift_x = np.arange(0, feat_w) * stride\n        shift_y = np.arange(0, feat_h) * stride\n        shift_xx, shift_yy = self._meshgrid(shift_x, shift_y)\n        shifts = np.stack([shift_xx, shift_yy, shift_xx, shift_yy], axis=-1)\n        shifts = shifts.astype(base_anchors.dtype)\n        # first feat_w elements correspond to the first row of shifts\n        # add A anchors (1, A, 4) to K shifts (K, 1, 4) to get\n        # shifted anchors (K, A, 4), reshape to (K*A, 4)\n\n        all_anchors = base_anchors[None, :, :] + shifts[:, None, :]\n        all_anchors = all_anchors.reshape(-1, 4)\n\n        return all_anchors\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/src/FasterRcnn/bbox_assign_sample.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"FasterRcnn positive and negative sample screening for RPN.\"\"\"\n\nimport numpy as np\nimport mindspore.nn as nn\nfrom mindspore.ops import operations as P\nfrom mindspore.common.tensor import Tensor\nimport mindspore.common.dtype as mstype\n\n# pylint: disable=locally-disabled, invalid-name, missing-docstring\n\n\nclass BboxAssignSample(nn.Cell):\n    \"\"\"\n    Bbox assigner and sampler defination.\n\n    Args:\n        config (dict): Config.\n        batch_size (int): Batchsize.\n        num_bboxes (int): The anchor nums.\n        add_gt_as_proposals (bool): add gt bboxes as proposals flag.\n\n    Returns:\n        Tensor, output tensor.\n        bbox_targets: bbox location, (batch_size, num_bboxes, 4)\n        bbox_weights: bbox weights, (batch_size, num_bboxes, 1)\n        labels: label for every bboxes, (batch_size, num_bboxes, 1)\n        label_weights: label weight for every bboxes, (batch_size, num_bboxes, 1)\n\n    Examples:\n        BboxAssignSample(config, 2, 1024, True)\n    \"\"\"\n\n    def __init__(self, config, batch_size, num_bboxes, add_gt_as_proposals):\n        super(BboxAssignSample, self).__init__()\n        cfg = config\n        self.batch_size = batch_size\n\n        self.neg_iou_thr = Tensor(cfg.neg_iou_thr, mstype.float16)\n        self.pos_iou_thr = Tensor(cfg.pos_iou_thr, mstype.float16)\n        self.min_pos_iou = Tensor(cfg.min_pos_iou, mstype.float16)\n        self.zero_thr = Tensor(0.0, mstype.float16)\n\n        self.num_bboxes = num_bboxes\n        self.num_gts = cfg.num_gts\n        self.num_expected_pos = cfg.num_expected_pos\n        self.num_expected_neg = cfg.num_expected_neg\n        self.add_gt_as_proposals = add_gt_as_proposals\n\n        if self.add_gt_as_proposals:\n            self.label_inds = Tensor(np.arange(1, self.num_gts + 1))\n\n        self.concat = P.Concat(axis=0)\n        self.max_gt = P.ArgMaxWithValue(axis=0)\n        self.max_anchor = P.ArgMaxWithValue(axis=1)\n        self.sum_inds = P.ReduceSum()\n        self.iou = P.IOU()\n        self.greaterequal = P.GreaterEqual()\n        self.greater = P.Greater()\n        self.select = P.Select()\n        self.gatherND = P.GatherNd()\n        self.squeeze = P.Squeeze()\n        self.cast = P.Cast()\n        self.logicaland = P.LogicalAnd()\n        self.less = P.Less()\n        self.random_choice_with_mask_pos = P.RandomChoiceWithMask(self.num_expected_pos)\n        self.random_choice_with_mask_neg = P.RandomChoiceWithMask(self.num_expected_neg)\n        self.reshape = P.Reshape()\n        self.equal = P.Equal()\n        self.bounding_box_encode = P.BoundingBoxEncode(means=(0.0, 0.0, 0.0, 0.0), stds=(1.0, 1.0, 1.0, 1.0))\n        self.scatterNdUpdate = P.ScatterNdUpdate()\n        self.scatterNd = P.ScatterNd()\n        self.logicalnot = P.LogicalNot()\n        self.tile = P.Tile()\n        self.zeros_like = P.ZerosLike()\n\n        self.assigned_gt_inds = Tensor(np.array(-1 * np.ones(num_bboxes), dtype=np.int32))\n        self.assigned_gt_zeros = Tensor(np.array(np.zeros(num_bboxes), dtype=np.int32))\n        self.assigned_gt_ones = Tensor(np.array(np.ones(num_bboxes), dtype=np.int32))\n        self.assigned_gt_ignores = Tensor(np.array(-1 * np.ones(num_bboxes), dtype=np.int32))\n        self.assigned_pos_ones = Tensor(np.array(np.ones(self.num_expected_pos), dtype=np.int32))\n\n        self.check_neg_mask = Tensor(np.array(np.ones(self.num_expected_neg - self.num_expected_pos), dtype=np.bool))\n        self.range_pos_size = Tensor(np.arange(self.num_expected_pos).astype(np.float16))\n        self.check_gt_one = Tensor(np.array(-1 * np.ones((self.num_gts, 4)), dtype=np.float16))\n        self.check_anchor_two = Tensor(np.array(-2 * np.ones((self.num_bboxes, 4)), dtype=np.float16))\n\n\n    def construct(self, gt_bboxes_i, gt_labels_i, valid_mask, bboxes, gt_valids):\n        gt_bboxes_i = self.select(self.cast(self.tile(self.reshape(self.cast(gt_valids, mstype.int32), \\\n                                  (self.num_gts, 1)), (1, 4)), mstype.bool_), gt_bboxes_i, self.check_gt_one)\n        bboxes = self.select(self.cast(self.tile(self.reshape(self.cast(valid_mask, mstype.int32), \\\n                             (self.num_bboxes, 1)), (1, 4)), mstype.bool_), bboxes, self.check_anchor_two)\n\n        overlaps = self.iou(bboxes, gt_bboxes_i)\n\n        max_overlaps_w_gt_index, max_overlaps_w_gt = self.max_gt(overlaps)\n        _, max_overlaps_w_ac = self.max_anchor(overlaps)\n\n        neg_sample_iou_mask = self.logicaland(self.greaterequal(max_overlaps_w_gt, self.zero_thr), \\\n                                              self.less(max_overlaps_w_gt, self.neg_iou_thr))\n        assigned_gt_inds2 = self.select(neg_sample_iou_mask, self.assigned_gt_zeros, self.assigned_gt_inds)\n\n        pos_sample_iou_mask = self.greaterequal(max_overlaps_w_gt, self.pos_iou_thr)\n        assigned_gt_inds3 = self.select(pos_sample_iou_mask, \\\n                                        max_overlaps_w_gt_index + self.assigned_gt_ones, assigned_gt_inds2)\n        assigned_gt_inds4 = assigned_gt_inds3\n        for j in range(self.num_gts):\n            max_overlaps_w_ac_j = max_overlaps_w_ac[j:j+1:1]\n            overlaps_w_gt_j = self.squeeze(overlaps[j:j+1:1, ::])\n\n            pos_mask_j = self.logicaland(self.greaterequal(max_overlaps_w_ac_j, self.min_pos_iou), \\\n                                         self.equal(overlaps_w_gt_j, max_overlaps_w_ac_j))\n\n            assigned_gt_inds4 = self.select(pos_mask_j, self.assigned_gt_ones + j, assigned_gt_inds4)\n\n        assigned_gt_inds5 = self.select(valid_mask, assigned_gt_inds4, self.assigned_gt_ignores)\n\n        pos_index, valid_pos_index = self.random_choice_with_mask_pos(self.greater(assigned_gt_inds5, 0))\n\n        pos_check_valid = self.cast(self.greater(assigned_gt_inds5, 0), mstype.float16)\n        pos_check_valid = self.sum_inds(pos_check_valid, -1)\n        valid_pos_index = self.less(self.range_pos_size, pos_check_valid)\n        pos_index = pos_index * self.reshape(self.cast(valid_pos_index, mstype.int32), (self.num_expected_pos, 1))\n\n        pos_assigned_gt_index = self.gatherND(assigned_gt_inds5, pos_index) - self.assigned_pos_ones\n        pos_assigned_gt_index = pos_assigned_gt_index * self.cast(valid_pos_index, mstype.int32)\n        pos_assigned_gt_index = self.reshape(pos_assigned_gt_index, (self.num_expected_pos, 1))\n\n        neg_index, valid_neg_index = self.random_choice_with_mask_neg(self.equal(assigned_gt_inds5, 0))\n\n        num_pos = self.cast(self.logicalnot(valid_pos_index), mstype.float16)\n        num_pos = self.sum_inds(num_pos, -1)\n        unvalid_pos_index = self.less(self.range_pos_size, num_pos)\n        valid_neg_index = self.logicaland(self.concat((self.check_neg_mask, unvalid_pos_index)), valid_neg_index)\n\n        pos_bboxes_ = self.gatherND(bboxes, pos_index)\n        pos_gt_bboxes_ = self.gatherND(gt_bboxes_i, pos_assigned_gt_index)\n        pos_gt_labels = self.gatherND(gt_labels_i, pos_assigned_gt_index)\n\n        pos_bbox_targets_ = self.bounding_box_encode(pos_bboxes_, pos_gt_bboxes_)\n\n        valid_pos_index = self.cast(valid_pos_index, mstype.int32)\n        valid_neg_index = self.cast(valid_neg_index, mstype.int32)\n        bbox_targets_total = self.scatterNd(pos_index, pos_bbox_targets_, (self.num_bboxes, 4))\n        bbox_weights_total = self.scatterNd(pos_index, valid_pos_index, (self.num_bboxes,))\n        labels_total = self.scatterNd(pos_index, pos_gt_labels, (self.num_bboxes,))\n        total_index = self.concat((pos_index, neg_index))\n        total_valid_index = self.concat((valid_pos_index, valid_neg_index))\n        label_weights_total = self.scatterNd(total_index, total_valid_index, (self.num_bboxes,))\n\n        return bbox_targets_total, self.cast(bbox_weights_total, mstype.bool_), \\\n               labels_total, self.cast(label_weights_total, mstype.bool_)\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/src/FasterRcnn/bbox_assign_sample_stage2.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"FasterRcnn tpositive and negative sample screening for Rcnn.\"\"\"\n\nimport numpy as np\nimport mindspore.nn as nn\nimport mindspore.common.dtype as mstype\nfrom mindspore.ops import operations as P\nfrom mindspore.common.tensor import Tensor\n\n# pylint: disable=locally-disabled, invalid-name, missing-docstring\n\n\nclass BboxAssignSampleForRcnn(nn.Cell):\n    \"\"\"\n    Bbox assigner and sampler defination.\n\n    Args:\n        config (dict): Config.\n        batch_size (int): Batchsize.\n        num_bboxes (int): The anchor nums.\n        add_gt_as_proposals (bool): add gt bboxes as proposals flag.\n\n    Returns:\n        Tensor, output tensor.\n        bbox_targets: bbox location, (batch_size, num_bboxes, 4)\n        bbox_weights: bbox weights, (batch_size, num_bboxes, 1)\n        labels: label for every bboxes, (batch_size, num_bboxes, 1)\n        label_weights: label weight for every bboxes, (batch_size, num_bboxes, 1)\n\n    Examples:\n        BboxAssignSampleForRcnn(config, 2, 1024, True)\n    \"\"\"\n\n    def __init__(self, config, batch_size, num_bboxes, add_gt_as_proposals):\n        super(BboxAssignSampleForRcnn, self).__init__()\n        cfg = config\n        self.batch_size = batch_size\n        self.neg_iou_thr = cfg.neg_iou_thr_stage2\n        self.pos_iou_thr = cfg.pos_iou_thr_stage2\n        self.min_pos_iou = cfg.min_pos_iou_stage2\n        self.num_gts = cfg.num_gts\n        self.num_bboxes = num_bboxes\n        self.num_expected_pos = cfg.num_expected_pos_stage2\n        self.num_expected_neg = cfg.num_expected_neg_stage2\n        self.num_expected_total = cfg.num_expected_total_stage2\n\n        self.add_gt_as_proposals = add_gt_as_proposals\n        self.label_inds = Tensor(np.arange(1, self.num_gts + 1).astype(np.int32))\n        self.add_gt_as_proposals_valid = Tensor(np.array(self.add_gt_as_proposals * np.ones(self.num_gts),\n                                                         dtype=np.int32))\n\n        self.concat = P.Concat(axis=0)\n        self.max_gt = P.ArgMaxWithValue(axis=0)\n        self.max_anchor = P.ArgMaxWithValue(axis=1)\n        self.sum_inds = P.ReduceSum()\n        self.iou = P.IOU()\n        self.greaterequal = P.GreaterEqual()\n        self.greater = P.Greater()\n        self.select = P.Select()\n        self.gatherND = P.GatherNd()\n        self.squeeze = P.Squeeze()\n        self.cast = P.Cast()\n        self.logicaland = P.LogicalAnd()\n        self.less = P.Less()\n        self.random_choice_with_mask_pos = P.RandomChoiceWithMask(self.num_expected_pos)\n        self.random_choice_with_mask_neg = P.RandomChoiceWithMask(self.num_expected_neg)\n        self.reshape = P.Reshape()\n        self.equal = P.Equal()\n        self.bounding_box_encode = P.BoundingBoxEncode(means=(0.0, 0.0, 0.0, 0.0), stds=(0.1, 0.1, 0.2, 0.2))\n        self.concat_axis1 = P.Concat(axis=1)\n        self.logicalnot = P.LogicalNot()\n        self.tile = P.Tile()\n\n        # Check\n        self.check_gt_one = Tensor(np.array(-1 * np.ones((self.num_gts, 4)), dtype=np.float16))\n        self.check_anchor_two = Tensor(np.array(-2 * np.ones((self.num_bboxes, 4)), dtype=np.float16))\n\n        # Init tensor\n        self.assigned_gt_inds = Tensor(np.array(-1 * np.ones(num_bboxes), dtype=np.int32))\n        self.assigned_gt_zeros = Tensor(np.array(np.zeros(num_bboxes), dtype=np.int32))\n        self.assigned_gt_ones = Tensor(np.array(np.ones(num_bboxes), dtype=np.int32))\n        self.assigned_gt_ignores = Tensor(np.array(-1 * np.ones(num_bboxes), dtype=np.int32))\n        self.assigned_pos_ones = Tensor(np.array(np.ones(self.num_expected_pos), dtype=np.int32))\n\n        self.gt_ignores = Tensor(np.array(-1 * np.ones(self.num_gts), dtype=np.int32))\n        self.range_pos_size = Tensor(np.arange(self.num_expected_pos).astype(np.float16))\n        self.check_neg_mask = Tensor(np.array(np.ones(self.num_expected_neg - self.num_expected_pos), dtype=np.bool))\n        self.bboxs_neg_mask = Tensor(np.zeros((self.num_expected_neg, 4), dtype=np.float16))\n        self.labels_neg_mask = Tensor(np.array(np.zeros(self.num_expected_neg), dtype=np.uint8))\n\n        self.reshape_shape_pos = (self.num_expected_pos, 1)\n        self.reshape_shape_neg = (self.num_expected_neg, 1)\n\n        self.scalar_zero = Tensor(0.0, dtype=mstype.float16)\n        self.scalar_neg_iou_thr = Tensor(self.neg_iou_thr, dtype=mstype.float16)\n        self.scalar_pos_iou_thr = Tensor(self.pos_iou_thr, dtype=mstype.float16)\n        self.scalar_min_pos_iou = Tensor(self.min_pos_iou, dtype=mstype.float16)\n\n    def construct(self, gt_bboxes_i, gt_labels_i, valid_mask, bboxes, gt_valids):\n        gt_bboxes_i = self.select(self.cast(self.tile(self.reshape(self.cast(gt_valids, mstype.int32), \\\n                                  (self.num_gts, 1)), (1, 4)), mstype.bool_), \\\n                                  gt_bboxes_i, self.check_gt_one)\n        bboxes = self.select(self.cast(self.tile(self.reshape(self.cast(valid_mask, mstype.int32), \\\n                             (self.num_bboxes, 1)), (1, 4)), mstype.bool_), \\\n                             bboxes, self.check_anchor_two)\n\n        overlaps = self.iou(bboxes, gt_bboxes_i)\n\n        max_overlaps_w_gt_index, max_overlaps_w_gt = self.max_gt(overlaps)\n        _, max_overlaps_w_ac = self.max_anchor(overlaps)\n\n        neg_sample_iou_mask = self.logicaland(self.greaterequal(max_overlaps_w_gt,\n                                                                self.scalar_zero),\n                                              self.less(max_overlaps_w_gt,\n                                                        self.scalar_neg_iou_thr))\n\n        assigned_gt_inds2 = self.select(neg_sample_iou_mask, self.assigned_gt_zeros, self.assigned_gt_inds)\n\n        pos_sample_iou_mask = self.greaterequal(max_overlaps_w_gt, self.scalar_pos_iou_thr)\n        assigned_gt_inds3 = self.select(pos_sample_iou_mask, \\\n                                        max_overlaps_w_gt_index + self.assigned_gt_ones, assigned_gt_inds2)\n\n        for j in range(self.num_gts):\n            max_overlaps_w_ac_j = max_overlaps_w_ac[j:j+1:1]\n            overlaps_w_ac_j = overlaps[j:j+1:1, ::]\n            temp1 = self.greaterequal(max_overlaps_w_ac_j, self.scalar_min_pos_iou)\n            temp2 = self.squeeze(self.equal(overlaps_w_ac_j, max_overlaps_w_ac_j))\n            pos_mask_j = self.logicaland(temp1, temp2)\n            assigned_gt_inds3 = self.select(pos_mask_j, (j+1)*self.assigned_gt_ones, assigned_gt_inds3)\n\n        assigned_gt_inds5 = self.select(valid_mask, assigned_gt_inds3, self.assigned_gt_ignores)\n\n        bboxes = self.concat((gt_bboxes_i, bboxes))\n        label_inds_valid = self.select(gt_valids, self.label_inds, self.gt_ignores)\n        label_inds_valid = label_inds_valid * self.add_gt_as_proposals_valid\n        assigned_gt_inds5 = self.concat((label_inds_valid, assigned_gt_inds5))\n\n        # Get pos index\n        pos_index, valid_pos_index = self.random_choice_with_mask_pos(self.greater(assigned_gt_inds5, 0))\n\n        pos_check_valid = self.cast(self.greater(assigned_gt_inds5, 0), mstype.float16)\n        pos_check_valid = self.sum_inds(pos_check_valid, -1)\n        valid_pos_index = self.less(self.range_pos_size, pos_check_valid)\n        pos_index = pos_index * self.reshape(self.cast(valid_pos_index, mstype.int32), (self.num_expected_pos, 1))\n\n        num_pos = self.sum_inds(self.cast(self.logicalnot(valid_pos_index), mstype.float16), -1)\n        valid_pos_index = self.cast(valid_pos_index, mstype.int32)\n        pos_index = self.reshape(pos_index, self.reshape_shape_pos)\n        valid_pos_index = self.reshape(valid_pos_index, self.reshape_shape_pos)\n        pos_index = pos_index * valid_pos_index\n\n        pos_assigned_gt_index = self.gatherND(assigned_gt_inds5, pos_index) - self.assigned_pos_ones\n        pos_assigned_gt_index = self.reshape(pos_assigned_gt_index, self.reshape_shape_pos)\n        pos_assigned_gt_index = pos_assigned_gt_index * valid_pos_index\n\n        pos_gt_labels = self.gatherND(gt_labels_i, pos_assigned_gt_index)\n\n        # Get neg index\n        neg_index, valid_neg_index = self.random_choice_with_mask_neg(self.equal(assigned_gt_inds5, 0))\n\n        unvalid_pos_index = self.less(self.range_pos_size, num_pos)\n        valid_neg_index = self.logicaland(self.concat((self.check_neg_mask, unvalid_pos_index)), valid_neg_index)\n        neg_index = self.reshape(neg_index, self.reshape_shape_neg)\n\n        valid_neg_index = self.cast(valid_neg_index, mstype.int32)\n        valid_neg_index = self.reshape(valid_neg_index, self.reshape_shape_neg)\n        neg_index = neg_index * valid_neg_index\n\n        pos_bboxes_ = self.gatherND(bboxes, pos_index)\n\n        neg_bboxes_ = self.gatherND(bboxes, neg_index)\n        pos_assigned_gt_index = self.reshape(pos_assigned_gt_index, self.reshape_shape_pos)\n        pos_gt_bboxes_ = self.gatherND(gt_bboxes_i, pos_assigned_gt_index)\n        pos_bbox_targets_ = self.bounding_box_encode(pos_bboxes_, pos_gt_bboxes_)\n\n        total_bboxes = self.concat((pos_bboxes_, neg_bboxes_))\n        total_deltas = self.concat((pos_bbox_targets_, self.bboxs_neg_mask))\n        total_labels = self.concat((pos_gt_labels, self.labels_neg_mask))\n\n        valid_pos_index = self.reshape(valid_pos_index, self.reshape_shape_pos)\n        valid_neg_index = self.reshape(valid_neg_index, self.reshape_shape_neg)\n        total_mask = self.concat((valid_pos_index, valid_neg_index))\n\n        return total_bboxes, total_deltas, total_labels, total_mask\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/src/FasterRcnn/faster_rcnn_r50.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"FasterRcnn based on ResNet50.\"\"\"\n\nimport numpy as np\nimport mindspore.nn as nn\nfrom mindspore.ops import operations as P\nfrom mindspore.common.tensor import Tensor\nimport mindspore.common.dtype as mstype\nfrom mindspore.ops import functional as F\nfrom .resnet50 import ResNetFea, ResidualBlockUsing\nfrom .bbox_assign_sample_stage2 import BboxAssignSampleForRcnn\nfrom .fpn_neck import FeatPyramidNeck\nfrom .proposal_generator import Proposal\nfrom .rcnn import Rcnn\nfrom .rpn import RPN\nfrom .roi_align import SingleRoIExtractor\nfrom .anchor_generator import AnchorGenerator\n\n# pylint: disable=locally-disabled, invalid-name, missing-docstring\n\n\nclass Faster_Rcnn_Resnet50(nn.Cell):\n    \"\"\"\n    FasterRcnn Network.\n\n    Note:\n        backbone = resnet50\n\n    Returns:\n        Tuple, tuple of output tensor.\n        rpn_loss: Scalar, Total loss of RPN subnet.\n        rcnn_loss: Scalar, Total loss of RCNN subnet.\n        rpn_cls_loss: Scalar, Classification loss of RPN subnet.\n        rpn_reg_loss: Scalar, Regression loss of RPN subnet.\n        rcnn_cls_loss: Scalar, Classification loss of RCNN subnet.\n        rcnn_reg_loss: Scalar, Regression loss of RCNN subnet.\n\n    Examples:\n        net = Faster_Rcnn_Resnet50()\n    \"\"\"\n    def __init__(self, config):\n        super(Faster_Rcnn_Resnet50, self).__init__()\n        self.train_batch_size = config.batch_size\n        self.num_classes = config.num_classes\n        self.anchor_scales = config.anchor_scales\n        self.anchor_ratios = config.anchor_ratios\n        self.anchor_strides = config.anchor_strides\n        self.target_means = tuple(config.rcnn_target_means)\n        self.target_stds = tuple(config.rcnn_target_stds)\n\n        # Anchor generator\n        anchor_base_sizes = None\n        self.anchor_base_sizes = list(\n            self.anchor_strides) if anchor_base_sizes is None else anchor_base_sizes\n\n        self.anchor_generators = []\n        for anchor_base in self.anchor_base_sizes:\n            self.anchor_generators.append(\n                AnchorGenerator(anchor_base, self.anchor_scales, self.anchor_ratios))\n\n        self.num_anchors = len(self.anchor_ratios) * len(self.anchor_scales)\n\n        featmap_sizes = config.feature_shapes\n        assert len(featmap_sizes) == len(self.anchor_generators)\n\n        self.anchor_list = self.get_anchors(featmap_sizes)\n\n        # Backbone resnet50\n        self.backbone = ResNetFea(ResidualBlockUsing,\n                                  config.resnet_block,\n                                  config.resnet_in_channels,\n                                  config.resnet_out_channels,\n                                  False)\n\n        # Fpn\n        self.fpn_ncek = FeatPyramidNeck(config.fpn_in_channels,\n                                        config.fpn_out_channels,\n                                        config.fpn_num_outs)\n\n        # Rpn and rpn loss\n        self.gt_labels_stage1 = Tensor(np.ones((self.train_batch_size, config.num_gts)).astype(np.uint8))\n        self.rpn_with_loss = RPN(config,\n                                 self.train_batch_size,\n                                 config.rpn_in_channels,\n                                 config.rpn_feat_channels,\n                                 config.num_anchors,\n                                 config.rpn_cls_out_channels)\n\n        # Proposal\n        self.proposal_generator = Proposal(config,\n                                           self.train_batch_size,\n                                           config.activate_num_classes,\n                                           config.use_sigmoid_cls)\n        self.proposal_generator.set_train_local(config, True)\n        self.proposal_generator_test = Proposal(config,\n                                                config.test_batch_size,\n                                                config.activate_num_classes,\n                                                config.use_sigmoid_cls)\n        self.proposal_generator_test.set_train_local(config, False)\n\n        # Assign and sampler stage two\n        self.bbox_assigner_sampler_for_rcnn = BboxAssignSampleForRcnn(config, self.train_batch_size,\n                                                                      config.num_bboxes_stage2, True)\n        self.decode = P.BoundingBoxDecode(max_shape=(768, 1280), means=self.target_means, \\\n                                          stds=self.target_stds)\n\n        # Roi\n        self.roi_align = SingleRoIExtractor(config,\n                                            config.roi_layer,\n                                            config.roi_align_out_channels,\n                                            config.roi_align_featmap_strides,\n                                            self.train_batch_size,\n                                            config.roi_align_finest_scale)\n        self.roi_align.set_train_local(config, True)\n        self.roi_align_test = SingleRoIExtractor(config,\n                                                 config.roi_layer,\n                                                 config.roi_align_out_channels,\n                                                 config.roi_align_featmap_strides,\n                                                 1,\n                                                 config.roi_align_finest_scale)\n        self.roi_align_test.set_train_local(config, False)\n\n        # Rcnn\n        self.rcnn = Rcnn(config, config.rcnn_in_channels * config.roi_layer['out_size'] * config.roi_layer['out_size'],\n                         self.train_batch_size, self.num_classes)\n\n        # Op declare\n        self.squeeze = P.Squeeze()\n        self.cast = P.Cast()\n\n        self.concat = P.Concat(axis=0)\n        self.concat_1 = P.Concat(axis=1)\n        self.concat_2 = P.Concat(axis=2)\n        self.reshape = P.Reshape()\n        self.select = P.Select()\n        self.greater = P.Greater()\n        self.transpose = P.Transpose()\n\n        # Test mode\n        self.test_batch_size = config.test_batch_size\n        self.split = P.Split(axis=0, output_num=self.test_batch_size)\n        self.split_shape = P.Split(axis=0, output_num=4)\n        self.split_scores = P.Split(axis=1, output_num=self.num_classes)\n        self.split_cls = P.Split(axis=0, output_num=self.num_classes-1)\n        self.tile = P.Tile()\n        self.gather = P.GatherNd()\n\n        self.rpn_max_num = config.rpn_max_num\n\n        self.zeros_for_nms = Tensor(np.zeros((self.rpn_max_num, 3)).astype(np.float16))\n        self.ones_mask = np.ones((self.rpn_max_num, 1)).astype(np.bool)\n        self.zeros_mask = np.zeros((self.rpn_max_num, 1)).astype(np.bool)\n        self.bbox_mask = Tensor(np.concatenate((self.ones_mask, self.zeros_mask,\n                                                self.ones_mask, self.zeros_mask), axis=1))\n        self.nms_pad_mask = Tensor(np.concatenate((self.ones_mask, self.ones_mask,\n                                                   self.ones_mask, self.ones_mask, self.zeros_mask), axis=1))\n\n        self.test_score_thresh = Tensor(np.ones((self.rpn_max_num, 1)).astype(np.float16) * config.test_score_thr)\n        self.test_score_zeros = Tensor(np.ones((self.rpn_max_num, 1)).astype(np.float16) * 0)\n        self.test_box_zeros = Tensor(np.ones((self.rpn_max_num, 4)).astype(np.float16) * -1)\n        self.test_iou_thr = Tensor(np.ones((self.rpn_max_num, 1)).astype(np.float16) * config.test_iou_thr)\n        self.test_max_per_img = config.test_max_per_img\n        self.nms_test = P.NMSWithMask(config.test_iou_thr)\n        self.softmax = P.Softmax(axis=1)\n        self.logicand = P.LogicalAnd()\n        self.oneslike = P.OnesLike()\n        self.test_topk = P.TopK(sorted=True)\n        self.test_num_proposal = self.test_batch_size * self.rpn_max_num\n\n        # Improve speed\n        self.concat_start = min(self.num_classes - 2, 55)\n        self.concat_end = (self.num_classes - 1)\n\n        # Init tensor\n        roi_align_index = [np.array(np.ones((config.num_expected_pos_stage2 + config.num_expected_neg_stage2, 1)) * i,\n                                    dtype=np.float16) for i in range(self.train_batch_size)]\n\n        roi_align_index_test = [np.array(np.ones((config.rpn_max_num, 1)) * i, dtype=np.float16) \\\n                                for i in range(self.test_batch_size)]\n\n        self.roi_align_index_tensor = Tensor(np.concatenate(roi_align_index))\n        self.roi_align_index_test_tensor = Tensor(np.concatenate(roi_align_index_test))\n\n    def construct(self, img_data, img_metas, gt_bboxes, gt_labels, gt_valids):\n        x = self.backbone(img_data)\n        x = self.fpn_ncek(x)\n\n        rpn_loss, cls_score, bbox_pred, rpn_cls_loss, rpn_reg_loss, _ = self.rpn_with_loss(x,\n                                                                                           img_metas,\n                                                                                           self.anchor_list,\n                                                                                           gt_bboxes,\n                                                                                           self.gt_labels_stage1,\n                                                                                           gt_valids)\n\n        if self.training:\n            proposal, proposal_mask = self.proposal_generator(cls_score, bbox_pred, self.anchor_list)\n        else:\n            proposal, proposal_mask = self.proposal_generator_test(cls_score, bbox_pred, self.anchor_list)\n\n        gt_labels = self.cast(gt_labels, mstype.int32)\n        gt_valids = self.cast(gt_valids, mstype.int32)\n        bboxes_tuple = ()\n        deltas_tuple = ()\n        labels_tuple = ()\n        mask_tuple = ()\n        if self.training:\n            for i in range(self.train_batch_size):\n                gt_bboxes_i = self.squeeze(gt_bboxes[i:i + 1:1, ::])\n\n                gt_labels_i = self.squeeze(gt_labels[i:i + 1:1, ::])\n                gt_labels_i = self.cast(gt_labels_i, mstype.uint8)\n\n                gt_valids_i = self.squeeze(gt_valids[i:i + 1:1, ::])\n                gt_valids_i = self.cast(gt_valids_i, mstype.bool_)\n\n                bboxes, deltas, labels, mask = self.bbox_assigner_sampler_for_rcnn(gt_bboxes_i,\n                                                                                   gt_labels_i,\n                                                                                   proposal_mask[i],\n                                                                                   proposal[i][::, 0:4:1],\n                                                                                   gt_valids_i)\n                bboxes_tuple += (bboxes,)\n                deltas_tuple += (deltas,)\n                labels_tuple += (labels,)\n                mask_tuple += (mask,)\n\n            bbox_targets = self.concat(deltas_tuple)\n            rcnn_labels = self.concat(labels_tuple)\n            bbox_targets = F.stop_gradient(bbox_targets)\n            rcnn_labels = F.stop_gradient(rcnn_labels)\n            rcnn_labels = self.cast(rcnn_labels, mstype.int32)\n        else:\n            mask_tuple += proposal_mask\n            bbox_targets = proposal_mask\n            rcnn_labels = proposal_mask\n            for p_i in proposal:\n                bboxes_tuple += (p_i[::, 0:4:1],)\n\n        if self.training:\n            if self.train_batch_size > 1:\n                bboxes_all = self.concat(bboxes_tuple)\n            else:\n                bboxes_all = bboxes_tuple[0]\n            rois = self.concat_1((self.roi_align_index_tensor, bboxes_all))\n        else:\n            if self.test_batch_size > 1:\n                bboxes_all = self.concat(bboxes_tuple)\n            else:\n                bboxes_all = bboxes_tuple[0]\n            rois = self.concat_1((self.roi_align_index_test_tensor, bboxes_all))\n\n\n        rois = self.cast(rois, mstype.float32)\n        rois = F.stop_gradient(rois)\n\n        if self.training:\n            roi_feats = self.roi_align(rois,\n                                       self.cast(x[0], mstype.float32),\n                                       self.cast(x[1], mstype.float32),\n                                       self.cast(x[2], mstype.float32),\n                                       self.cast(x[3], mstype.float32))\n        else:\n            roi_feats = self.roi_align_test(rois,\n                                            self.cast(x[0], mstype.float32),\n                                            self.cast(x[1], mstype.float32),\n                                            self.cast(x[2], mstype.float32),\n                                            self.cast(x[3], mstype.float32))\n\n\n        roi_feats = self.cast(roi_feats, mstype.float16)\n        rcnn_masks = self.concat(mask_tuple)\n        rcnn_masks = F.stop_gradient(rcnn_masks)\n        rcnn_mask_squeeze = self.squeeze(self.cast(rcnn_masks, mstype.bool_))\n        rcnn_loss, rcnn_cls_loss, rcnn_reg_loss, _ = self.rcnn(roi_feats,\n                                                               bbox_targets,\n                                                               rcnn_labels,\n                                                               rcnn_mask_squeeze)\n\n        output = ()\n        if self.training:\n            output += (rpn_loss, rcnn_loss, rpn_cls_loss, rpn_reg_loss, rcnn_cls_loss, rcnn_reg_loss)\n        else:\n            output = self.get_det_bboxes(rcnn_cls_loss, rcnn_reg_loss, rcnn_masks, bboxes_all, img_metas)\n\n        return output\n\n    def get_det_bboxes(self, cls_logits, reg_logits, mask_logits, rois, img_metas):\n        \"\"\"Get the actual detection box.\"\"\"\n        scores = self.softmax(cls_logits)\n\n        boxes_all = ()\n        for i in range(self.num_classes):\n            k = i * 4\n            reg_logits_i = self.squeeze(reg_logits[::, k:k+4:1])\n            out_boxes_i = self.decode(rois, reg_logits_i)\n            boxes_all += (out_boxes_i,)\n\n        img_metas_all = self.split(img_metas)\n        scores_all = self.split(scores)\n        mask_all = self.split(self.cast(mask_logits, mstype.int32))\n\n        boxes_all_with_batchsize = ()\n        for i in range(self.test_batch_size):\n            scale = self.split_shape(self.squeeze(img_metas_all[i]))\n            scale_h = scale[2]\n            scale_w = scale[3]\n            boxes_tuple = ()\n            for j in range(self.num_classes):\n                boxes_tmp = self.split(boxes_all[j])\n                out_boxes_h = boxes_tmp[i] / scale_h\n                out_boxes_w = boxes_tmp[i] / scale_w\n                boxes_tuple += (self.select(self.bbox_mask, out_boxes_w, out_boxes_h),)\n            boxes_all_with_batchsize += (boxes_tuple,)\n\n        output = self.multiclass_nms(boxes_all_with_batchsize, scores_all, mask_all)\n\n        return output\n\n    def multiclass_nms(self, boxes_all, scores_all, mask_all):\n        \"\"\"Multiscale postprocessing.\"\"\"\n        all_bboxes = ()\n        all_labels = ()\n        all_masks = ()\n\n        for i in range(self.test_batch_size):\n            bboxes = boxes_all[i]\n            scores = scores_all[i]\n            masks = self.cast(mask_all[i], mstype.bool_)\n\n            res_boxes_tuple = ()\n            res_labels_tuple = ()\n            res_masks_tuple = ()\n\n            for j in range(self.num_classes - 1):\n                k = j + 1\n                _cls_scores = scores[::, k:k + 1:1]\n                _bboxes = self.squeeze(bboxes[k])\n                _mask_o = self.reshape(masks, (self.rpn_max_num, 1))\n\n                cls_mask = self.greater(_cls_scores, self.test_score_thresh)\n                _mask = self.logicand(_mask_o, cls_mask)\n\n                _reg_mask = self.cast(self.tile(self.cast(_mask, mstype.int32), (1, 4)), mstype.bool_)\n\n                _bboxes = self.select(_reg_mask, _bboxes, self.test_box_zeros)\n                _cls_scores = self.select(_mask, _cls_scores, self.test_score_zeros)\n                __cls_scores = self.squeeze(_cls_scores)\n                scores_sorted, topk_inds = self.test_topk(__cls_scores, self.rpn_max_num)\n                topk_inds = self.reshape(topk_inds, (self.rpn_max_num, 1))\n                scores_sorted = self.reshape(scores_sorted, (self.rpn_max_num, 1))\n                _bboxes_sorted = self.gather(_bboxes, topk_inds)\n                _mask_sorted = self.gather(_mask, topk_inds)\n\n                scores_sorted = self.tile(scores_sorted, (1, 4))\n                cls_dets = self.concat_1((_bboxes_sorted, scores_sorted))\n                cls_dets = P.Slice()(cls_dets, (0, 0), (self.rpn_max_num, 5))\n\n                cls_dets, _index, _mask_nms = self.nms_test(cls_dets)\n                _index = self.reshape(_index, (self.rpn_max_num, 1))\n                _mask_nms = self.reshape(_mask_nms, (self.rpn_max_num, 1))\n\n                _mask_n = self.gather(_mask_sorted, _index)\n\n                _mask_n = self.logicand(_mask_n, _mask_nms)\n                cls_labels = self.oneslike(_index) * j\n                res_boxes_tuple += (cls_dets,)\n                res_labels_tuple += (cls_labels,)\n                res_masks_tuple += (_mask_n,)\n\n            res_boxes_start = self.concat(res_boxes_tuple[:self.concat_start])\n            res_labels_start = self.concat(res_labels_tuple[:self.concat_start])\n            res_masks_start = self.concat(res_masks_tuple[:self.concat_start])\n\n            res_boxes_end = self.concat(res_boxes_tuple[self.concat_start:self.concat_end])\n            res_labels_end = self.concat(res_labels_tuple[self.concat_start:self.concat_end])\n            res_masks_end = self.concat(res_masks_tuple[self.concat_start:self.concat_end])\n\n            res_boxes = self.concat((res_boxes_start, res_boxes_end))\n            res_labels = self.concat((res_labels_start, res_labels_end))\n            res_masks = self.concat((res_masks_start, res_masks_end))\n\n            reshape_size = (self.num_classes - 1) * self.rpn_max_num\n            res_boxes = self.reshape(res_boxes, (1, reshape_size, 5))\n            res_labels = self.reshape(res_labels, (1, reshape_size, 1))\n            res_masks = self.reshape(res_masks, (1, reshape_size, 1))\n\n            all_bboxes += (res_boxes,)\n            all_labels += (res_labels,)\n            all_masks += (res_masks,)\n\n        all_bboxes = self.concat(all_bboxes)\n        all_labels = self.concat(all_labels)\n        all_masks = self.concat(all_masks)\n        return all_bboxes, all_labels, all_masks\n\n    def get_anchors(self, featmap_sizes):\n        \"\"\"Get anchors according to feature map sizes.\n\n        Args:\n            featmap_sizes (list[tuple]): Multi-level feature map sizes.\n            img_metas (list[dict]): Image meta info.\n\n        Returns:\n            tuple: anchors of each image, valid flags of each image\n        \"\"\"\n        num_levels = len(featmap_sizes)\n\n        # since feature map sizes of all images are the same, we only compute\n        # anchors for one time\n        multi_level_anchors = ()\n        for i in range(num_levels):\n            anchors = self.anchor_generators[i].grid_anchors(\n                featmap_sizes[i], self.anchor_strides[i])\n            multi_level_anchors += (Tensor(anchors.astype(np.float16)),)\n\n        return multi_level_anchors\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/src/FasterRcnn/fpn_neck.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"FasterRcnn feature pyramid network.\"\"\"\n\nimport numpy as np\nimport mindspore.nn as nn\nfrom mindspore import context\nfrom mindspore.ops import operations as P\nfrom mindspore.common.tensor import Tensor\nfrom mindspore.common import dtype as mstype\nfrom mindspore.common.initializer import initializer\n\n# pylint: disable=locally-disabled, missing-docstring\n\ncontext.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n\ndef bias_init_zeros(shape):\n    \"\"\"Bias init method.\"\"\"\n    return Tensor(np.array(np.zeros(shape).astype(np.float32)).astype(np.float16))\n\ndef _conv(in_channels, out_channels, kernel_size=3, stride=1, padding=0, pad_mode='pad'):\n    \"\"\"Conv2D wrapper.\"\"\"\n    shape = (out_channels, in_channels, kernel_size, kernel_size)\n    weights = initializer(\"XavierUniform\", shape=shape, dtype=mstype.float16).to_tensor()\n    shape_bias = (out_channels,)\n    biass = bias_init_zeros(shape_bias)\n    return nn.Conv2d(in_channels, out_channels,\n                     kernel_size=kernel_size, stride=stride, padding=padding,\n                     pad_mode=pad_mode, weight_init=weights, has_bias=True, bias_init=biass)\n\nclass FeatPyramidNeck(nn.Cell):\n    \"\"\"\n    Feature pyramid network cell, usually uses as network neck.\n\n    Applies the convolution on multiple, input feature maps\n    and output feature map with same channel size. if required num of\n    output larger then num of inputs, add extra maxpooling for further\n    downsampling;\n\n    Args:\n        in_channels (tuple) - Channel size of input feature maps.\n        out_channels (int) - Channel size output.\n        num_outs (int) - Num of output features.\n\n    Returns:\n        Tuple, with tensors of same channel size.\n\n    Examples:\n        neck = FeatPyramidNeck([100,200,300], 50, 4)\n        input_data = (normal(0,0.1,(1,c,1280//(4*2**i), 768//(4*2**i)),\n                      dtype=np.float32) \\\n                      for i, c in enumerate(config.fpn_in_channels))\n        x = neck(input_data)\n    \"\"\"\n\n    def __init__(self,\n                 in_channels,\n                 out_channels,\n                 num_outs):\n        super(FeatPyramidNeck, self).__init__()\n        self.num_outs = num_outs\n        self.in_channels = in_channels\n        self.fpn_layer = len(self.in_channels)\n\n        assert not self.num_outs < len(in_channels)\n\n        self.lateral_convs_list_ = []\n        self.fpn_convs_ = []\n\n        for _, channel in enumerate(in_channels):\n            l_conv = _conv(channel, out_channels, kernel_size=1, stride=1, padding=0, pad_mode='valid')\n            fpn_conv = _conv(out_channels, out_channels, kernel_size=3, stride=1, padding=0, pad_mode='same')\n            self.lateral_convs_list_.append(l_conv)\n            self.fpn_convs_.append(fpn_conv)\n        self.lateral_convs_list = nn.layer.CellList(self.lateral_convs_list_)\n        self.fpn_convs_list = nn.layer.CellList(self.fpn_convs_)\n        self.interpolate1 = P.ResizeNearestNeighbor((48, 80))\n        self.interpolate2 = P.ResizeNearestNeighbor((96, 160))\n        self.interpolate3 = P.ResizeNearestNeighbor((192, 320))\n        self.maxpool = P.MaxPool(kernel_size=1, strides=2, pad_mode=\"same\")\n\n    def construct(self, inputs):\n        x = ()\n        for i in range(self.fpn_layer):\n            x += (self.lateral_convs_list[i](inputs[i]),)\n\n        y = (x[3],)\n        y = y + (x[2] + self.interpolate1(y[self.fpn_layer - 4]),)\n        y = y + (x[1] + self.interpolate2(y[self.fpn_layer - 3]),)\n        y = y + (x[0] + self.interpolate3(y[self.fpn_layer - 2]),)\n\n        z = ()\n        for i in range(self.fpn_layer - 1, -1, -1):\n            z = z + (y[i],)\n\n        outs = ()\n        for i in range(self.fpn_layer):\n            outs = outs + (self.fpn_convs_list[i](z[i]),)\n\n        for i in range(self.num_outs - self.fpn_layer):\n            outs = outs + (self.maxpool(outs[3]),)\n        return outs\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/src/FasterRcnn/proposal_generator.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"FasterRcnn proposal generator.\"\"\"\n\nimport numpy as np\nimport mindspore.nn as nn\nimport mindspore.common.dtype as mstype\nfrom mindspore.ops import operations as P\nfrom mindspore import Tensor\nfrom mindspore import context\n\n# pylint: disable=locally-disabled, invalid-name, missing-docstring\n\n\ncontext.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n\n\nclass Proposal(nn.Cell):\n    \"\"\"\n    Proposal subnet.\n\n    Args:\n        config (dict): Config.\n        batch_size (int): Batchsize.\n        num_classes (int) - Class number.\n        use_sigmoid_cls (bool) - Select sigmoid or softmax function.\n        target_means (tuple) - Means for encode function. Default: (.0, .0, .0, .0).\n        target_stds (tuple) - Stds for encode function. Default: (1.0, 1.0, 1.0, 1.0).\n\n    Returns:\n        Tuple, tuple of output tensor,(proposal, mask).\n\n    Examples:\n        Proposal(config = config, batch_size = 1, num_classes = 81, use_sigmoid_cls = True, \\\n                 target_means=(.0, .0, .0, .0), target_stds=(1.0, 1.0, 1.0, 1.0))\n    \"\"\"\n    def __init__(self,\n                 config,\n                 batch_size,\n                 num_classes,\n                 use_sigmoid_cls,\n                 target_means=(.0, .0, .0, .0),\n                 target_stds=(1.0, 1.0, 1.0, 1.0)\n                 ):\n        super(Proposal, self).__init__()\n        cfg = config\n        self.batch_size = batch_size\n        self.num_classes = num_classes\n        self.target_means = target_means\n        self.target_stds = target_stds\n        self.use_sigmoid_cls = use_sigmoid_cls\n\n        if self.use_sigmoid_cls:\n            self.cls_out_channels = num_classes - 1\n            self.activation = P.Sigmoid()\n            self.reshape_shape = (-1, 1)\n        else:\n            self.cls_out_channels = num_classes\n            self.activation = P.Softmax(axis=1)\n            self.reshape_shape = (-1, 2)\n\n        if self.cls_out_channels <= 0:\n            raise ValueError('num_classes={} is too small'.format(num_classes))\n\n        self.num_pre = cfg.rpn_proposal_nms_pre\n        self.min_box_size = cfg.rpn_proposal_min_bbox_size\n        self.nms_thr = cfg.rpn_proposal_nms_thr\n        self.nms_post = cfg.rpn_proposal_nms_post\n        self.nms_across_levels = cfg.rpn_proposal_nms_across_levels\n        self.max_num = cfg.rpn_proposal_max_num\n        self.num_levels = cfg.fpn_num_outs\n\n        # Op Define\n        self.squeeze = P.Squeeze()\n        self.reshape = P.Reshape()\n        self.cast = P.Cast()\n\n        self.feature_shapes = cfg.feature_shapes\n\n        self.transpose_shape = (1, 2, 0)\n\n        self.decode = P.BoundingBoxDecode(max_shape=(cfg.img_height, cfg.img_width), \\\n                                          means=self.target_means, \\\n                                          stds=self.target_stds)\n\n        self.nms = P.NMSWithMask(self.nms_thr)\n        self.concat_axis0 = P.Concat(axis=0)\n        self.concat_axis1 = P.Concat(axis=1)\n        self.split = P.Split(axis=1, output_num=5)\n        self.min = P.Minimum()\n        self.gatherND = P.GatherNd()\n        self.slice = P.Slice()\n        self.select = P.Select()\n        self.greater = P.Greater()\n        self.transpose = P.Transpose()\n        self.tile = P.Tile()\n        self.set_train_local(config, training=True)\n\n        self.multi_10 = Tensor(10.0, mstype.float16)\n\n    def set_train_local(self, config, training=True):\n        \"\"\"Set training flag.\"\"\"\n        self.training_local = training\n\n        cfg = config\n        self.topK_stage1 = ()\n        self.topK_shape = ()\n        total_max_topk_input = 0\n        if not self.training_local:\n            self.num_pre = cfg.rpn_nms_pre\n            self.min_box_size = cfg.rpn_min_bbox_min_size\n            self.nms_thr = cfg.rpn_nms_thr\n            self.nms_post = cfg.rpn_nms_post\n            self.nms_across_levels = cfg.rpn_nms_across_levels\n            self.max_num = cfg.rpn_max_num\n\n        for shp in self.feature_shapes:\n            k_num = min(self.num_pre, (shp[0] * shp[1] * 3))\n            total_max_topk_input += k_num\n            self.topK_stage1 += (k_num,)\n            self.topK_shape += ((k_num, 1),)\n\n        self.topKv2 = P.TopK(sorted=True)\n        self.topK_shape_stage2 = (self.max_num, 1)\n        self.min_float_num = -65536.0\n        self.topK_mask = Tensor(self.min_float_num * np.ones(total_max_topk_input, np.float16))\n\n    def construct(self, rpn_cls_score_total, rpn_bbox_pred_total, anchor_list):\n        proposals_tuple = ()\n        masks_tuple = ()\n        for img_id in range(self.batch_size):\n            cls_score_list = ()\n            bbox_pred_list = ()\n            for i in range(self.num_levels):\n                rpn_cls_score_i = self.squeeze(rpn_cls_score_total[i][img_id:img_id+1:1, ::, ::, ::])\n                rpn_bbox_pred_i = self.squeeze(rpn_bbox_pred_total[i][img_id:img_id+1:1, ::, ::, ::])\n\n                cls_score_list = cls_score_list + (rpn_cls_score_i,)\n                bbox_pred_list = bbox_pred_list + (rpn_bbox_pred_i,)\n\n            proposals, masks = self.get_bboxes_single(cls_score_list, bbox_pred_list, anchor_list)\n            proposals_tuple += (proposals,)\n            masks_tuple += (masks,)\n        return proposals_tuple, masks_tuple\n\n    def get_bboxes_single(self, cls_scores, bbox_preds, mlvl_anchors):\n        \"\"\"Get proposal boundingbox.\"\"\"\n        mlvl_proposals = ()\n        mlvl_mask = ()\n        for idx in range(self.num_levels):\n            rpn_cls_score = self.transpose(cls_scores[idx], self.transpose_shape)\n            rpn_bbox_pred = self.transpose(bbox_preds[idx], self.transpose_shape)\n            anchors = mlvl_anchors[idx]\n\n            rpn_cls_score = self.reshape(rpn_cls_score, self.reshape_shape)\n            rpn_cls_score = self.activation(rpn_cls_score)\n            rpn_cls_score_process = self.cast(self.squeeze(rpn_cls_score[::, 0::]), mstype.float16)\n\n            rpn_bbox_pred_process = self.cast(self.reshape(rpn_bbox_pred, (-1, 4)), mstype.float16)\n\n            scores_sorted, topk_inds = self.topKv2(rpn_cls_score_process, self.topK_stage1[idx])\n\n            topk_inds = self.reshape(topk_inds, self.topK_shape[idx])\n\n            bboxes_sorted = self.gatherND(rpn_bbox_pred_process, topk_inds)\n            anchors_sorted = self.cast(self.gatherND(anchors, topk_inds), mstype.float16)\n\n            proposals_decode = self.decode(anchors_sorted, bboxes_sorted)\n\n            proposals_decode = self.concat_axis1((proposals_decode, self.reshape(scores_sorted, self.topK_shape[idx])))\n            proposals, _, mask_valid = self.nms(proposals_decode)\n\n            mlvl_proposals = mlvl_proposals + (proposals,)\n            mlvl_mask = mlvl_mask + (mask_valid,)\n\n        proposals = self.concat_axis0(mlvl_proposals)\n        masks = self.concat_axis0(mlvl_mask)\n\n        _, _, _, _, scores = self.split(proposals)\n        scores = self.squeeze(scores)\n        topk_mask = self.cast(self.topK_mask, mstype.float16)\n        scores_using = self.select(masks, scores, topk_mask)\n\n        _, topk_inds = self.topKv2(scores_using, self.max_num)\n\n        topk_inds = self.reshape(topk_inds, self.topK_shape_stage2)\n        proposals = self.gatherND(proposals, topk_inds)\n        masks = self.gatherND(masks, topk_inds)\n        return proposals, masks\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/src/FasterRcnn/rcnn.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"FasterRcnn Rcnn network.\"\"\"\n\nimport numpy as np\nimport mindspore.common.dtype as mstype\nimport mindspore.nn as nn\nfrom mindspore.ops import operations as P\nfrom mindspore.common.tensor import Tensor\nfrom mindspore.common.initializer import initializer\nfrom mindspore.common.parameter import Parameter\n\n# pylint: disable=locally-disabled, missing-docstring\n\n\nclass DenseNoTranpose(nn.Cell):\n    \"\"\"Dense method\"\"\"\n    def __init__(self, input_channels, output_channels, weight_init):\n        super(DenseNoTranpose, self).__init__()\n\n        self.weight = Parameter(initializer(weight_init, [input_channels, output_channels], mstype.float16),\n                                name=\"weight\")\n        self.bias = Parameter(initializer(\"zeros\", [output_channels], mstype.float16).to_tensor(), name=\"bias\")\n\n        self.matmul = P.MatMul(transpose_b=False)\n        self.bias_add = P.BiasAdd()\n\n    def construct(self, x):\n        output = self.bias_add(self.matmul(x, self.weight), self.bias)\n        return output\n\n\nclass Rcnn(nn.Cell):\n    \"\"\"\n    Rcnn subnet.\n\n    Args:\n        config (dict) - Config.\n        representation_size (int) - Channels of shared dense.\n        batch_size (int) - Batchsize.\n        num_classes (int) - Class number.\n        target_means (list) - Means for encode function. Default: (.0, .0, .0, .0]).\n        target_stds (list) - Stds for encode function. Default: (0.1, 0.1, 0.2, 0.2).\n\n    Returns:\n        Tuple, tuple of output tensor.\n\n    Examples:\n        Rcnn(config=config, representation_size = 1024, batch_size=2, num_classes = 81, \\\n             target_means=(0., 0., 0., 0.), target_stds=(0.1, 0.1, 0.2, 0.2))\n    \"\"\"\n    def __init__(self,\n                 config,\n                 representation_size,\n                 batch_size,\n                 num_classes,\n                 target_means=(0., 0., 0., 0.),\n                 target_stds=(0.1, 0.1, 0.2, 0.2)\n                 ):\n        super(Rcnn, self).__init__()\n        cfg = config\n        self.rcnn_loss_cls_weight = Tensor(np.array(cfg.rcnn_loss_cls_weight).astype(np.float16))\n        self.rcnn_loss_reg_weight = Tensor(np.array(cfg.rcnn_loss_reg_weight).astype(np.float16))\n        self.rcnn_fc_out_channels = cfg.rcnn_fc_out_channels\n        self.target_means = target_means\n        self.target_stds = target_stds\n        self.num_classes = num_classes\n        self.in_channels = cfg.rcnn_in_channels\n        self.train_batch_size = batch_size\n        self.test_batch_size = cfg.test_batch_size\n\n        shape_0 = (self.rcnn_fc_out_channels, representation_size)\n        weights_0 = initializer(\"XavierUniform\", shape=shape_0[::-1], dtype=mstype.float16).to_tensor()\n        shape_1 = (self.rcnn_fc_out_channels, self.rcnn_fc_out_channels)\n        weights_1 = initializer(\"XavierUniform\", shape=shape_1[::-1], dtype=mstype.float16).to_tensor()\n        self.shared_fc_0 = DenseNoTranpose(representation_size, self.rcnn_fc_out_channels, weights_0)\n        self.shared_fc_1 = DenseNoTranpose(self.rcnn_fc_out_channels, self.rcnn_fc_out_channels, weights_1)\n\n        cls_weight = initializer('Normal', shape=[num_classes, self.rcnn_fc_out_channels][::-1],\n                                 dtype=mstype.float16).to_tensor()\n        reg_weight = initializer('Normal', shape=[num_classes * 4, self.rcnn_fc_out_channels][::-1],\n                                 dtype=mstype.float16).to_tensor()\n        self.cls_scores = DenseNoTranpose(self.rcnn_fc_out_channels, num_classes, cls_weight)\n        self.reg_scores = DenseNoTranpose(self.rcnn_fc_out_channels, num_classes * 4, reg_weight)\n\n        self.flatten = P.Flatten()\n        self.relu = P.ReLU()\n        self.logicaland = P.LogicalAnd()\n        self.loss_cls = P.SoftmaxCrossEntropyWithLogits()\n        self.loss_bbox = P.SmoothL1Loss(beta=1.0)\n        self.reshape = P.Reshape()\n        self.onehot = P.OneHot()\n        self.greater = P.Greater()\n        self.cast = P.Cast()\n        self.sum_loss = P.ReduceSum()\n        self.tile = P.Tile()\n        self.expandims = P.ExpandDims()\n\n        self.gather = P.GatherNd()\n        self.argmax = P.ArgMaxWithValue(axis=1)\n\n        self.on_value = Tensor(1.0, mstype.float32)\n        self.off_value = Tensor(0.0, mstype.float32)\n        self.value = Tensor(1.0, mstype.float16)\n\n        self.num_bboxes = (cfg.num_expected_pos_stage2 + cfg.num_expected_neg_stage2) * batch_size\n\n        rmv_first = np.ones((self.num_bboxes, self.num_classes))\n        rmv_first[:, 0] = np.zeros((self.num_bboxes,))\n        self.rmv_first_tensor = Tensor(rmv_first.astype(np.float16))\n\n        self.num_bboxes_test = cfg.rpn_max_num * cfg.test_batch_size\n\n        range_max = np.arange(self.num_bboxes_test).astype(np.int32)\n        self.range_max = Tensor(range_max)\n\n    def construct(self, featuremap, bbox_targets, labels, mask):\n        x = self.flatten(featuremap)\n\n        x = self.relu(self.shared_fc_0(x))\n        x = self.relu(self.shared_fc_1(x))\n\n        x_cls = self.cls_scores(x)\n        x_reg = self.reg_scores(x)\n\n        if self.training:\n            bbox_weights = self.cast(self.logicaland(self.greater(labels, 0), mask), mstype.int32) * labels\n            labels = self.cast(self.onehot(labels, self.num_classes, self.on_value, self.off_value), mstype.float16)\n            bbox_targets = self.tile(self.expandims(bbox_targets, 1), (1, self.num_classes, 1))\n\n            loss, loss_cls, loss_reg, loss_print = self.loss(x_cls, x_reg, bbox_targets, bbox_weights, labels, mask)\n            out = (loss, loss_cls, loss_reg, loss_print)\n        else:\n            out = (x_cls, (x_cls / self.value), x_reg, x_cls)\n\n        return out\n\n    def loss(self, cls_score, bbox_pred, bbox_targets, bbox_weights, labels, weights):\n        \"\"\"Loss method.\"\"\"\n        loss_print = ()\n        loss_cls, _ = self.loss_cls(cls_score, labels)\n\n        weights = self.cast(weights, mstype.float16)\n        loss_cls = loss_cls * weights\n        loss_cls = self.sum_loss(loss_cls, (0,)) / self.sum_loss(weights, (0,))\n\n        bbox_weights = self.cast(self.onehot(bbox_weights, self.num_classes, self.on_value, self.off_value),\n                                 mstype.float16)\n        bbox_weights = bbox_weights * self.rmv_first_tensor\n\n        pos_bbox_pred = self.reshape(bbox_pred, (self.num_bboxes, -1, 4))\n        loss_reg = self.loss_bbox(pos_bbox_pred, bbox_targets)\n        loss_reg = self.sum_loss(loss_reg, (2,))\n        loss_reg = loss_reg * bbox_weights\n        loss_reg = loss_reg / self.sum_loss(weights, (0,))\n        loss_reg = self.sum_loss(loss_reg, (0, 1))\n\n        loss = self.rcnn_loss_cls_weight * loss_cls + self.rcnn_loss_reg_weight * loss_reg\n        loss_print += (loss_cls, loss_reg)\n\n        return loss, loss_cls, loss_reg, loss_print\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/src/FasterRcnn/resnet50.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n# ============================================================================\r\n\"\"\"Resnet50 backbone.\"\"\"\r\n\r\nimport numpy as np\r\nimport mindspore.nn as nn\r\nfrom mindspore.ops import operations as P\r\nfrom mindspore.common.tensor import Tensor\r\nfrom mindspore.ops import functional as F\r\nfrom mindspore import context\r\n\r\n# pylint: disable=locally-disabled, invalid-name, missing-docstring\r\n\r\n\r\ncontext.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\r\n\r\n\r\ndef weight_init_ones(shape):\r\n    \"\"\"Weight init.\"\"\"\r\n    return Tensor(np.array(np.ones(shape).astype(np.float32) * 0.01).astype(np.float16))\r\n\r\n\r\ndef _conv(in_channels, out_channels, kernel_size=3, stride=1, padding=0, pad_mode='pad'):\r\n    \"\"\"Conv2D wrapper.\"\"\"\r\n    shape = (out_channels, in_channels, kernel_size, kernel_size)\r\n    weights = weight_init_ones(shape)\r\n    return nn.Conv2d(in_channels, out_channels,\r\n                     kernel_size=kernel_size, stride=stride, padding=padding,\r\n                     pad_mode=pad_mode, weight_init=weights, has_bias=False)\r\n\r\n\r\ndef _BatchNorm2dInit(out_chls, momentum=0.1, affine=True, use_batch_statistics=True):\r\n    \"\"\"Batchnorm2D wrapper.\"\"\"\r\n    gamma_init = Tensor(np.array(np.ones(out_chls)).astype(np.float16))\r\n    beta_init = Tensor(np.array(np.ones(out_chls) * 0).astype(np.float16))\r\n    moving_mean_init = Tensor(np.array(np.ones(out_chls) * 0).astype(np.float16))\r\n    moving_var_init = Tensor(np.array(np.ones(out_chls)).astype(np.float16))\r\n\r\n    return nn.BatchNorm2d(out_chls, momentum=momentum, affine=affine, gamma_init=gamma_init,\r\n                          beta_init=beta_init, moving_mean_init=moving_mean_init,\r\n                          moving_var_init=moving_var_init, use_batch_statistics=use_batch_statistics)\r\n\r\n\r\nclass ResNetFea(nn.Cell):\r\n    \"\"\"\r\n    ResNet architecture.\r\n\r\n    Args:\r\n        block (Cell): Block for network.\r\n        layer_nums (list): Numbers of block in different layers.\r\n        in_channels (list): Input channel in each layer.\r\n        out_channels (list): Output channel in each layer.\r\n        weights_update (bool): Weight update flag.\r\n    Returns:\r\n        Tensor, output tensor.\r\n\r\n    Examples:\r\n        >>> ResNet(ResidualBlock,\r\n        >>>        [3, 4, 6, 3],\r\n        >>>        [64, 256, 512, 1024],\r\n        >>>        [256, 512, 1024, 2048],\r\n        >>>        False)\r\n    \"\"\"\r\n    def __init__(self,\r\n                 block,\r\n                 layer_nums,\r\n                 in_channels,\r\n                 out_channels,\r\n                 weights_update=False):\r\n        super(ResNetFea, self).__init__()\r\n\r\n        if not len(layer_nums) == len(in_channels) == len(out_channels) == 4:\r\n            raise ValueError(\"the length of \"\r\n                             \"layer_num, inchannel, outchannel list must be 4!\")\r\n\r\n        bn_training = False\r\n        self.conv1 = _conv(3, 64, kernel_size=7, stride=2, padding=3, pad_mode='pad')\r\n        self.bn1 = _BatchNorm2dInit(64, affine=bn_training, use_batch_statistics=bn_training)\r\n        self.relu = P.ReLU()\r\n        self.maxpool = P.MaxPool(kernel_size=3, strides=2, pad_mode=\"SAME\")\r\n        self.weights_update = weights_update\r\n\r\n        if not self.weights_update:\r\n            self.conv1.weight.requires_grad = False\r\n\r\n        self.layer1 = self._make_layer(block,\r\n                                       layer_nums[0],\r\n                                       in_channel=in_channels[0],\r\n                                       out_channel=out_channels[0],\r\n                                       stride=1,\r\n                                       training=bn_training,\r\n                                       weights_update=self.weights_update)\r\n        self.layer2 = self._make_layer(block,\r\n                                       layer_nums[1],\r\n                                       in_channel=in_channels[1],\r\n                                       out_channel=out_channels[1],\r\n                                       stride=2,\r\n                                       training=bn_training,\r\n                                       weights_update=True)\r\n        self.layer3 = self._make_layer(block,\r\n                                       layer_nums[2],\r\n                                       in_channel=in_channels[2],\r\n                                       out_channel=out_channels[2],\r\n                                       stride=2,\r\n                                       training=bn_training,\r\n                                       weights_update=True)\r\n        self.layer4 = self._make_layer(block,\r\n                                       layer_nums[3],\r\n                                       in_channel=in_channels[3],\r\n                                       out_channel=out_channels[3],\r\n                                       stride=2,\r\n                                       training=bn_training,\r\n                                       weights_update=True)\r\n\r\n    def _make_layer(self, block, layer_num, in_channel, out_channel, stride, training=False, weights_update=False):\r\n        \"\"\"Make block layer.\"\"\"\r\n        layers = []\r\n        down_sample = False\r\n        if stride != 1 or in_channel != out_channel:\r\n            down_sample = True\r\n        resblk = block(in_channel,\r\n                       out_channel,\r\n                       stride=stride,\r\n                       down_sample=down_sample,\r\n                       training=training,\r\n                       weights_update=weights_update)\r\n        layers.append(resblk)\r\n\r\n        for _ in range(1, layer_num):\r\n            resblk = block(out_channel, out_channel, stride=1, training=training, weights_update=weights_update)\r\n            layers.append(resblk)\r\n\r\n        return nn.SequentialCell(layers)\r\n\r\n    def construct(self, x):\r\n        x = self.conv1(x)\r\n        x = self.bn1(x)\r\n        x = self.relu(x)\r\n        c1 = self.maxpool(x)\r\n\r\n        c2 = self.layer1(c1)\r\n        identity = c2\r\n        if not self.weights_update:\r\n            identity = F.stop_gradient(c2)\r\n        c3 = self.layer2(identity)\r\n        c4 = self.layer3(c3)\r\n        c5 = self.layer4(c4)\r\n\r\n        return identity, c3, c4, c5\r\n\r\n\r\nclass ResidualBlockUsing(nn.Cell):\r\n    \"\"\"\r\n    ResNet V1 residual block definition.\r\n\r\n    Args:\r\n        in_channels (int) - Input channel.\r\n        out_channels (int) - Output channel.\r\n        stride (int) - Stride size for the initial convolutional layer. Default: 1.\r\n        down_sample (bool) - If to do the downsample in block. Default: False.\r\n        momentum (float) - Momentum for batchnorm layer. Default: 0.1.\r\n        training (bool) - Training flag. Default: False.\r\n        weights_updata (bool) - Weights update flag. Default: False.\r\n\r\n    Returns:\r\n        Tensor, output tensor.\r\n\r\n    Examples:\r\n        ResidualBlock(3,256,stride=2,down_sample=True)\r\n    \"\"\"\r\n    expansion = 4\r\n\r\n    def __init__(self,\r\n                 in_channels,\r\n                 out_channels,\r\n                 stride=1,\r\n                 down_sample=False,\r\n                 momentum=0.1,\r\n                 training=False,\r\n                 weights_update=False):\r\n        super(ResidualBlockUsing, self).__init__()\r\n\r\n        self.affine = weights_update\r\n\r\n        out_chls = out_channels // self.expansion\r\n        self.conv1 = _conv(in_channels, out_chls, kernel_size=1, stride=1, padding=0)\r\n        self.bn1 = _BatchNorm2dInit(out_chls, momentum=momentum, affine=self.affine, use_batch_statistics=training)\r\n\r\n        self.conv2 = _conv(out_chls, out_chls, kernel_size=3, stride=stride, padding=1)\r\n        self.bn2 = _BatchNorm2dInit(out_chls, momentum=momentum, affine=self.affine, use_batch_statistics=training)\r\n\r\n        self.conv3 = _conv(out_chls, out_channels, kernel_size=1, stride=1, padding=0)\r\n        self.bn3 = _BatchNorm2dInit(out_channels, momentum=momentum, affine=self.affine, use_batch_statistics=training)\r\n\r\n        if training:\r\n            self.bn1 = self.bn1.set_train()\r\n            self.bn2 = self.bn2.set_train()\r\n            self.bn3 = self.bn3.set_train()\r\n\r\n        if not weights_update:\r\n            self.conv1.weight.requires_grad = False\r\n            self.conv2.weight.requires_grad = False\r\n            self.conv3.weight.requires_grad = False\r\n\r\n        self.relu = P.ReLU()\r\n        self.downsample = down_sample\r\n        if self.downsample:\r\n            self.conv_down_sample = _conv(in_channels, out_channels, kernel_size=1, stride=stride, padding=0)\r\n            self.bn_down_sample = _BatchNorm2dInit(out_channels, momentum=momentum, affine=self.affine,\r\n                                                   use_batch_statistics=training)\r\n            if training:\r\n                self.bn_down_sample = self.bn_down_sample.set_train()\r\n            if not weights_update:\r\n                self.conv_down_sample.weight.requires_grad = False\r\n        self.add = P.Add()\r\n\r\n    def construct(self, x):\r\n        identity = x\r\n\r\n        out = self.conv1(x)\r\n        out = self.bn1(out)\r\n        out = self.relu(out)\r\n\r\n        out = self.conv2(out)\r\n        out = self.bn2(out)\r\n        out = self.relu(out)\r\n\r\n        out = self.conv3(out)\r\n        out = self.bn3(out)\r\n\r\n        if self.downsample:\r\n            identity = self.conv_down_sample(identity)\r\n            identity = self.bn_down_sample(identity)\r\n\r\n        out = self.add(out, identity)\r\n        out = self.relu(out)\r\n\r\n        return out\r\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/src/FasterRcnn/roi_align.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"FasterRcnn ROIAlign module.\"\"\"\n\nimport numpy as np\nimport mindspore.nn as nn\nimport mindspore.common.dtype as mstype\nfrom mindspore.ops import operations as P\nfrom mindspore.ops import composite as C\nfrom mindspore.nn import layer as L\nfrom mindspore.common.tensor import Tensor\n\n# pylint: disable=locally-disabled, invalid-name, missing-docstring\n\n\nclass ROIAlign(nn.Cell):\n    \"\"\"\n    Extract RoI features from mulitple feature map.\n\n    Args:\n        out_size_h (int) - RoI height.\n        out_size_w (int) - RoI width.\n        spatial_scale (int) - RoI spatial scale.\n        sample_num (int) - RoI sample number.\n    \"\"\"\n    def __init__(self,\n                 out_size_h,\n                 out_size_w,\n                 spatial_scale,\n                 sample_num=0):\n        super(ROIAlign, self).__init__()\n\n        self.out_size = (out_size_h, out_size_w)\n        self.spatial_scale = float(spatial_scale)\n        self.sample_num = int(sample_num)\n        self.align_op = P.ROIAlign(self.out_size[0], self.out_size[1],\n                                   self.spatial_scale, self.sample_num)\n\n    def construct(self, features, rois):\n        return self.align_op(features, rois)\n\n    def __repr__(self):\n        format_str = self.__class__.__name__\n        format_str += '(out_size={}, spatial_scale={}, sample_num={}'.format(\n            self.out_size, self.spatial_scale, self.sample_num)\n        return format_str\n\n\nclass SingleRoIExtractor(nn.Cell):\n    \"\"\"\n    Extract RoI features from a single level feature map.\n\n    If there are mulitple input feature levels, each RoI is mapped to a level\n    according to its scale.\n\n    Args:\n        config (dict): Config\n        roi_layer (dict): Specify RoI layer type and arguments.\n        out_channels (int): Output channels of RoI layers.\n        featmap_strides (int): Strides of input feature maps.\n        batch_size (int)： Batchsize.\n        finest_scale (int): Scale threshold of mapping to level 0.\n    \"\"\"\n\n    def __init__(self,\n                 config,\n                 roi_layer,\n                 out_channels,\n                 featmap_strides,\n                 batch_size=1,\n                 finest_scale=56):\n        super(SingleRoIExtractor, self).__init__()\n        cfg = config\n        self.train_batch_size = batch_size\n        self.out_channels = out_channels\n        self.featmap_strides = featmap_strides\n        self.num_levels = len(self.featmap_strides)\n        self.out_size = roi_layer['out_size']\n        self.sample_num = roi_layer['sample_num']\n        self.roi_layers = self.build_roi_layers(self.featmap_strides)\n        self.roi_layers = L.CellList(self.roi_layers)\n\n        self.sqrt = P.Sqrt()\n        self.log = P.Log()\n        self.finest_scale_ = finest_scale\n        self.clamp = C.clip_by_value\n\n        self.cast = P.Cast()\n        self.equal = P.Equal()\n        self.select = P.Select()\n\n        _mode_16 = False\n        self.dtype = np.float16 if _mode_16 else np.float32\n        self.ms_dtype = mstype.float16 if _mode_16 else mstype.float32\n        self.set_train_local(cfg, training=True)\n\n    def set_train_local(self, config, training=True):\n        \"\"\"Set training flag.\"\"\"\n        self.training_local = training\n\n        cfg = config\n        # Init tensor\n        self.batch_size = cfg.roi_sample_num if self.training_local else cfg.rpn_max_num\n        self.batch_size = self.train_batch_size*self.batch_size \\\n            if self.training_local else cfg.test_batch_size*self.batch_size\n        self.ones = Tensor(np.array(np.ones((self.batch_size, 1)), dtype=self.dtype))\n        finest_scale = np.array(np.ones((self.batch_size, 1)), dtype=self.dtype) * self.finest_scale_\n        self.finest_scale = Tensor(finest_scale)\n        self.epslion = Tensor(np.array(np.ones((self.batch_size, 1)), dtype=self.dtype)*self.dtype(1e-6))\n        self.zeros = Tensor(np.array(np.zeros((self.batch_size, 1)), dtype=np.int32))\n        self.max_levels = Tensor(np.array(np.ones((self.batch_size, 1)), dtype=np.int32)*(self.num_levels-1))\n        self.twos = Tensor(np.array(np.ones((self.batch_size, 1)), dtype=self.dtype) * 2)\n        self.res_ = Tensor(np.array(np.zeros((self.batch_size, self.out_channels,\n                                              self.out_size, self.out_size)), dtype=self.dtype))\n    def num_inputs(self):\n        return len(self.featmap_strides)\n\n    def init_weights(self):\n        pass\n\n    def log2(self, value):\n        return self.log(value) / self.log(self.twos)\n\n    def build_roi_layers(self, featmap_strides):\n        roi_layers = []\n        for s in featmap_strides:\n            layer_cls = ROIAlign(self.out_size, self.out_size,\n                                 spatial_scale=1 / s,\n                                 sample_num=self.sample_num)\n            roi_layers.append(layer_cls)\n        return roi_layers\n\n    def _c_map_roi_levels(self, rois):\n        \"\"\"Map rois to corresponding feature levels by scales.\n\n        - scale < finest_scale * 2: level 0\n        - finest_scale * 2 <= scale < finest_scale * 4: level 1\n        - finest_scale * 4 <= scale < finest_scale * 8: level 2\n        - scale >= finest_scale * 8: level 3\n\n        Args:\n            rois (Tensor): Input RoIs, shape (k, 5).\n            num_levels (int): Total level number.\n\n        Returns:\n            Tensor: Level index (0-based) of each RoI, shape (k, )\n        \"\"\"\n        scale = self.sqrt(rois[::, 3:4:1] - rois[::, 1:2:1] + self.ones) * \\\n             self.sqrt(rois[::, 4:5:1] - rois[::, 2:3:1] + self.ones)\n\n        target_lvls = self.log2(scale / self.finest_scale + self.epslion)\n        target_lvls = P.Floor()(target_lvls)\n        target_lvls = self.cast(target_lvls, mstype.int32)\n        target_lvls = self.clamp(target_lvls, self.zeros, self.max_levels)\n\n        return target_lvls\n\n    def construct(self, rois, feat1, feat2, feat3, feat4):\n        feats = (feat1, feat2, feat3, feat4)\n        res = self.res_\n        target_lvls = self._c_map_roi_levels(rois)\n        for i in range(self.num_levels):\n            mask = self.equal(target_lvls, P.ScalarToArray()(i))\n            mask = P.Reshape()(mask, (-1, 1, 1, 1))\n            roi_feats_t = self.roi_layers[i](feats[i], rois)\n            mask = self.cast(P.Tile()(self.cast(mask, mstype.int32), (1, 256, 7, 7)), mstype.bool_)\n            res = self.select(mask, roi_feats_t, res)\n\n        return res\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/src/FasterRcnn/rpn.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"RPN for fasterRCNN\"\"\"\nimport numpy as np\nimport mindspore.nn as nn\nimport mindspore.common.dtype as mstype\nfrom mindspore.ops import operations as P\nfrom mindspore import Tensor\nfrom mindspore.ops import functional as F\nfrom mindspore.common.initializer import initializer\nfrom .bbox_assign_sample import BboxAssignSample\n\n# pylint: disable=locally-disabled, invalid-name, missing-docstring\n\n# pylint: disable=locally-disabled, invalid-name, missing-docstring\n\n\nclass RpnRegClsBlock(nn.Cell):\n    \"\"\"\n    Rpn reg cls block for rpn layer\n\n    Args:\n        in_channels (int) - Input channels of shared convolution.\n        feat_channels (int) - Output channels of shared convolution.\n        num_anchors (int) - The anchor number.\n        cls_out_channels (int) - Output channels of classification convolution.\n        weight_conv (Tensor) - weight init for rpn conv.\n        bias_conv (Tensor) - bias init for rpn conv.\n        weight_cls (Tensor) - weight init for rpn cls conv.\n        bias_cls (Tensor) - bias init for rpn cls conv.\n        weight_reg (Tensor) - weight init for rpn reg conv.\n        bias_reg (Tensor) - bias init for rpn reg conv.\n\n    Returns:\n        Tensor, output tensor.\n    \"\"\"\n    def __init__(self,\n                 in_channels,\n                 feat_channels,\n                 num_anchors,\n                 cls_out_channels,\n                 weight_conv,\n                 bias_conv,\n                 weight_cls,\n                 bias_cls,\n                 weight_reg,\n                 bias_reg):\n        super(RpnRegClsBlock, self).__init__()\n        self.rpn_conv = nn.Conv2d(in_channels, feat_channels, kernel_size=3, stride=1, pad_mode='same',\n                                  has_bias=True, weight_init=weight_conv, bias_init=bias_conv)\n        self.relu = nn.ReLU()\n\n        self.rpn_cls = nn.Conv2d(feat_channels, num_anchors * cls_out_channels, kernel_size=1, pad_mode='valid',\n                                 has_bias=True, weight_init=weight_cls, bias_init=bias_cls)\n        self.rpn_reg = nn.Conv2d(feat_channels, num_anchors * 4, kernel_size=1, pad_mode='valid',\n                                 has_bias=True, weight_init=weight_reg, bias_init=bias_reg)\n\n    def construct(self, x):\n        x = self.relu(self.rpn_conv(x))\n\n        x1 = self.rpn_cls(x)\n        x2 = self.rpn_reg(x)\n\n        return x1, x2\n\n\nclass RPN(nn.Cell):\n    \"\"\"\n    ROI proposal network..\n\n    Args:\n        config (dict) - Config.\n        batch_size (int) - Batchsize.\n        in_channels (int) - Input channels of shared convolution.\n        feat_channels (int) - Output channels of shared convolution.\n        num_anchors (int) - The anchor number.\n        cls_out_channels (int) - Output channels of classification convolution.\n\n    Returns:\n        Tuple, tuple of output tensor.\n\n    Examples:\n        RPN(config=config, batch_size=2, in_channels=256, feat_channels=1024,\n            num_anchors=3, cls_out_channels=512)\n    \"\"\"\n    def __init__(self,\n                 config,\n                 batch_size,\n                 in_channels,\n                 feat_channels,\n                 num_anchors,\n                 cls_out_channels):\n        super(RPN, self).__init__()\n        cfg_rpn = config\n        self.num_bboxes = cfg_rpn.num_bboxes\n        self.slice_index = ()\n        self.feature_anchor_shape = ()\n        self.slice_index += (0,)\n        index = 0\n        for shape in cfg_rpn.feature_shapes:\n            self.slice_index += (self.slice_index[index] + shape[0] * shape[1] * num_anchors,)\n            self.feature_anchor_shape += (shape[0] * shape[1] * num_anchors * batch_size,)\n            index += 1\n\n        self.num_anchors = num_anchors\n        self.batch_size = batch_size\n        self.test_batch_size = cfg_rpn.test_batch_size\n        self.num_layers = 5\n        self.real_ratio = Tensor(np.ones((1, 1)).astype(np.float16))\n\n        self.rpn_convs_list = nn.layer.CellList(self._make_rpn_layer(self.num_layers, in_channels, feat_channels,\n                                                                     num_anchors, cls_out_channels))\n\n        self.transpose = P.Transpose()\n        self.reshape = P.Reshape()\n        self.concat = P.Concat(axis=0)\n        self.fill = P.Fill()\n        self.placeh1 = Tensor(np.ones((1,)).astype(np.float16))\n\n        self.trans_shape = (0, 2, 3, 1)\n\n        self.reshape_shape_reg = (-1, 4)\n        self.reshape_shape_cls = (-1,)\n        self.rpn_loss_reg_weight = Tensor(np.array(cfg_rpn.rpn_loss_reg_weight).astype(np.float16))\n        self.rpn_loss_cls_weight = Tensor(np.array(cfg_rpn.rpn_loss_cls_weight).astype(np.float16))\n        self.num_expected_total = Tensor(np.array(cfg_rpn.num_expected_neg * self.batch_size).astype(np.float16))\n        self.num_bboxes = cfg_rpn.num_bboxes\n        self.get_targets = BboxAssignSample(cfg_rpn, self.batch_size, self.num_bboxes, False)\n        self.CheckValid = P.CheckValid()\n        self.sum_loss = P.ReduceSum()\n        self.loss_cls = P.SigmoidCrossEntropyWithLogits()\n        self.loss_bbox = P.SmoothL1Loss(beta=1.0/9.0)\n        self.squeeze = P.Squeeze()\n        self.cast = P.Cast()\n        self.tile = P.Tile()\n        self.zeros_like = P.ZerosLike()\n        self.loss = Tensor(np.zeros((1,)).astype(np.float16))\n        self.clsloss = Tensor(np.zeros((1,)).astype(np.float16))\n        self.regloss = Tensor(np.zeros((1,)).astype(np.float16))\n\n    def _make_rpn_layer(self, num_layers, in_channels, feat_channels, num_anchors, cls_out_channels):\n        \"\"\"\n        make rpn layer for rpn proposal network\n\n        Args:\n        num_layers (int) - layer num.\n        in_channels (int) - Input channels of shared convolution.\n        feat_channels (int) - Output channels of shared convolution.\n        num_anchors (int) - The anchor number.\n        cls_out_channels (int) - Output channels of classification convolution.\n\n        Returns:\n        List, list of RpnRegClsBlock cells.\n        \"\"\"\n        rpn_layer = []\n\n        shp_weight_conv = (feat_channels, in_channels, 3, 3)\n        shp_bias_conv = (feat_channels,)\n        weight_conv = initializer('Normal', shape=shp_weight_conv, dtype=mstype.float16).to_tensor()\n        bias_conv = initializer(0, shape=shp_bias_conv, dtype=mstype.float16).to_tensor()\n\n        shp_weight_cls = (num_anchors * cls_out_channels, feat_channels, 1, 1)\n        shp_bias_cls = (num_anchors * cls_out_channels,)\n        weight_cls = initializer('Normal', shape=shp_weight_cls, dtype=mstype.float16).to_tensor()\n        bias_cls = initializer(0, shape=shp_bias_cls, dtype=mstype.float16).to_tensor()\n\n        shp_weight_reg = (num_anchors * 4, feat_channels, 1, 1)\n        shp_bias_reg = (num_anchors * 4,)\n        weight_reg = initializer('Normal', shape=shp_weight_reg, dtype=mstype.float16).to_tensor()\n        bias_reg = initializer(0, shape=shp_bias_reg, dtype=mstype.float16).to_tensor()\n\n        for i in range(num_layers):\n            rpn_layer.append(RpnRegClsBlock(in_channels, feat_channels, num_anchors, cls_out_channels, \\\n                                            weight_conv, bias_conv, weight_cls, \\\n                                            bias_cls, weight_reg, bias_reg))\n\n        for i in range(1, num_layers):\n            rpn_layer[i].rpn_conv.weight = rpn_layer[0].rpn_conv.weight\n            rpn_layer[i].rpn_cls.weight = rpn_layer[0].rpn_cls.weight\n            rpn_layer[i].rpn_reg.weight = rpn_layer[0].rpn_reg.weight\n\n            rpn_layer[i].rpn_conv.bias = rpn_layer[0].rpn_conv.bias\n            rpn_layer[i].rpn_cls.bias = rpn_layer[0].rpn_cls.bias\n            rpn_layer[i].rpn_reg.bias = rpn_layer[0].rpn_reg.bias\n\n        return rpn_layer\n\n    def construct(self, inputs, img_metas, anchor_list, gt_bboxes, gt_labels, gt_valids):\n        loss_print = ()\n        rpn_cls_score = ()\n        rpn_bbox_pred = ()\n        rpn_cls_score_total = ()\n        rpn_bbox_pred_total = ()\n\n        for i in range(self.num_layers):\n            x1, x2 = self.rpn_convs_list[i](inputs[i])\n\n            rpn_cls_score_total = rpn_cls_score_total + (x1,)\n            rpn_bbox_pred_total = rpn_bbox_pred_total + (x2,)\n\n            x1 = self.transpose(x1, self.trans_shape)\n            x1 = self.reshape(x1, self.reshape_shape_cls)\n\n            x2 = self.transpose(x2, self.trans_shape)\n            x2 = self.reshape(x2, self.reshape_shape_reg)\n\n            rpn_cls_score = rpn_cls_score + (x1,)\n            rpn_bbox_pred = rpn_bbox_pred + (x2,)\n\n        loss = self.loss\n        clsloss = self.clsloss\n        regloss = self.regloss\n        bbox_targets = ()\n        bbox_weights = ()\n        labels = ()\n        label_weights = ()\n\n        output = ()\n        if self.training:\n            for i in range(self.batch_size):\n                multi_level_flags = ()\n                anchor_list_tuple = ()\n\n                for j in range(self.num_layers):\n                    res = self.cast(self.CheckValid(anchor_list[j], self.squeeze(img_metas[i:i + 1:1, ::])),\n                                    mstype.int32)\n                    multi_level_flags = multi_level_flags + (res,)\n                    anchor_list_tuple = anchor_list_tuple + (anchor_list[j],)\n\n                valid_flag_list = self.concat(multi_level_flags)\n                anchor_using_list = self.concat(anchor_list_tuple)\n\n                gt_bboxes_i = self.squeeze(gt_bboxes[i:i + 1:1, ::])\n                gt_labels_i = self.squeeze(gt_labels[i:i + 1:1, ::])\n                gt_valids_i = self.squeeze(gt_valids[i:i + 1:1, ::])\n\n                bbox_target, bbox_weight, label, label_weight = self.get_targets(gt_bboxes_i,\n                                                                                 gt_labels_i,\n                                                                                 self.cast(valid_flag_list,\n                                                                                           mstype.bool_),\n                                                                                 anchor_using_list, gt_valids_i)\n\n                bbox_weight = self.cast(bbox_weight, mstype.float16)\n                label = self.cast(label, mstype.float16)\n                label_weight = self.cast(label_weight, mstype.float16)\n\n                for j in range(self.num_layers):\n                    begin = self.slice_index[j]\n                    end = self.slice_index[j + 1]\n                    stride = 1\n                    bbox_targets += (bbox_target[begin:end:stride, ::],)\n                    bbox_weights += (bbox_weight[begin:end:stride],)\n                    labels += (label[begin:end:stride],)\n                    label_weights += (label_weight[begin:end:stride],)\n\n            for i in range(self.num_layers):\n                bbox_target_using = ()\n                bbox_weight_using = ()\n                label_using = ()\n                label_weight_using = ()\n\n                for j in range(self.batch_size):\n                    bbox_target_using += (bbox_targets[i + (self.num_layers * j)],)\n                    bbox_weight_using += (bbox_weights[i + (self.num_layers * j)],)\n                    label_using += (labels[i + (self.num_layers * j)],)\n                    label_weight_using += (label_weights[i + (self.num_layers * j)],)\n\n                bbox_target_with_batchsize = self.concat(bbox_target_using)\n                bbox_weight_with_batchsize = self.concat(bbox_weight_using)\n                label_with_batchsize = self.concat(label_using)\n                label_weight_with_batchsize = self.concat(label_weight_using)\n\n                # stop\n                bbox_target_ = F.stop_gradient(bbox_target_with_batchsize)\n                bbox_weight_ = F.stop_gradient(bbox_weight_with_batchsize)\n                label_ = F.stop_gradient(label_with_batchsize)\n                label_weight_ = F.stop_gradient(label_weight_with_batchsize)\n\n                cls_score_i = rpn_cls_score[i]\n                reg_score_i = rpn_bbox_pred[i]\n\n                loss_cls = self.loss_cls(cls_score_i, label_)\n                loss_cls_item = loss_cls * label_weight_\n                loss_cls_item = self.sum_loss(loss_cls_item, (0,)) / self.num_expected_total\n\n                loss_reg = self.loss_bbox(reg_score_i, bbox_target_)\n                bbox_weight_ = self.tile(self.reshape(bbox_weight_, (self.feature_anchor_shape[i], 1)), (1, 4))\n                loss_reg = loss_reg * bbox_weight_\n                loss_reg_item = self.sum_loss(loss_reg, (1,))\n                loss_reg_item = self.sum_loss(loss_reg_item, (0,)) / self.num_expected_total\n\n                loss_total = self.rpn_loss_cls_weight * loss_cls_item + self.rpn_loss_reg_weight * loss_reg_item\n\n                loss += loss_total\n                loss_print += (loss_total, loss_cls_item, loss_reg_item)\n                clsloss += loss_cls_item\n                regloss += loss_reg_item\n\n                output = (loss, rpn_cls_score_total, rpn_bbox_pred_total, clsloss, regloss, loss_print)\n        else:\n            output = (self.placeh1, rpn_cls_score_total, rpn_bbox_pred_total, self.placeh1, self.placeh1, self.placeh1)\n\n        return output\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/src/config.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ===========================================================================\n\"\"\"\nnetwork config setting, will be used in train.py and eval.py\n\"\"\"\nfrom easydict import EasyDict as ed\n\nconfig = ed({\n    \"img_width\": 1280,\n    \"img_height\": 768,\n    \"keep_ratio\": False,\n    \"flip_ratio\": 0.5,\n    \"photo_ratio\": 0.5,\n    \"expand_ratio\": 1.0,\n\n    # anchor\n    \"feature_shapes\": [(192, 320), (96, 160), (48, 80), (24, 40), (12, 20)],\n    \"anchor_scales\": [8],\n    \"anchor_ratios\": [0.5, 1.0, 2.0],\n    \"anchor_strides\": [4, 8, 16, 32, 64],\n    \"num_anchors\": 3,\n\n    # resnet\n    \"resnet_block\": [3, 4, 6, 3],\n    \"resnet_in_channels\": [64, 256, 512, 1024],\n    \"resnet_out_channels\": [256, 512, 1024, 2048],\n\n    # fpn\n    \"fpn_in_channels\": [256, 512, 1024, 2048],\n    \"fpn_out_channels\": 256,\n    \"fpn_num_outs\": 5,\n\n    # rpn\n    \"rpn_in_channels\": 256,\n    \"rpn_feat_channels\": 256,\n    \"rpn_loss_cls_weight\": 1.0,\n    \"rpn_loss_reg_weight\": 1.0,\n    \"rpn_cls_out_channels\": 1,\n    \"rpn_target_means\": [0., 0., 0., 0.],\n    \"rpn_target_stds\": [1.0, 1.0, 1.0, 1.0],\n\n    # bbox_assign_sampler\n    \"neg_iou_thr\": 0.3,\n    \"pos_iou_thr\": 0.7,\n    \"min_pos_iou\": 0.3,\n    \"num_bboxes\": 245520,\n    \"num_gts\": 128,\n    \"num_expected_neg\": 256,\n    \"num_expected_pos\": 128,\n\n    # proposal\n    \"activate_num_classes\": 2,\n    \"use_sigmoid_cls\": True,\n\n    # roi_align\n    \"roi_layer\": dict(type='RoIAlign', out_size=7, sample_num=2),\n    \"roi_align_out_channels\": 256,\n    \"roi_align_featmap_strides\": [4, 8, 16, 32],\n    \"roi_align_finest_scale\": 56,\n    \"roi_sample_num\": 640,\n\n    # bbox_assign_sampler_stage2\n    \"neg_iou_thr_stage2\": 0.5,\n    \"pos_iou_thr_stage2\": 0.5,\n    \"min_pos_iou_stage2\": 0.5,\n    \"num_bboxes_stage2\": 2000,\n    \"num_expected_pos_stage2\": 128,\n    \"num_expected_neg_stage2\": 512,\n    \"num_expected_total_stage2\": 512,\n\n    # rcnn\n    \"rcnn_num_layers\": 2,\n    \"rcnn_in_channels\": 256,\n    \"rcnn_fc_out_channels\": 1024,\n    \"rcnn_loss_cls_weight\": 1,\n    \"rcnn_loss_reg_weight\": 1,\n    \"rcnn_target_means\": [0., 0., 0., 0.],\n    \"rcnn_target_stds\": [0.1, 0.1, 0.2, 0.2],\n\n    # train proposal\n    \"rpn_proposal_nms_across_levels\": False,\n    \"rpn_proposal_nms_pre\": 2000,\n    \"rpn_proposal_nms_post\": 2000,\n    \"rpn_proposal_max_num\": 2000,\n    \"rpn_proposal_nms_thr\": 0.7,\n    \"rpn_proposal_min_bbox_size\": 0,\n\n    # test proposal\n    \"rpn_nms_across_levels\": False,\n    \"rpn_nms_pre\": 1000,\n    \"rpn_nms_post\": 1000,\n    \"rpn_max_num\": 1000,\n    \"rpn_nms_thr\": 0.7,\n    \"rpn_min_bbox_min_size\": 0,\n    \"test_score_thr\": 0.05,\n    \"test_iou_thr\": 0.5,\n    \"test_max_per_img\": 100,\n    \"test_batch_size\": 1,\n\n    \"rpn_head_loss_type\": \"CrossEntropyLoss\",\n    \"rpn_head_use_sigmoid\": True,\n    \"rpn_head_weight\": 1.0,\n\n    # LR\n    \"base_lr\": 0.02,\n    \"base_step\": 58633,\n    \"total_epoch\": 13,\n    \"warmup_step\": 500,\n    \"warmup_mode\": \"linear\",\n    \"warmup_ratio\": 1/3.0,\n    \"sgd_step\": [8, 11],\n    \"sgd_momentum\": 0.9,\n\n    # train\n    \"batch_size\": 1,\n    \"loss_scale\": 1,\n    \"momentum\": 0.91,\n    \"weight_decay\": 1e-4,\n    \"epoch_size\": 12,\n    \"save_checkpoint\": True,\n    \"save_checkpoint_epochs\": 1,\n    \"keep_checkpoint_max\": 10,\n    \"save_checkpoint_path\": \"./\",\n\n    \"mindrecord_dir\": \"../MindRecord_COCO_TRAIN\",\n    \"coco_root\": \"./cocodataset/\",\n    \"train_data_type\": \"train2017\",\n    \"val_data_type\": \"val2017\",\n    \"instance_set\": \"annotations/instances_{}.json\",\n    \"coco_classes\": ('background', 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus',\n                     'train', 'truck', 'boat', 'traffic light', 'fire hydrant',\n                     'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog',\n                     'horse', 'sheep', 'cow', 'elephant', 'bear', 'zebra',\n                     'giraffe', 'backpack', 'umbrella', 'handbag', 'tie',\n                     'suitcase', 'frisbee', 'skis', 'snowboard', 'sports ball',\n                     'kite', 'baseball bat', 'baseball glove', 'skateboard',\n                     'surfboard', 'tennis racket', 'bottle', 'wine glass', 'cup',\n                     'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',\n                     'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza',\n                     'donut', 'cake', 'chair', 'couch', 'potted plant', 'bed',\n                     'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote',\n                     'keyboard', 'cell phone', 'microwave', 'oven', 'toaster', 'sink',\n                     'refrigerator', 'book', 'clock', 'vase', 'scissors',\n                     'teddy bear', 'hair drier', 'toothbrush'),\n    \"num_classes\": 81\n})\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/src/dataset.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\n\"\"\"FasterRcnn dataset\"\"\"\nfrom __future__ import division\n\nimport os\nimport numpy as np\nfrom numpy import random\n\nimport mmcv\nimport mindspore.dataset as de\nimport mindspore.dataset.vision.c_transforms as C\nimport mindspore.dataset.transforms as CC\nimport mindspore.common.dtype as mstype\nfrom mindspore.mindrecord import FileWriter\nfrom src.config import config\n\n# pylint: disable=locally-disabled, unused-variable\n\n\ndef bbox_overlaps(bboxes1, bboxes2, mode='iou'):\n    \"\"\"Calculate the ious between each bbox of bboxes1 and bboxes2.\n\n    Args:\n        bboxes1(ndarray): shape (n, 4)\n        bboxes2(ndarray): shape (k, 4)\n        mode(str): iou (intersection over union) or iof (intersection\n            over foreground)\n\n    Returns:\n        ious(ndarray): shape (n, k)\n    \"\"\"\n\n    assert mode in ['iou', 'iof']\n\n    bboxes1 = bboxes1.astype(np.float32)\n    bboxes2 = bboxes2.astype(np.float32)\n    rows = bboxes1.shape[0]\n    cols = bboxes2.shape[0]\n    ious = np.zeros((rows, cols), dtype=np.float32)\n    if rows * cols == 0:\n        return ious\n    exchange = False\n    if bboxes1.shape[0] > bboxes2.shape[0]:\n        bboxes1, bboxes2 = bboxes2, bboxes1\n        ious = np.zeros((cols, rows), dtype=np.float32)\n        exchange = True\n    area1 = (bboxes1[:, 2] - bboxes1[:, 0] + 1) * (bboxes1[:, 3] - bboxes1[:, 1] + 1)\n    area2 = (bboxes2[:, 2] - bboxes2[:, 0] + 1) * (bboxes2[:, 3] - bboxes2[:, 1] + 1)\n    for i in range(bboxes1.shape[0]):\n        x_start = np.maximum(bboxes1[i, 0], bboxes2[:, 0])\n        y_start = np.maximum(bboxes1[i, 1], bboxes2[:, 1])\n        x_end = np.minimum(bboxes1[i, 2], bboxes2[:, 2])\n        y_end = np.minimum(bboxes1[i, 3], bboxes2[:, 3])\n        overlap = np.maximum(x_end - x_start + 1, 0) * np.maximum(\n            y_end - y_start + 1, 0)\n        if mode == 'iou':\n            union = area1[i] + area2 - overlap\n        else:\n            union = area1[i] if not exchange else area2\n        ious[i, :] = overlap / union\n    if exchange:\n        ious = ious.T\n    return ious\n\n\nclass PhotoMetricDistortion:\n    \"\"\"Photo Metric Distortion\"\"\"\n\n    def __init__(self,\n                 brightness_delta=32,\n                 contrast_range=(0.5, 1.5),\n                 saturation_range=(0.5, 1.5),\n                 hue_delta=18):\n        self.brightness_delta = brightness_delta\n        self.contrast_lower, self.contrast_upper = contrast_range\n        self.saturation_lower, self.saturation_upper = saturation_range\n        self.hue_delta = hue_delta\n\n    def __call__(self, img, boxes, labels):\n        # random brightness\n        img = img.astype('float32')\n\n        if random.randint(2):\n            delta = random.uniform(-self.brightness_delta,\n                                   self.brightness_delta)\n            img += delta\n\n        # mode == 0 --> do random contrast first\n        # mode == 1 --> do random contrast last\n        mode = random.randint(2)\n        if mode == 1:\n            if random.randint(2):\n                alpha = random.uniform(self.contrast_lower,\n                                       self.contrast_upper)\n                img *= alpha\n\n        # convert color from BGR to HSV\n        img = mmcv.bgr2hsv(img)\n\n        # random saturation\n        if random.randint(2):\n            img[..., 1] *= random.uniform(self.saturation_lower,\n                                          self.saturation_upper)\n\n        # random hue\n        if random.randint(2):\n            img[..., 0] += random.uniform(-self.hue_delta, self.hue_delta)\n            img[..., 0][img[..., 0] > 360] -= 360\n            img[..., 0][img[..., 0] < 0] += 360\n\n        # convert color from HSV to BGR\n        img = mmcv.hsv2bgr(img)\n\n        # random contrast\n        if mode == 0:\n            if random.randint(2):\n                alpha = random.uniform(self.contrast_lower,\n                                       self.contrast_upper)\n                img *= alpha\n\n        # randomly swap channels\n        if random.randint(2):\n            img = img[..., random.permutation(3)]\n\n        return img, boxes, labels\n\n\nclass Expand:\n    \"\"\"expand image\"\"\"\n\n    def __init__(self, mean=(0, 0, 0), to_rgb=True, ratio_range=(1, 4)):\n        if to_rgb:\n            self.mean = mean[::-1]\n        else:\n            self.mean = mean\n        self.min_ratio, self.max_ratio = ratio_range\n\n    def __call__(self, img, boxes, labels):\n        if random.randint(2):\n            return img, boxes, labels\n\n        h, w, c = img.shape\n        ratio = random.uniform(self.min_ratio, self.max_ratio)\n        expand_img = np.full((int(h * ratio), int(w * ratio), c),\n                             self.mean).astype(img.dtype)\n        left = int(random.uniform(0, w * ratio - w))\n        top = int(random.uniform(0, h * ratio - h))\n        expand_img[top:top + h, left:left + w] = img\n        img = expand_img\n        boxes += np.tile((left, top), 2)\n        return img, boxes, labels\n\n\ndef rescale_column(img, img_shape, gt_bboxes, gt_label, gt_num):\n    \"\"\"rescale operation for image\"\"\"\n    img_data, scale_factor = mmcv.imrescale(img, (config.img_width, config.img_height), return_scale=True)\n    if img_data.shape[0] > config.img_height:\n        img_data, scale_factor2 = mmcv.imrescale(img_data, (config.img_height, config.img_width), return_scale=True)\n        scale_factor = scale_factor * scale_factor2\n    img_shape = np.append(img_shape, scale_factor)\n    img_shape = np.asarray(img_shape, dtype=np.float32)\n    gt_bboxes = gt_bboxes * scale_factor\n\n    gt_bboxes[:, 0::2] = np.clip(gt_bboxes[:, 0::2], 0, img_shape[1] - 1)\n    gt_bboxes[:, 1::2] = np.clip(gt_bboxes[:, 1::2], 0, img_shape[0] - 1)\n\n    return (img_data, img_shape, gt_bboxes, gt_label, gt_num)\n\n\ndef resize_column(img, img_shape, gt_bboxes, gt_label, gt_num):\n    \"\"\"resize operation for image\"\"\"\n    img_data = img\n    img_data, w_scale, h_scale = mmcv.imresize(\n        img_data, (config.img_width, config.img_height), return_scale=True)\n    scale_factor = np.array(\n        [w_scale, h_scale, w_scale, h_scale], dtype=np.float32)\n    img_shape = (config.img_height, config.img_width, 1.0)\n    img_shape = np.asarray(img_shape, dtype=np.float32)\n\n    gt_bboxes = gt_bboxes * scale_factor\n\n    gt_bboxes[:, 0::2] = np.clip(gt_bboxes[:, 0::2], 0, img_shape[1] - 1)\n    gt_bboxes[:, 1::2] = np.clip(gt_bboxes[:, 1::2], 0, img_shape[0] - 1)\n\n    return (img_data, img_shape, gt_bboxes, gt_label, gt_num)\n\n\ndef resize_column_test(img, img_shape, gt_bboxes, gt_label, gt_num):\n    \"\"\"resize operation for image of eval\"\"\"\n    img_data = img\n    img_data, w_scale, h_scale = mmcv.imresize(\n        img_data, (config.img_width, config.img_height), return_scale=True)\n    scale_factor = np.array(\n        [w_scale, h_scale, w_scale, h_scale], dtype=np.float32)\n    img_shape = np.append(img_shape, (h_scale, w_scale))\n    img_shape = np.asarray(img_shape, dtype=np.float32)\n\n    gt_bboxes = gt_bboxes * scale_factor\n\n    gt_bboxes[:, 0::2] = np.clip(gt_bboxes[:, 0::2], 0, img_shape[1] - 1)\n    gt_bboxes[:, 1::2] = np.clip(gt_bboxes[:, 1::2], 0, img_shape[0] - 1)\n\n    return (img_data, img_shape, gt_bboxes, gt_label, gt_num)\n\n\ndef impad_to_multiple_column(img, img_shape, gt_bboxes, gt_label, gt_num):\n    \"\"\"impad operation for image\"\"\"\n    img_data = mmcv.impad(img, (config.img_height, config.img_width))\n    img_data = img_data.astype(np.float32)\n    return (img_data, img_shape, gt_bboxes, gt_label, gt_num)\n\n\ndef imnormalize_column(img, img_shape, gt_bboxes, gt_label, gt_num):\n    \"\"\"imnormalize operation for image\"\"\"\n    img_data = mmcv.imnormalize(img, [123.675, 116.28, 103.53], [58.395, 57.12, 57.375], True)\n    img_data = img_data.astype(np.float32)\n    return (img_data, img_shape, gt_bboxes, gt_label, gt_num)\n\n\ndef flip_column(img, img_shape, gt_bboxes, gt_label, gt_num):\n    \"\"\"flip operation for image\"\"\"\n    img_data = img\n    img_data = mmcv.imflip(img_data)\n    flipped = gt_bboxes.copy()\n    _, w, _ = img_data.shape\n\n    flipped[..., 0::4] = w - gt_bboxes[..., 2::4] - 1\n    flipped[..., 2::4] = w - gt_bboxes[..., 0::4] - 1\n\n    return (img_data, img_shape, flipped, gt_label, gt_num)\n\n\ndef flipped_generation(img, img_shape, gt_bboxes, gt_label, gt_num):\n    \"\"\"flipped generation\"\"\"\n    img_data = img\n    flipped = gt_bboxes.copy()\n    _, w, _ = img_data.shape\n\n    flipped[..., 0::4] = w - gt_bboxes[..., 2::4] - 1\n    flipped[..., 2::4] = w - gt_bboxes[..., 0::4] - 1\n\n    return (img_data, img_shape, flipped, gt_label, gt_num)\n\n\ndef image_bgr_rgb(img, img_shape, gt_bboxes, gt_label, gt_num):\n    img_data = img[:, :, ::-1]\n    return (img_data, img_shape, gt_bboxes, gt_label, gt_num)\n\n\ndef transpose_column(img, img_shape, gt_bboxes, gt_label, gt_num):\n    \"\"\"transpose operation for image\"\"\"\n    img_data = img.transpose(2, 0, 1).copy()\n    img_data = img_data.astype(np.float16)\n    img_shape = img_shape.astype(np.float16)\n    gt_bboxes = gt_bboxes.astype(np.float16)\n    gt_label = gt_label.astype(np.int32)\n    gt_num = gt_num.astype(np.bool)\n\n    return (img_data, img_shape, gt_bboxes, gt_label, gt_num)\n\n\ndef photo_crop_column(img, img_shape, gt_bboxes, gt_label, gt_num):\n    \"\"\"photo crop operation for image\"\"\"\n    random_photo = PhotoMetricDistortion()\n    img_data, gt_bboxes, gt_label = random_photo(img, gt_bboxes, gt_label)\n\n    return (img_data, img_shape, gt_bboxes, gt_label, gt_num)\n\n\ndef expand_column(img, img_shape, gt_bboxes, gt_label, gt_num):\n    \"\"\"expand operation for image\"\"\"\n    expand = Expand()\n    img, gt_bboxes, gt_label = expand(img, gt_bboxes, gt_label)\n\n    return (img, img_shape, gt_bboxes, gt_label, gt_num)\n\n\ndef preprocess_fn(image, box, is_training):\n    \"\"\"Preprocess function for dataset.\"\"\"\n\n    def _infer_data(image_bgr, image_shape, gt_box_new, gt_label_new, gt_iscrowd_new_revert):\n        image_shape = image_shape[:2]\n        input_data = image_bgr, image_shape, gt_box_new, gt_label_new, gt_iscrowd_new_revert\n\n        if config.keep_ratio:\n            input_data = rescale_column(*input_data)\n        else:\n            input_data = resize_column_test(*input_data)\n\n        input_data = image_bgr_rgb(*input_data)\n\n        output_data = input_data\n        return output_data\n\n    def _data_aug(image, box, is_training):\n        \"\"\"Data augmentation function.\"\"\"\n        image_bgr = image.copy()\n        image_bgr[:, :, 0] = image[:, :, 2]\n        image_bgr[:, :, 1] = image[:, :, 1]\n        image_bgr[:, :, 2] = image[:, :, 0]\n        image_shape = image_bgr.shape[:2]\n        gt_box = box[:, :4]\n        gt_label = box[:, 4]\n        gt_iscrowd = box[:, 5]\n\n        pad_max_number = 128\n        gt_box_new = np.pad(gt_box, ((0, pad_max_number - box.shape[0]), (0, 0)), mode=\"constant\", constant_values=0)\n        gt_label_new = np.pad(gt_label, ((0, pad_max_number - box.shape[0])), mode=\"constant\", constant_values=-1)\n        gt_iscrowd_new = np.pad(gt_iscrowd, ((0, pad_max_number - box.shape[0])), mode=\"constant\", constant_values=1)\n        gt_iscrowd_new_revert = (~(gt_iscrowd_new.astype(np.bool))).astype(np.int32)\n\n        if not is_training:\n            return _infer_data(image_bgr, image_shape, gt_box_new, gt_label_new, gt_iscrowd_new_revert)\n\n        input_data = image_bgr, image_shape, gt_box_new, gt_label_new, gt_iscrowd_new_revert\n\n        if config.keep_ratio:\n            input_data = rescale_column(*input_data)\n        else:\n            input_data = resize_column(*input_data)\n\n        input_data = image_bgr_rgb(*input_data)\n\n        output_data = input_data\n        return output_data\n\n    return _data_aug(image, box, is_training)\n\n\ndef create_coco_label(is_training):\n    \"\"\"Get image path and annotation from COCO.\"\"\"\n    from pycocotools.coco import COCO\n\n    coco_root = config.coco_root\n    data_type = config.val_data_type\n    if is_training:\n        data_type = config.train_data_type\n\n    # Classes need to train or test.\n    train_cls = config.coco_classes\n    train_cls_dict = {}\n    for i, cls in enumerate(train_cls):\n        train_cls_dict[cls] = i\n\n    anno_json = os.path.join(coco_root, config.instance_set.format(data_type))\n\n    coco = COCO(anno_json)\n    classs_dict = {}\n    cat_ids = coco.loadCats(coco.getCatIds())\n    for cat in cat_ids:\n        classs_dict[cat[\"id\"]] = cat[\"name\"]\n\n    image_ids = coco.getImgIds()\n    image_files = []\n    image_anno_dict = {}\n\n    for img_id in image_ids:\n        image_info = coco.loadImgs(img_id)\n        file_name = image_info[0][\"file_name\"]\n        anno_ids = coco.getAnnIds(imgIds=img_id, iscrowd=None)\n        anno = coco.loadAnns(anno_ids)\n        image_path = os.path.join(coco_root, data_type, file_name)\n        annos = []\n        for label in anno:\n            bbox = label[\"bbox\"]\n            class_name = classs_dict[label[\"category_id\"]]\n            if class_name in train_cls:\n                x1, x2 = bbox[0], bbox[0] + bbox[2]\n                y1, y2 = bbox[1], bbox[1] + bbox[3]\n                annos.append([x1, y1, x2, y2] + [train_cls_dict[class_name]] + [int(label[\"iscrowd\"])])\n\n        image_files.append(image_path)\n        if annos:\n            image_anno_dict[image_path] = np.array(annos)\n        else:\n            image_anno_dict[image_path] = np.array([0, 0, 0, 0, 0, 1])\n\n    return image_files, image_anno_dict\n\n\ndef anno_parser(annos_str):\n    \"\"\"Parse annotation from string to list.\"\"\"\n    annos = []\n    for anno_str in annos_str:\n        anno = list(map(int, anno_str.strip().split(',')))\n        annos.append(anno)\n    return annos\n\n\ndef filter_valid_data(image_dir, anno_path):\n    \"\"\"Filter valid image file, which both in image_dir and anno_path.\"\"\"\n    image_files = []\n    image_anno_dict = {}\n    if not os.path.isdir(image_dir):\n        raise RuntimeError(\"Path given is not valid.\")\n    if not os.path.isfile(anno_path):\n        raise RuntimeError(\"Annotation file is not valid.\")\n\n    with open(anno_path, \"rb\") as f:\n        lines = f.readlines()\n    for line in lines:\n        line_str = line.decode(\"utf-8\").strip()\n        line_split = str(line_str).split(' ')\n        file_name = line_split[0]\n        image_path = os.path.join(image_dir, file_name)\n        if os.path.isfile(image_path):\n            image_anno_dict[image_path] = anno_parser(line_split[1:])\n            image_files.append(image_path)\n    return image_files, image_anno_dict\n\n\ndef data_to_mindrecord_byte_image(dataset=\"coco\", is_training=True, prefix=\"fasterrcnn.mindrecord\", file_num=8):\n    \"\"\"Create MindRecord file.\"\"\"\n    mindrecord_dir = config.mindrecord_dir\n    mindrecord_path = os.path.join(mindrecord_dir, prefix)\n    writer = FileWriter(mindrecord_path, file_num)\n    if dataset == \"coco\":\n        image_files, image_anno_dict = create_coco_label(is_training)\n    else:\n        image_files, image_anno_dict = filter_valid_data(config.IMAGE_DIR, config.ANNO_PATH)\n\n    fasterrcnn_json = {\n        \"image\": {\"type\": \"bytes\"},\n        \"annotation\": {\"type\": \"int32\", \"shape\": [-1, 6]},\n    }\n    writer.add_schema(fasterrcnn_json, \"fasterrcnn_json\")\n\n    for image_name in image_files:\n        with open(image_name, 'rb') as f:\n            img = f.read()\n        annos = np.array(image_anno_dict[image_name], dtype=np.int32)\n        row = {\"image\": img, \"annotation\": annos}\n        writer.write_raw_data([row])\n    writer.commit()\n\n\ndef create_fasterrcnn_dataset(mindrecord_file, batch_size=2, repeat_num=12, device_num=1, rank_id=0,\n                              is_training=True, num_parallel_workers=4):\n    \"\"\"Creatr FasterRcnn dataset with MindDataset.\"\"\"\n    ds = de.MindDataset(mindrecord_file, columns_list=[\"image\", \"annotation\"], num_shards=device_num, shard_id=rank_id,\n                        num_parallel_workers=1, shuffle=False)\n    decode = C.Decode()\n    ds = ds.map(operations=decode, input_columns=[\"image\"], num_parallel_workers=1)\n    compose_map_func = (lambda image, annotation: preprocess_fn(image, annotation, is_training))\n\n    hwc_to_chw = C.HWC2CHW()\n    normalize_op = C.Normalize((123.675, 116.28, 103.53), (58.395, 57.12, 57.375))\n    horizontally_op = C.RandomHorizontalFlip(1)\n    type_cast0 = CC.TypeCast(mstype.float32)\n    type_cast1 = CC.TypeCast(mstype.float16)\n    type_cast2 = CC.TypeCast(mstype.int32)\n    type_cast3 = CC.TypeCast(mstype.bool_)\n\n    if is_training:\n        ds = ds.map(operations=compose_map_func, input_columns=[\"image\", \"annotation\"],\n                    output_columns=[\"image\", \"image_shape\", \"box\", \"label\", \"valid_num\"],\n                    column_order=[\"image\", \"image_shape\", \"box\", \"label\", \"valid_num\"],\n                    num_parallel_workers=num_parallel_workers)\n\n        flip = (np.random.rand() < config.flip_ratio)\n        if flip:\n            ds = ds.map(operations=[normalize_op, type_cast0], input_columns=[\"image\"],\n                        num_parallel_workers=12)\n            ds = ds.map(operations=flipped_generation,\n                        input_columns=[\"image\", \"image_shape\", \"box\", \"label\", \"valid_num\"],\n                        num_parallel_workers=num_parallel_workers)\n        else:\n            ds = ds.map(operations=[normalize_op, type_cast0], input_columns=[\"image\"],\n                        num_parallel_workers=12)\n        ds = ds.map(operations=[hwc_to_chw, type_cast1], input_columns=[\"image\"],\n                    num_parallel_workers=12)\n\n    else:\n        ds = ds.map(operations=compose_map_func,\n                    input_columns=[\"image\", \"annotation\"],\n                    output_columns=[\"image\", \"image_shape\", \"box\", \"label\", \"valid_num\"],\n                    column_order=[\"image\", \"image_shape\", \"box\", \"label\", \"valid_num\"],\n                    num_parallel_workers=num_parallel_workers)\n\n        ds = ds.map(operations=[normalize_op, hwc_to_chw, type_cast1], input_columns=[\"image\"],\n                    num_parallel_workers=24)\n\n    # transpose_column from python to c\n    ds = ds.map(operations=[type_cast1], input_columns=[\"image_shape\"])\n    ds = ds.map(operations=[type_cast1], input_columns=[\"box\"])\n    ds = ds.map(operations=[type_cast2], input_columns=[\"label\"])\n    ds = ds.map(operations=[type_cast3], input_columns=[\"valid_num\"])\n    ds = ds.batch(batch_size, drop_remainder=True)\n    ds = ds.repeat(repeat_num)\n\n    return ds\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/src/lr_schedule.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"lr generator for fasterrcnn\"\"\"\nimport math\n\ndef linear_warmup_learning_rate(current_step, warmup_steps, base_lr, init_lr):\n    lr_inc = (float(base_lr) - float(init_lr)) / float(warmup_steps)\n    learning_rate = float(init_lr) + lr_inc * current_step\n    return learning_rate\n\ndef a_cosine_learning_rate(current_step, base_lr, warmup_steps, decay_steps):\n    base = float(current_step - warmup_steps) / float(decay_steps)\n    learning_rate = (1 + math.cos(base * math.pi)) / 2 * base_lr\n    return learning_rate\n\ndef dynamic_lr(config, rank_size=1):\n    \"\"\"dynamic learning rate generator\"\"\"\n    base_lr = config.base_lr\n\n    base_step = (config.base_step // rank_size) + rank_size\n    total_steps = int(base_step * config.total_epoch)\n    warmup_steps = int(config.warmup_step)\n    lr = []\n    for i in range(total_steps):\n        if i < warmup_steps:\n            lr.append(linear_warmup_learning_rate(i, warmup_steps, base_lr, base_lr * config.warmup_ratio))\n        else:\n            lr.append(a_cosine_learning_rate(i, base_lr, warmup_steps, total_steps))\n\n    return lr\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/src/network_define.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"FasterRcnn training network wrapper.\"\"\"\n\nimport time\nimport numpy as np\nimport mindspore.nn as nn\nfrom mindspore.common.tensor import Tensor\nfrom mindspore.ops import functional as F\nfrom mindspore.ops import composite as C\nfrom mindspore import ParameterTuple\nfrom mindspore.train.callback import Callback\nfrom mindspore.nn.wrap.grad_reducer import DistributedGradReducer\n\n# pylint: disable=locally-disabled, missing-docstring, unused-argument\n\n\ntime_stamp_init = False\ntime_stamp_first = 0\nclass LossCallBack(Callback):\n    \"\"\"\n    Monitor the loss in training.\n\n    If the loss is NAN or INF terminating training.\n\n    Note:\n        If per_print_times is 0 do not print loss.\n\n    Args:\n        per_print_times (int): Print loss every times. Default: 1.\n    \"\"\"\n\n    def __init__(self, per_print_times=1, rank_id=0):\n        super(LossCallBack, self).__init__()\n        if not isinstance(per_print_times, int) or per_print_times < 0:\n            raise ValueError(\"print_step must be int and >= 0.\")\n        self._per_print_times = per_print_times\n        self.count = 0\n        self.rpn_loss_sum = 0\n        self.rcnn_loss_sum = 0\n        self.rpn_cls_loss_sum = 0\n        self.rpn_reg_loss_sum = 0\n        self.rcnn_cls_loss_sum = 0\n        self.rcnn_reg_loss_sum = 0\n        self.rank_id = rank_id\n\n        global time_stamp_init, time_stamp_first\n        if not time_stamp_init:\n            time_stamp_first = time.time()\n            time_stamp_init = True\n\n    def step_end(self, run_context):\n        cb_params = run_context.original_args()\n        rpn_loss = cb_params.net_outputs[0].asnumpy()\n        rcnn_loss = cb_params.net_outputs[1].asnumpy()\n        rpn_cls_loss = cb_params.net_outputs[2].asnumpy()\n\n        rpn_reg_loss = cb_params.net_outputs[3].asnumpy()\n        rcnn_cls_loss = cb_params.net_outputs[4].asnumpy()\n        rcnn_reg_loss = cb_params.net_outputs[5].asnumpy()\n\n        self.count += 1\n        self.rpn_loss_sum += float(rpn_loss)\n        self.rcnn_loss_sum += float(rcnn_loss)\n        self.rpn_cls_loss_sum += float(rpn_cls_loss)\n        self.rpn_reg_loss_sum += float(rpn_reg_loss)\n        self.rcnn_cls_loss_sum += float(rcnn_cls_loss)\n        self.rcnn_reg_loss_sum += float(rcnn_reg_loss)\n\n        cur_step_in_epoch = (cb_params.cur_step_num - 1) % cb_params.batch_num + 1\n\n        if self.count >= 1:\n            global time_stamp_first\n            time_stamp_current = time.time()\n\n            rpn_loss = self.rpn_loss_sum/self.count\n            rcnn_loss = self.rcnn_loss_sum/self.count\n            rpn_cls_loss = self.rpn_cls_loss_sum/self.count\n\n            rpn_reg_loss = self.rpn_reg_loss_sum/self.count\n            rcnn_cls_loss = self.rcnn_cls_loss_sum/self.count\n            rcnn_reg_loss = self.rcnn_reg_loss_sum/self.count\n\n            total_loss = rpn_loss + rcnn_loss\n\n            loss_file = open(\"./loss_{}.log\".format(self.rank_id), \"a+\")\n            loss_file.write(\"%lu epoch: %s step: %s ,rpn_loss: %.5f, rcnn_loss: %.5f, rpn_cls_loss: %.5f, \"\n                            \"rpn_reg_loss: %.5f, rcnn_cls_loss: %.5f, rcnn_reg_loss: %.5f, total_loss: %.5f\" %\n                            (time_stamp_current - time_stamp_first, cb_params.cur_epoch_num, cur_step_in_epoch,\n                             rpn_loss, rcnn_loss, rpn_cls_loss, rpn_reg_loss,\n                             rcnn_cls_loss, rcnn_reg_loss, total_loss))\n            loss_file.write(\"\\n\")\n            loss_file.close()\n\n            self.count = 0\n            self.rpn_loss_sum = 0\n            self.rcnn_loss_sum = 0\n            self.rpn_cls_loss_sum = 0\n            self.rpn_reg_loss_sum = 0\n            self.rcnn_cls_loss_sum = 0\n            self.rcnn_reg_loss_sum = 0\n\nclass LossNet(nn.Cell):\n    \"\"\"FasterRcnn loss method\"\"\"\n    def construct(self, x1, x2, x3, x4, x5, x6):\n        return x1 + x2\n\nclass WithLossCell(nn.Cell):\n    \"\"\"\n    Wrap the network with loss function to compute loss.\n\n    Args:\n        backbone (Cell): The target network to wrap.\n        loss_fn (Cell): The loss function used to compute loss.\n    \"\"\"\n    def __init__(self, backbone, loss_fn):\n        super(WithLossCell, self).__init__(auto_prefix=False)\n        self._backbone = backbone\n        self._loss_fn = loss_fn\n\n    def construct(self, x, img_shape, gt_bboxe, gt_label, gt_num):\n        loss1, loss2, loss3, loss4, loss5, loss6 = self._backbone(x, img_shape, gt_bboxe, gt_label, gt_num)\n        return self._loss_fn(loss1, loss2, loss3, loss4, loss5, loss6)\n\n    @property\n    def backbone_network(self):\n        \"\"\"\n        Get the backbone network.\n\n        Returns:\n            Cell, return backbone network.\n        \"\"\"\n        return self._backbone\n\n\nclass TrainOneStepCell(nn.Cell):\n    \"\"\"\n    Network training package class.\n\n    Append an optimizer to the training network after that the construct function\n    can be called to create the backward graph.\n\n    Args:\n        network (Cell): The training network.\n        network_backbone (Cell): The forward network.\n        optimizer (Cell): Optimizer for updating the weights.\n        sens (Number): The adjust parameter. Default value is 1.0.\n        reduce_flag (bool): The reduce flag. Default value is False.\n        mean (bool): Allreduce method. Default value is False.\n        degree (int): Device number. Default value is None.\n    \"\"\"\n    def __init__(self, network, network_backbone, optimizer, sens=1.0, reduce_flag=False, mean=True, degree=None):\n        super(TrainOneStepCell, self).__init__(auto_prefix=False)\n        self.network = network\n        self.network.set_grad()\n        self.backbone = network_backbone\n        self.weights = ParameterTuple(network.trainable_params())\n        self.optimizer = optimizer\n        self.grad = C.GradOperation(get_by_list=True,\n                                    sens_param=True)\n        self.sens = Tensor((np.ones((1,)) * sens).astype(np.float16))\n        self.reduce_flag = reduce_flag\n        if reduce_flag:\n            self.grad_reducer = DistributedGradReducer(optimizer.parameters, mean, degree)\n\n    def construct(self, x, img_shape, gt_bboxe, gt_label, gt_num):\n        weights = self.weights\n        loss1, loss2, loss3, loss4, loss5, loss6 = self.backbone(x, img_shape, gt_bboxe, gt_label, gt_num)\n        grads = self.grad(self.network, weights)(x, img_shape, gt_bboxe, gt_label, gt_num, self.sens)\n        if self.reduce_flag:\n            grads = self.grad_reducer(grads)\n        return F.depend(loss1, self.optimizer(grads)), loss2, loss3, loss4, loss5, loss6\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/faster_rcnn/src/util.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"coco eval for fasterrcnn\"\"\"\nimport json\nimport numpy as np\nfrom pycocotools.coco import COCO\nfrom pycocotools.cocoeval import COCOeval\nimport mmcv\n\n# pylint: disable=locally-disabled, invalid-name\n\n_init_value = np.array(0.0)\nsummary_init = {\n    'Precision/mAP': _init_value,\n    'Precision/mAP@.50IOU': _init_value,\n    'Precision/mAP@.75IOU': _init_value,\n    'Precision/mAP (small)': _init_value,\n    'Precision/mAP (medium)': _init_value,\n    'Precision/mAP (large)': _init_value,\n    'Recall/AR@1': _init_value,\n    'Recall/AR@10': _init_value,\n    'Recall/AR@100': _init_value,\n    'Recall/AR@100 (small)': _init_value,\n    'Recall/AR@100 (medium)': _init_value,\n    'Recall/AR@100 (large)': _init_value,\n}\n\n\ndef coco_eval(result_files, result_types, coco, max_dets=(100, 300, 1000), single_result=False):\n    \"\"\"coco eval for fasterrcnn\"\"\"\n    anns = json.load(open(result_files['bbox']))\n    if not anns:\n        return summary_init\n\n    if mmcv.is_str(coco):\n        coco = COCO(coco)\n    assert isinstance(coco, COCO)\n\n    for res_type in result_types:\n        result_file = result_files[res_type]\n        assert result_file.endswith('.json')\n\n        coco_dets = coco.loadRes(result_file)\n        gt_img_ids = coco.getImgIds()\n        det_img_ids = coco_dets.getImgIds()\n        iou_type = 'bbox' if res_type == 'proposal' else res_type\n        cocoEval = COCOeval(coco, coco_dets, iou_type)\n        if res_type == 'proposal':\n            cocoEval.params.useCats = 0\n            cocoEval.params.maxDets = list(max_dets)\n\n        tgt_ids = gt_img_ids if not single_result else det_img_ids\n\n        if single_result:\n            res_dict = dict()\n            for id_i in tgt_ids:\n                cocoEval = COCOeval(coco, coco_dets, iou_type)\n                if res_type == 'proposal':\n                    cocoEval.params.useCats = 0\n                    cocoEval.params.maxDets = list(max_dets)\n\n                cocoEval.params.imgIds = [id_i]\n                cocoEval.evaluate()\n                cocoEval.accumulate()\n                cocoEval.summarize()\n                res_dict.update({coco.imgs[id_i]['file_name']: cocoEval.stats[1]})\n\n        cocoEval = COCOeval(coco, coco_dets, iou_type)\n        if res_type == 'proposal':\n            cocoEval.params.useCats = 0\n            cocoEval.params.maxDets = list(max_dets)\n\n        cocoEval.params.imgIds = tgt_ids\n        cocoEval.evaluate()\n        cocoEval.accumulate()\n        cocoEval.summarize()\n\n        summary_metrics = {\n            'Precision/mAP': cocoEval.stats[0],\n            'Precision/mAP@.50IOU': cocoEval.stats[1],\n            'Precision/mAP@.75IOU': cocoEval.stats[2],\n            'Precision/mAP (small)': cocoEval.stats[3],\n            'Precision/mAP (medium)': cocoEval.stats[4],\n            'Precision/mAP (large)': cocoEval.stats[5],\n            'Recall/AR@1': cocoEval.stats[6],\n            'Recall/AR@10': cocoEval.stats[7],\n            'Recall/AR@100': cocoEval.stats[8],\n            'Recall/AR@100 (small)': cocoEval.stats[9],\n            'Recall/AR@100 (medium)': cocoEval.stats[10],\n            'Recall/AR@100 (large)': cocoEval.stats[11],\n        }\n\n    return summary_metrics\n\n\ndef xyxy2xywh(bbox):\n    _bbox = bbox.tolist()\n    return [\n        _bbox[0],\n        _bbox[1],\n        _bbox[2] - _bbox[0] + 1,\n        _bbox[3] - _bbox[1] + 1,\n        ]\n\ndef bbox2result_1image(bboxes, labels, num_classes):\n    \"\"\"Convert detection results to a list of numpy arrays.\n\n    Args:\n        bboxes (Tensor): shape (n, 5)\n        labels (Tensor): shape (n, )\n        num_classes (int): class number, including background class\n\n    Returns:\n        list(ndarray): bbox results of each class\n    \"\"\"\n    if bboxes.shape[0] == 0:\n        result = [np.zeros((0, 5), dtype=np.float32) for i in range(num_classes - 1)]\n    else:\n        result = [bboxes[labels == i, :] for i in range(num_classes - 1)]\n    return result\n\ndef proposal2json(dataset, results):\n    \"\"\"convert proposal to json mode\"\"\"\n    img_ids = dataset.getImgIds()\n    json_results = []\n    dataset_len = dataset.get_dataset_size()*2\n    for idx in range(dataset_len):\n        img_id = img_ids[idx]\n        bboxes = results[idx]\n        for i in range(bboxes.shape[0]):\n            data = dict()\n            data['image_id'] = img_id\n            data['bbox'] = xyxy2xywh(bboxes[i])\n            data['score'] = float(bboxes[i][4])\n            data['category_id'] = 1\n            json_results.append(data)\n    return json_results\n\ndef det2json(dataset, results):\n    \"\"\"convert det to json mode\"\"\"\n    cat_ids = dataset.getCatIds()\n    img_ids = dataset.getImgIds()\n    json_results = []\n    dataset_len = len(img_ids)\n    for idx in range(dataset_len):\n        img_id = img_ids[idx]\n        if idx == len(results): break\n        result = results[idx]\n        for label, result_label in enumerate(result):\n            bboxes = result_label\n            for i in range(bboxes.shape[0]):\n                data = dict()\n                data['image_id'] = img_id\n                data['bbox'] = xyxy2xywh(bboxes[i])\n                data['score'] = float(bboxes[i][4])\n                data['category_id'] = cat_ids[label]\n                json_results.append(data)\n    return json_results\n\ndef segm2json(dataset, results):\n    \"\"\"convert segm to json mode\"\"\"\n    bbox_json_results = []\n    segm_json_results = []\n    for idx in range(len(dataset)):\n        img_id = dataset.img_ids[idx]\n        det, seg = results[idx]\n        for label, det_label in enumerate(det):\n            # bbox results\n            bboxes = det_label\n            for i in range(bboxes.shape[0]):\n                data = dict()\n                data['image_id'] = img_id\n                data['bbox'] = xyxy2xywh(bboxes[i])\n                data['score'] = float(bboxes[i][4])\n                data['category_id'] = dataset.cat_ids[label]\n                bbox_json_results.append(data)\n\n            if len(seg) == 2:\n                segms = seg[0][label]\n                mask_score = seg[1][label]\n            else:\n                segms = seg[label]\n                mask_score = [bbox[4] for bbox in bboxes]\n            for i in range(bboxes.shape[0]):\n                data = dict()\n                data['image_id'] = img_id\n                data['score'] = float(mask_score[i])\n                data['category_id'] = dataset.cat_ids[label]\n                segms[i]['counts'] = segms[i]['counts'].decode()\n                data['segmentation'] = segms[i]\n                segm_json_results.append(data)\n    return bbox_json_results, segm_json_results\n\ndef results2json(dataset, results, out_file):\n    \"\"\"convert result convert to json mode\"\"\"\n    result_files = dict()\n    if isinstance(results[0], list):\n        json_results = det2json(dataset, results)\n        result_files['bbox'] = '{}.{}.json'.format(out_file, 'bbox')\n        result_files['proposal'] = '{}.{}.json'.format(out_file, 'bbox')\n        mmcv.dump(json_results, result_files['bbox'])\n    elif isinstance(results[0], tuple):\n        json_results = segm2json(dataset, results)\n        result_files['bbox'] = '{}.{}.json'.format(out_file, 'bbox')\n        result_files['proposal'] = '{}.{}.json'.format(out_file, 'bbox')\n        result_files['segm'] = '{}.{}.json'.format(out_file, 'segm')\n        mmcv.dump(json_results[0], result_files['bbox'])\n        mmcv.dump(json_results[1], result_files['segm'])\n    elif isinstance(results[0], np.ndarray):\n        json_results = proposal2json(dataset, results)\n        result_files['proposal'] = '{}.{}.json'.format(out_file, 'proposal')\n        mmcv.dump(json_results, result_files['proposal'])\n    else:\n        raise TypeError('invalid type of results')\n    return result_files\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/yolov3_darknet53/coco_attack_deepfool.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"Generate adversarial example for yolov3_darknet53 by DeepFool\"\"\"\nimport os\nimport argparse\nimport datetime\nimport numpy as np\n\nfrom mindspore import Tensor\nfrom mindspore.nn import Cell\nfrom mindspore.ops import operations as P\nfrom mindspore.context import ParallelMode\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nimport mindspore as ms\n\nfrom mindarmour.adv_robustness.attacks import DeepFool\n\nfrom src.yolo import YOLOV3DarkNet53\nfrom src.logger import get_logger\nfrom src.yolo_dataset import create_yolo_dataset\nfrom src.config import ConfigYOLOV3DarkNet53\n\n\ndef parse_args():\n    \"\"\"Parse arguments.\"\"\"\n    parser = argparse.ArgumentParser('mindspore coco testing')\n\n    # device related\n    parser.add_argument('--data_dir', type=str, default='', help='train data dir')\n    parser.add_argument('--pretrained', default='', type=str, help='model_path, local pretrained model to load')\n    parser.add_argument('--samples_num', default=1, type=int, help='Number of sample to be generated.')\n    parser.add_argument('--log_path', type=str, default='outputs/', help='checkpoint save location')\n    parser.add_argument('--testing_shape', type=str, default='', help='shape for test ')\n\n    args, _ = parser.parse_known_args()\n\n    args.data_root = os.path.join(args.data_dir, 'val2014')\n    args.annFile = os.path.join(args.data_dir, 'annotations/instances_val2014.json')\n\n    return args\n\n\ndef conver_testing_shape(args):\n    \"\"\"Convert testing shape to list.\"\"\"\n    testing_shape = [int(args.testing_shape), int(args.testing_shape)]\n    return testing_shape\n\n\nclass SolveOutput(Cell):\n    \"\"\"Solve output of the target network to adapt DeepFool.\"\"\"\n    def __init__(self, network):\n        super(SolveOutput, self).__init__()\n        self._network = network\n        self._reshape = P.Reshape()\n\n    def construct(self, image, input_shape):\n        prediction = self._network(image, input_shape)\n        output_big = prediction[0]\n        output_big = self._reshape(output_big, (output_big.shape[0], -1, 85))\n        output_big_boxes = output_big[:, :, 0: 5]\n        output_big_logits = output_big[:, :, 5:]\n        return output_big_boxes, output_big_logits\n\n\ndef test():\n    \"\"\"The function of eval.\"\"\"\n    args = parse_args()\n\n    devid = int(os.getenv('DEVICE_ID')) if os.getenv('DEVICE_ID') else 0\n    context.set_context(mode=context.GRAPH_MODE, device_target='Ascend', save_graphs=True, device_id=devid)\n\n    # logger\n    args.outputs_dir = os.path.join(args.log_path,\n                                    datetime.datetime.now().strftime('%Y-%m-%d_time_%H_%M_%S'))\n    rank_id = int(os.environ.get('RANK_ID')) if os.environ.get('RANK_ID') else 0\n    args.logger = get_logger(args.outputs_dir, rank_id)\n\n    context.reset_auto_parallel_context()\n    parallel_mode = ParallelMode.STAND_ALONE\n    context.set_auto_parallel_context(parallel_mode=parallel_mode, gradients_mean=True, device_num=1)\n\n    args.logger.info('Creating Network....')\n    network = SolveOutput(YOLOV3DarkNet53(is_training=False))\n\n    data_root = args.data_root\n    ann_file = args.annFile\n\n    args.logger.info(args.pretrained)\n    if os.path.isfile(args.pretrained):\n        param_dict = load_checkpoint(args.pretrained)\n        param_dict_new = {}\n        for key, values in param_dict.items():\n            if key.startswith('moments.'):\n                continue\n            elif key.startswith('yolo_network.'):\n                param_dict_new[key[13:]] = values\n            else:\n                param_dict_new[key] = values\n        load_param_into_net(network, param_dict_new)\n        args.logger.info('load_model {} success'.format(args.pretrained))\n    else:\n        args.logger.info('{} not exists or not a pre-trained file'.format(args.pretrained))\n        assert FileNotFoundError('{} not exists or not a pre-trained file'.format(args.pretrained))\n        exit(1)\n\n    config = ConfigYOLOV3DarkNet53()\n    if args.testing_shape:\n        config.test_img_shape = conver_testing_shape(args)\n\n    ds, data_size = create_yolo_dataset(data_root, ann_file, is_training=False, batch_size=1,\n                                        max_epoch=1, device_num=1, rank=rank_id, shuffle=False,\n                                        config=config)\n\n    args.logger.info('testing shape : {}'.format(config.test_img_shape))\n    args.logger.info('totol {} images to eval'.format(data_size))\n\n    network.set_train(False)\n    # build attacker\n    attack = DeepFool(network, num_classes=80, model_type='detection', reserve_ratio=0.9, bounds=(0, 1))\n    input_shape = Tensor(tuple(config.test_img_shape), ms.float32)\n\n    args.logger.info('Start inference....')\n    batch_num = args.samples_num\n    adv_example = []\n    for i, data in enumerate(ds.create_dict_iterator(num_epochs=1)):\n        if i >= batch_num:\n            break\n        image = data[\"image\"]\n        image_shape = data[\"image_shape\"]\n\n        gt_boxes, gt_logits = network(image, input_shape)\n        gt_boxes, gt_logits = gt_boxes.asnumpy(), gt_logits.asnumpy()\n        gt_labels = np.argmax(gt_logits, axis=2)\n\n        adv_img = attack.generate((image.asnumpy(), image_shape.asnumpy()), (gt_boxes, gt_labels))\n        adv_example.append(adv_img)\n    np.save('adv_example.npy', adv_example)\n\n\nif __name__ == \"__main__\":\n    test()\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/yolov3_darknet53/src/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/yolov3_darknet53/src/config.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n# ============================================================================\r\n\"\"\"Config parameters for Darknet based yolov3_darknet53 models.\"\"\"\r\n\r\n\r\nclass ConfigYOLOV3DarkNet53:\r\n    \"\"\"\r\n    Config parameters for the yolov3_darknet53.\r\n\r\n    Examples:\r\n        ConfigYOLOV3DarkNet53()\r\n    \"\"\"\r\n    # train_param\r\n    # data augmentation related\r\n    hue = 0.1\r\n    saturation = 1.5\r\n    value = 1.5\r\n    jitter = 0.3\r\n\r\n    resize_rate = 1\r\n    multi_scale = [[320, 320],\r\n                   [352, 352],\r\n                   [384, 384],\r\n                   [416, 416],\r\n                   [448, 448],\r\n                   [480, 480],\r\n                   [512, 512],\r\n                   [544, 544],\r\n                   [576, 576],\r\n                   [608, 608]\r\n                   ]\r\n\r\n    num_classes = 80\r\n    max_box = 50\r\n\r\n    backbone_input_shape = [32, 64, 128, 256, 512]\r\n    backbone_shape = [64, 128, 256, 512, 1024]\r\n    backbone_layers = [1, 2, 8, 8, 4]\r\n\r\n    # confidence under ignore_threshold means no object when training\r\n    ignore_threshold = 0.7\r\n\r\n    # h->w\r\n    anchor_scales = [(10, 13),\r\n                     (16, 30),\r\n                     (33, 23),\r\n                     (30, 61),\r\n                     (62, 45),\r\n                     (59, 119),\r\n                     (116, 90),\r\n                     (156, 198),\r\n                     (373, 326)]\r\n    out_channel = 255\r\n\r\n    # test_param\r\n    test_img_shape = [416, 416]\r\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/yolov3_darknet53/src/convert_weight.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"Convert weight to mindspore ckpt.\"\"\"\nimport os\nimport argparse\nimport numpy as np\nfrom mindspore.train.serialization import save_checkpoint\nfrom mindspore import Tensor\n\nfrom src.yolo import YOLOV3DarkNet53\n\ndef load_weight(weights_file):\n    \"\"\"Loads pre-trained weights.\"\"\"\n    if not os.path.isfile(weights_file):\n        raise ValueError(f'\"{weights_file}\" is not a valid weight file.')\n    with open(weights_file, 'rb') as fp:\n        np.fromfile(fp, dtype=np.int32, count=5)\n        return np.fromfile(fp, dtype=np.float32)\n\n\ndef build_network():\n    \"\"\"Build YOLOv3 network.\"\"\"\n    network = YOLOV3DarkNet53(is_training=True)\n    params = network.get_parameters()\n    params = [p for p in params if 'backbone' in p.name]\n    return params\n\n\ndef convert(weights_file, output_file):\n    \"\"\"Conver weight to mindspore ckpt.\"\"\"\n    params = build_network()\n    weights = load_weight(weights_file)\n    index = 0\n    param_list = []\n    for i in range(0, len(params), 5):\n        weight = params[i]\n        mean = params[i+1]\n        var = params[i+2]\n        gamma = params[i+3]\n        beta = params[i+4]\n        beta_data = weights[index: index+beta.size()].reshape(beta.shape)\n        index += beta.size()\n        gamma_data = weights[index: index+gamma.size()].reshape(gamma.shape)\n        index += gamma.size()\n        mean_data = weights[index: index+mean.size()].reshape(mean.shape)\n        index += mean.size()\n        var_data = weights[index: index + var.size()].reshape(var.shape)\n        index += var.size()\n        weight_data = weights[index: index+weight.size()].reshape(weight.shape)\n        index += weight.size()\n\n        param_list.append({'name': weight.name, 'type': weight.dtype, 'shape': weight.shape,\n                           'data': Tensor(weight_data)})\n        param_list.append({'name': mean.name, 'type': mean.dtype, 'shape': mean.shape, 'data': Tensor(mean_data)})\n        param_list.append({'name': var.name, 'type': var.dtype, 'shape': var.shape, 'data': Tensor(var_data)})\n        param_list.append({'name': gamma.name, 'type': gamma.dtype, 'shape': gamma.shape, 'data': Tensor(gamma_data)})\n        param_list.append({'name': beta.name, 'type': beta.dtype, 'shape': beta.shape, 'data': Tensor(beta_data)})\n\n    save_checkpoint(param_list, output_file)\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(description=\"yolov3 weight convert.\")\n    parser.add_argument(\"--input_file\", type=str, default=\"./darknet53.conv.74\", help=\"input file path.\")\n    parser.add_argument(\"--output_file\", type=str, default=\"./ackbone_darknet53.ckpt\", help=\"output file path.\")\n    args_opt = parser.parse_args()\n\n    convert(args_opt.input_file, args_opt.output_file)\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/yolov3_darknet53/src/darknet.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n# ============================================================================\r\n\"\"\"DarkNet model.\"\"\"\r\nimport mindspore.nn as nn\r\nfrom mindspore.ops import operations as P\r\n\r\n# pylint: disable=locally-disables, missing-docstring\r\n\r\n\r\ndef conv_block(in_channels,\r\n               out_channels,\r\n               kernel_size,\r\n               stride,\r\n               dilation=1):\r\n    \"\"\"Get a conv2d batchnorm and relu layer\"\"\"\r\n    pad_mode = 'same'\r\n    padding = 0\r\n\r\n    return nn.SequentialCell(\r\n        [nn.Conv2d(in_channels,\r\n                   out_channels,\r\n                   kernel_size=kernel_size,\r\n                   stride=stride,\r\n                   padding=padding,\r\n                   dilation=dilation,\r\n                   pad_mode=pad_mode),\r\n         nn.BatchNorm2d(out_channels, momentum=0.1),\r\n         nn.ReLU()]\r\n    )\r\n\r\n\r\nclass ResidualBlock(nn.Cell):\r\n    \"\"\"\r\n    DarkNet V1 residual block definition.\r\n\r\n    Args:\r\n        in_channels: Integer. Input channel.\r\n        out_channels: Integer. Output channel.\r\n\r\n    Returns:\r\n        Tensor, output tensor.\r\n    Examples:\r\n        ResidualBlock(3, 208)\r\n    \"\"\"\r\n    expansion = 4\r\n\r\n    def __init__(self,\r\n                 in_channels,\r\n                 out_channels):\r\n\r\n        super(ResidualBlock, self).__init__()\r\n        out_chls = out_channels//2\r\n        self.conv1 = conv_block(in_channels, out_chls, kernel_size=1, stride=1)\r\n        self.conv2 = conv_block(out_chls, out_channels, kernel_size=3, stride=1)\r\n        self.add = P.Add()\r\n\r\n    def construct(self, x):\r\n        identity = x\r\n        out = self.conv1(x)\r\n        out = self.conv2(out)\r\n        out = self.add(out, identity)\r\n\r\n        return out\r\n\r\n\r\nclass DarkNet(nn.Cell):\r\n    \"\"\"\r\n    DarkNet V1 network.\r\n\r\n    Args:\r\n        block: Cell. Block for network.\r\n        layer_nums: List. Numbers of different layers.\r\n        in_channels: Integer. Input channel.\r\n        out_channels: Integer. Output channel.\r\n        detect: Bool. Whether detect or not. Default:False.\r\n\r\n    Returns:\r\n        Tuple, tuple of output tensor,(f1,f2,f3,f4,f5).\r\n\r\n    Examples:\r\n        DarkNet(ResidualBlock,\r\n               [1, 2, 8, 8, 4],\r\n               [32, 64, 128, 256, 512],\r\n               [64, 128, 256, 512, 1024],\r\n               100)\r\n    \"\"\"\r\n    def __init__(self,\r\n                 block,\r\n                 layer_nums,\r\n                 in_channels,\r\n                 out_channels,\r\n                 detect=False):\r\n        super(DarkNet, self).__init__()\r\n\r\n        self.outchannel = out_channels[-1]\r\n        self.detect = detect\r\n\r\n        if not len(layer_nums) == len(in_channels) == len(out_channels) == 5:\r\n            raise ValueError(\"the length of layer_num, inchannel, outchannel list must be 5!\")\r\n        self.conv0 = conv_block(3,\r\n                                in_channels[0],\r\n                                kernel_size=3,\r\n                                stride=1)\r\n        self.conv1 = conv_block(in_channels[0],\r\n                                out_channels[0],\r\n                                kernel_size=3,\r\n                                stride=2)\r\n        self.layer1 = self._make_layer(block,\r\n                                       layer_nums[0],\r\n                                       in_channel=out_channels[0],\r\n                                       out_channel=out_channels[0])\r\n        self.conv2 = conv_block(in_channels[1],\r\n                                out_channels[1],\r\n                                kernel_size=3,\r\n                                stride=2)\r\n        self.layer2 = self._make_layer(block,\r\n                                       layer_nums[1],\r\n                                       in_channel=out_channels[1],\r\n                                       out_channel=out_channels[1])\r\n        self.conv3 = conv_block(in_channels[2],\r\n                                out_channels[2],\r\n                                kernel_size=3,\r\n                                stride=2)\r\n        self.layer3 = self._make_layer(block,\r\n                                       layer_nums[2],\r\n                                       in_channel=out_channels[2],\r\n                                       out_channel=out_channels[2])\r\n        self.conv4 = conv_block(in_channels[3],\r\n                                out_channels[3],\r\n                                kernel_size=3,\r\n                                stride=2)\r\n        self.layer4 = self._make_layer(block,\r\n                                       layer_nums[3],\r\n                                       in_channel=out_channels[3],\r\n                                       out_channel=out_channels[3])\r\n        self.conv5 = conv_block(in_channels[4],\r\n                                out_channels[4],\r\n                                kernel_size=3,\r\n                                stride=2)\r\n        self.layer5 = self._make_layer(block,\r\n                                       layer_nums[4],\r\n                                       in_channel=out_channels[4],\r\n                                       out_channel=out_channels[4])\r\n\r\n    def _make_layer(self, block, layer_num, in_channel, out_channel):\r\n        \"\"\"\r\n        Make Layer for DarkNet.\r\n\r\n        :param block: Cell. DarkNet block.\r\n        :param layer_num: Integer. Layer number.\r\n        :param in_channel: Integer. Input channel.\r\n        :param out_channel: Integer. Output channel.\r\n\r\n        Examples:\r\n            _make_layer(ConvBlock, 1, 128, 256)\r\n        \"\"\"\r\n        layers = []\r\n        darkblk = block(in_channel, out_channel)\r\n        layers.append(darkblk)\r\n\r\n        for _ in range(1, layer_num):\r\n            darkblk = block(out_channel, out_channel)\r\n            layers.append(darkblk)\r\n\r\n        return nn.SequentialCell(layers)\r\n\r\n    def construct(self, x):\r\n        c1 = self.conv0(x)\r\n        c2 = self.conv1(c1)\r\n        c3 = self.layer1(c2)\r\n        c4 = self.conv2(c3)\r\n        c5 = self.layer2(c4)\r\n        c6 = self.conv3(c5)\r\n        c7 = self.layer3(c6)\r\n        c8 = self.conv4(c7)\r\n        c9 = self.layer4(c8)\r\n        c10 = self.conv5(c9)\r\n        c11 = self.layer5(c10)\r\n        if self.detect:\r\n            return c7, c9, c11\r\n\r\n        return c11\r\n\r\n    def get_out_channels(self):\r\n        return self.outchannel\r\n\r\n\r\ndef darknet53():\r\n    \"\"\"\r\n    Get DarkNet53 neural network.\r\n\r\n    Returns:\r\n        Cell, cell instance of DarkNet53 neural network.\r\n\r\n    Examples:\r\n        darknet53()\r\n    \"\"\"\r\n    return DarkNet(ResidualBlock, [1, 2, 8, 8, 4],\r\n                   [32, 64, 128, 256, 512],\r\n                   [64, 128, 256, 512, 1024])\r\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/yolov3_darknet53/src/distributed_sampler.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n# ============================================================================\r\n\"\"\"Yolo dataset distributed sampler.\"\"\"\r\nfrom __future__ import division\r\nimport math\r\nimport numpy as np\r\n\r\n\r\nclass DistributedSampler:\r\n    \"\"\"Distributed sampler.\"\"\"\r\n    def __init__(self, dataset_size, num_replicas=None, rank=None, shuffle=True):\r\n        if num_replicas is None:\r\n            print(\"***********Setting world_size to 1 since it is not passed in ******************\")\r\n            num_replicas = 1\r\n        if rank is None:\r\n            print(\"***********Setting rank to 0 since it is not passed in ******************\")\r\n            rank = 0\r\n        self.dataset_size = dataset_size\r\n        self.num_replicas = num_replicas\r\n        self.rank = rank\r\n        self.epoch = 0\r\n        self.num_samples = int(math.ceil(dataset_size * 1.0 / self.num_replicas))\r\n        self.total_size = self.num_samples * self.num_replicas\r\n        self.shuffle = shuffle\r\n\r\n    def __iter__(self):\r\n        # deterministically shuffle based on epoch\r\n        if self.shuffle:\r\n            indices = np.random.RandomState(seed=self.epoch).permutation(self.dataset_size)\r\n            # np.array type. number from 0 to len(dataset_size)-1, used as index of dataset\r\n            indices = indices.tolist()\r\n            self.epoch += 1\r\n            # change to list type\r\n        else:\r\n            indices = list(range(self.dataset_size))\r\n\r\n        # add extra samples to make it evenly divisible\r\n        indices += indices[:(self.total_size - len(indices))]\r\n        assert len(indices) == self.total_size\r\n\r\n        # subsample\r\n        indices = indices[self.rank:self.total_size:self.num_replicas]\r\n        assert len(indices) == self.num_samples\r\n\r\n        return iter(indices)\r\n\r\n    def __len__(self):\r\n        return self.num_samples\r\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/yolov3_darknet53/src/initializer.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"Parameter init.\"\"\"\nimport math\nfrom functools import reduce\nimport numpy as np\nfrom mindspore.common import initializer as init\nfrom mindspore.common.initializer import Initializer as MeInitializer\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nimport mindspore.nn as nn\nfrom .util import load_backbone\n\ndef calculate_gain(nonlinearity, param=None):\n    r\"\"\"Return the recommended gain value for the given nonlinearity function.\n    The values are as follows:\n\n    ================= ====================================================\n    nonlinearity      gain\n    ================= ====================================================\n    Linear / Identity :math:`1`\n    Conv{1,2,3}D      :math:`1`\n    Sigmoid           :math:`1`\n    Tanh              :math:`\\frac{5}{3}`\n    ReLU              :math:`\\sqrt{2}`\n    Leaky Relu        :math:`\\sqrt{\\frac{2}{1 + \\text{negative\\_slope}^2}}`\n    ================= ====================================================\n\n    Args:\n        nonlinearity: the non-linear function (`nn.functional` name)\n        param: optional parameter for the non-linear function\n\n    Examples:\n        >>> gain = nn.init.calculate_gain('leaky_relu', 0.2)  # leaky_relu with negative_slope=0.2\n    \"\"\"\n    linear_fns = ['linear', 'conv1d', 'conv2d', 'conv3d', 'conv_transpose1d', 'conv_transpose2d', 'conv_transpose3d']\n    if nonlinearity in linear_fns or nonlinearity == 'sigmoid':\n        return 1\n    if nonlinearity == 'tanh':\n        return 5.0 / 3\n    if nonlinearity == 'relu':\n        return math.sqrt(2.0)\n    if nonlinearity == 'leaky_relu':\n        if param is None:\n            negative_slope = 0.01\n        elif not isinstance(param, bool) and isinstance(param, int) or isinstance(param, float):\n            # True/False are instances of int, hence check above\n            negative_slope = param\n        else:\n            raise ValueError(\"negative_slope {} not a valid number\".format(param))\n        return math.sqrt(2.0 / (1 + negative_slope ** 2))\n\n    raise ValueError(\"Unsupported nonlinearity {}\".format(nonlinearity))\n\n\ndef _assignment(arr, num):\n    \"\"\"Assign the value of 'num' and 'arr'.\"\"\"\n    if arr.shape == ():\n        arr = arr.reshape((1))\n        arr[:] = num\n        arr = arr.reshape(())\n    else:\n        if isinstance(num, np.ndarray):\n            arr[:] = num[:]\n        else:\n            arr[:] = num\n    return arr\n\n\ndef _calculate_correct_fan(array, mode):\n    mode = mode.lower()\n    valid_modes = ['fan_in', 'fan_out']\n    if mode not in valid_modes:\n        raise ValueError(\"Mode {} not supported, please use one of {}\".format(mode, valid_modes))\n\n    fan_in, fan_out = _calculate_fan_in_and_fan_out(array)\n    return fan_in if mode == 'fan_in' else fan_out\n\n\ndef kaiming_uniform_(arr, a=0, mode='fan_in', nonlinearity='leaky_relu'):\n    r\"\"\"Fills the input `Tensor` with values according to the method\n    described in `Delving deep into rectifiers: Surpassing human-level\n    performance on ImageNet classification` - He, K. et al. (2015), using a\n    uniform distribution. The resulting tensor will have values sampled from\n    :math:`\\mathcal{U}(-\\text{bound}, \\text{bound})` where\n\n    .. math::\n        \\text{bound} = \\text{gain} \\times \\sqrt{\\frac{3}{\\text{fan\\_mode}}}\n\n    Also known as He initialization.\n\n    Args:\n        tensor: an n-dimensional `Tensor`\n        a: the negative slope of the rectifier used after this layer (only\n        used with ``'leaky_relu'``)\n        mode: either ``'fan_in'`` (default) or ``'fan_out'``. Choosing ``'fan_in'``\n            preserves the magnitude of the variance of the weights in the\n            forward pass. Choosing ``'fan_out'`` preserves the magnitudes in the\n            backwards pass.\n        nonlinearity: the non-linear function (`nn.functional` name),\n            recommended to use only with ``'relu'`` or ``'leaky_relu'`` (default).\n\n    Examples:\n        >>> w = np.empty(3, 5)\n        >>> nn.init.kaiming_uniform_(w, mode='fan_in', nonlinearity='relu')\n    \"\"\"\n    fan = _calculate_correct_fan(arr, mode)\n    gain = calculate_gain(nonlinearity, a)\n    std = gain / math.sqrt(fan)\n    bound = math.sqrt(3.0) * std  # Calculate uniform bounds from standard deviation\n    return np.random.uniform(-bound, bound, arr.shape)\n\n\ndef _calculate_fan_in_and_fan_out(arr):\n    \"\"\"Calculate fan in and fan out.\"\"\"\n    dimensions = len(arr.shape)\n    if dimensions < 2:\n        raise ValueError(\"Fan in and fan out can not be computed for array with fewer than 2 dimensions\")\n\n    num_input_fmaps = arr.shape[1]\n    num_output_fmaps = arr.shape[0]\n    receptive_field_size = 1\n    if dimensions > 2:\n        receptive_field_size = reduce(lambda x, y: x * y, arr.shape[2:])\n    fan_in = num_input_fmaps * receptive_field_size\n    fan_out = num_output_fmaps * receptive_field_size\n\n    return fan_in, fan_out\n\n\nclass KaimingUniform(MeInitializer):\n    \"\"\"Kaiming uniform initializer.\"\"\"\n    def __init__(self, a=0, mode='fan_in', nonlinearity='leaky_relu'):\n        super(KaimingUniform, self).__init__()\n        self.a = a\n        self.mode = mode\n        self.nonlinearity = nonlinearity\n\n    def _initialize(self, arr):\n        tmp = kaiming_uniform_(arr, self.a, self.mode, self.nonlinearity)\n        _assignment(arr, tmp)\n\n\ndef default_recurisive_init(custom_cell):\n    \"\"\"Initialize parameter.\"\"\"\n    for _, cell in custom_cell.cells_and_names():\n        if isinstance(cell, nn.Conv2d):\n            cell.weight.set_data(init.initializer(KaimingUniform(a=math.sqrt(5)),\n                                                  cell.weight.shape,\n                                                  cell.weight.dtype))\n            if cell.bias is not None:\n                fan_in, _ = _calculate_fan_in_and_fan_out(cell.weight)\n                bound = 1 / math.sqrt(fan_in)\n                cell.bias.set_data(init.initializer(init.Uniform(bound),\n                                                    cell.bias.shape,\n                                                    cell.bias.dtype))\n        elif isinstance(cell, nn.Dense):\n            cell.weight.set_data(init.initializer(KaimingUniform(a=math.sqrt(5)),\n                                                  cell.weight.shape,\n                                                  cell.weight.dtype))\n            if cell.bias is not None:\n                fan_in, _ = _calculate_fan_in_and_fan_out(cell.weight)\n                bound = 1 / math.sqrt(fan_in)\n                cell.bias.set_data(init.initializer(init.Uniform(bound),\n                                                    cell.bias.shape,\n                                                    cell.bias.dtype))\n        elif isinstance(cell, (nn.BatchNorm2d, nn.BatchNorm1d)):\n            pass\n\ndef load_yolov3_params(args, network):\n    \"\"\"Load yolov3 darknet parameter from checkpoint.\"\"\"\n    if args.pretrained_backbone:\n        network = load_backbone(network, args.pretrained_backbone, args)\n        args.logger.info('load pre-trained backbone {} into network'.format(args.pretrained_backbone))\n    else:\n        args.logger.info('Not load pre-trained backbone, please be careful')\n\n    if args.resume_yolov3:\n        param_dict = load_checkpoint(args.resume_yolov3)\n        param_dict_new = {}\n        for key, values in param_dict.items():\n            if key.startswith('moments.'):\n                continue\n            elif key.startswith('yolo_network.'):\n                param_dict_new[key[13:]] = values\n                args.logger.info('in resume {}'.format(key))\n            else:\n                param_dict_new[key] = values\n                args.logger.info('in resume {}'.format(key))\n\n        args.logger.info('resume finished')\n        load_param_into_net(network, param_dict_new)\n        args.logger.info('load_model {} success'.format(args.resume_yolov3))\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/yolov3_darknet53/src/logger.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"Custom Logger.\"\"\"\nimport os\nimport sys\nimport logging\nfrom datetime import datetime\n\n\nclass LOGGER(logging.Logger):\n    \"\"\"\n    Logger.\n\n    Args:\n         logger_name: String. Logger name.\n         rank: Integer. Rank id.\n    \"\"\"\n    def __init__(self, logger_name, rank=0):\n        super(LOGGER, self).__init__(logger_name)\n        self.rank = rank\n        if rank % 8 == 0:\n            console = logging.StreamHandler(sys.stdout)\n            console.setLevel(logging.INFO)\n            formatter = logging.Formatter('%(asctime)s:%(levelname)s:%(message)s')\n            console.setFormatter(formatter)\n            self.addHandler(console)\n\n    def setup_logging_file(self, log_dir, rank=0):\n        \"\"\"Setup logging file.\"\"\"\n        self.rank = rank\n        if not os.path.exists(log_dir):\n            os.makedirs(log_dir, exist_ok=True)\n        log_name = datetime.now().strftime('%Y-%m-%d_time_%H_%M_%S') + '_rank_{}.log'.format(rank)\n        self.log_fn = os.path.join(log_dir, log_name)\n        fh = logging.FileHandler(self.log_fn)\n        fh.setLevel(logging.INFO)\n        formatter = logging.Formatter('%(asctime)s:%(levelname)s:%(message)s')\n        fh.setFormatter(formatter)\n        self.addHandler(fh)\n\n    def info(self, msg, *args, **kwargs):\n        if self.isEnabledFor(logging.INFO):\n            self._log(logging.INFO, msg, args, **kwargs)\n\n    def save_args(self, args):\n        self.info('Args:')\n        args_dict = vars(args)\n        for key in args_dict.keys():\n            self.info('--> %s: %s', key, args_dict[key])\n        self.info('')\n\n\ndef get_logger(path, rank):\n    \"\"\"Get Logger.\"\"\"\n    logger = LOGGER('yolov3_darknet53', rank)\n    logger.setup_logging_file(path, rank)\n    return logger\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/yolov3_darknet53/src/loss.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"YOLOV3 loss.\"\"\"\nfrom mindspore.ops import operations as P\nimport mindspore.nn as nn\n\n\nclass XYLoss(nn.Cell):\n    \"\"\"Loss for x and y.\"\"\"\n    def __init__(self):\n        super(XYLoss, self).__init__()\n        self.cross_entropy = P.SigmoidCrossEntropyWithLogits()\n        self.reduce_sum = P.ReduceSum()\n\n    def construct(self, object_mask, box_loss_scale, predict_xy, true_xy):\n        xy_loss = object_mask * box_loss_scale * self.cross_entropy(predict_xy, true_xy)\n        xy_loss = self.reduce_sum(xy_loss, ())\n        return xy_loss\n\n\nclass WHLoss(nn.Cell):\n    \"\"\"Loss for w and h.\"\"\"\n    def __init__(self):\n        super(WHLoss, self).__init__()\n        self.square = P.Square()\n        self.reduce_sum = P.ReduceSum()\n\n    def construct(self, object_mask, box_loss_scale, predict_wh, true_wh):\n        wh_loss = object_mask * box_loss_scale * 0.5 * P.Square()(true_wh - predict_wh)\n        wh_loss = self.reduce_sum(wh_loss, ())\n        return wh_loss\n\n\nclass ConfidenceLoss(nn.Cell):\n    \"\"\"Loss for confidence.\"\"\"\n    def __init__(self):\n        super(ConfidenceLoss, self).__init__()\n        self.cross_entropy = P.SigmoidCrossEntropyWithLogits()\n        self.reduce_sum = P.ReduceSum()\n\n    def construct(self, object_mask, predict_confidence, ignore_mask):\n        confidence_loss = self.cross_entropy(predict_confidence, object_mask)\n        confidence_loss = object_mask * confidence_loss + (1 - object_mask) * confidence_loss * ignore_mask\n        confidence_loss = self.reduce_sum(confidence_loss, ())\n        return confidence_loss\n\n\nclass ClassLoss(nn.Cell):\n    \"\"\"Loss for classification.\"\"\"\n    def __init__(self):\n        super(ClassLoss, self).__init__()\n        self.cross_entropy = P.SigmoidCrossEntropyWithLogits()\n        self.reduce_sum = P.ReduceSum()\n\n    def construct(self, object_mask, predict_class, class_probs):\n        class_loss = object_mask * self.cross_entropy(predict_class, class_probs)\n        class_loss = self.reduce_sum(class_loss, ())\n        return class_loss\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/yolov3_darknet53/src/lr_scheduler.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"Learning rate scheduler.\"\"\"\nimport math\nfrom collections import Counter\n\nimport numpy as np\n\n# pylint: disable=locally-disables, invalid-name\n\n\ndef linear_warmup_lr(current_step, warmup_steps, base_lr, init_lr):\n    \"\"\"Linear learning rate.\"\"\"\n    lr_inc = (float(base_lr) - float(init_lr)) / float(warmup_steps)\n    lr = float(init_lr) + lr_inc * current_step\n    return lr\n\n\ndef warmup_step_lr(lr, lr_epochs, steps_per_epoch, warmup_epochs, max_epoch, gamma=0.1):\n    \"\"\"Warmup step learning rate.\"\"\"\n    base_lr = lr\n    warmup_init_lr = 0\n    total_steps = int(max_epoch * steps_per_epoch)\n    warmup_steps = int(warmup_epochs * steps_per_epoch)\n    milestones = lr_epochs\n    milestones_steps = []\n    for milestone in milestones:\n        milestones_step = milestone * steps_per_epoch\n        milestones_steps.append(milestones_step)\n\n    lr_each_step = []\n    lr = base_lr\n    milestones_steps_counter = Counter(milestones_steps)\n    for i in range(total_steps):\n        if i < warmup_steps:\n            lr = linear_warmup_lr(i + 1, warmup_steps, base_lr, warmup_init_lr)\n        else:\n            lr = lr * gamma**milestones_steps_counter[i]\n        lr_each_step.append(lr)\n\n    return np.array(lr_each_step).astype(np.float32)\n\n\ndef multi_step_lr(lr, milestones, steps_per_epoch, max_epoch, gamma=0.1):\n    return warmup_step_lr(lr, milestones, steps_per_epoch, 0, max_epoch, gamma=gamma)\n\n\ndef step_lr(lr, epoch_size, steps_per_epoch, max_epoch, gamma=0.1):\n    lr_epochs = []\n    for i in range(1, max_epoch):\n        if i % epoch_size == 0:\n            lr_epochs.append(i)\n    return multi_step_lr(lr, lr_epochs, steps_per_epoch, max_epoch, gamma=gamma)\n\n\ndef warmup_cosine_annealing_lr(lr, steps_per_epoch, warmup_epochs, max_epoch, T_max, eta_min=0):\n    \"\"\"Cosine annealing learning rate.\"\"\"\n    base_lr = lr\n    warmup_init_lr = 0\n    total_steps = int(max_epoch * steps_per_epoch)\n    warmup_steps = int(warmup_epochs * steps_per_epoch)\n\n    lr_each_step = []\n    for i in range(total_steps):\n        last_epoch = i // steps_per_epoch\n        if i < warmup_steps:\n            lr = linear_warmup_lr(i + 1, warmup_steps, base_lr, warmup_init_lr)\n        else:\n            lr = eta_min + (base_lr - eta_min) * (1. + math.cos(math.pi*last_epoch / T_max)) / 2\n        lr_each_step.append(lr)\n\n    return np.array(lr_each_step).astype(np.float32)\n\n\ndef warmup_cosine_annealing_lr_V2(lr, steps_per_epoch, warmup_epochs, max_epoch, T_max, eta_min=0):\n    \"\"\"Cosine annealing learning rate V2.\"\"\"\n    base_lr = lr\n    warmup_init_lr = 0\n    total_steps = int(max_epoch * steps_per_epoch)\n    warmup_steps = int(warmup_epochs * steps_per_epoch)\n\n    last_lr = 0\n    last_epoch_V1 = 0\n\n    T_max_V2 = int(max_epoch*1/3)\n\n    lr_each_step = []\n    for i in range(total_steps):\n        last_epoch = i // steps_per_epoch\n        if i < warmup_steps:\n            lr = linear_warmup_lr(i + 1, warmup_steps, base_lr, warmup_init_lr)\n        else:\n            if i < total_steps*2/3:\n                lr = eta_min + (base_lr - eta_min) * (1. + math.cos(math.pi*last_epoch / T_max)) / 2\n                last_lr = lr\n                last_epoch_V1 = last_epoch\n            else:\n                base_lr = last_lr\n                last_epoch = last_epoch-last_epoch_V1\n                lr = eta_min + (base_lr - eta_min) * (1. + math.cos(math.pi * last_epoch / T_max_V2)) / 2\n\n        lr_each_step.append(lr)\n    return np.array(lr_each_step).astype(np.float32)\n\n\ndef warmup_cosine_annealing_lr_sample(lr, steps_per_epoch, warmup_epochs, max_epoch, T_max, eta_min=0):\n    \"\"\"Warmup cosine annealing learning rate.\"\"\"\n    start_sample_epoch = 60\n    step_sample = 2\n    tobe_sampled_epoch = 60\n    end_sampled_epoch = start_sample_epoch + step_sample*tobe_sampled_epoch\n    max_sampled_epoch = max_epoch+tobe_sampled_epoch\n    T_max = max_sampled_epoch\n\n    base_lr = lr\n    warmup_init_lr = 0\n    total_steps = int(max_epoch * steps_per_epoch)\n    total_sampled_steps = int(max_sampled_epoch * steps_per_epoch)\n    warmup_steps = int(warmup_epochs * steps_per_epoch)\n\n    lr_each_step = []\n\n    for i in range(total_sampled_steps):\n        last_epoch = i // steps_per_epoch\n        if last_epoch in range(start_sample_epoch, end_sampled_epoch, step_sample):\n            continue\n        if i < warmup_steps:\n            lr = linear_warmup_lr(i + 1, warmup_steps, base_lr, warmup_init_lr)\n        else:\n            lr = eta_min + (base_lr - eta_min) * (1. + math.cos(math.pi*last_epoch / T_max)) / 2\n        lr_each_step.append(lr)\n\n    assert total_steps == len(lr_each_step)\n    return np.array(lr_each_step).astype(np.float32)\n\n\ndef get_lr(args):\n    \"\"\"generate learning rate.\"\"\"\n    if args.lr_scheduler == 'exponential':\n        lr = warmup_step_lr(args.lr,\n                            args.lr_epochs,\n                            args.steps_per_epoch,\n                            args.warmup_epochs,\n                            args.max_epoch,\n                            gamma=args.lr_gamma,\n                            )\n    elif args.lr_scheduler == 'cosine_annealing':\n        lr = warmup_cosine_annealing_lr(args.lr,\n                                        args.steps_per_epoch,\n                                        args.warmup_epochs,\n                                        args.max_epoch,\n                                        args.T_max,\n                                        args.eta_min)\n    elif args.lr_scheduler == 'cosine_annealing_V2':\n        lr = warmup_cosine_annealing_lr_V2(args.lr,\n                                           args.steps_per_epoch,\n                                           args.warmup_epochs,\n                                           args.max_epoch,\n                                           args.T_max,\n                                           args.eta_min)\n    elif args.lr_scheduler == 'cosine_annealing_sample':\n        lr = warmup_cosine_annealing_lr_sample(args.lr,\n                                               args.steps_per_epoch,\n                                               args.warmup_epochs,\n                                               args.max_epoch,\n                                               args.T_max,\n                                               args.eta_min)\n    else:\n        raise NotImplementedError(args.lr_scheduler)\n    return lr\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/yolov3_darknet53/src/transforms.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n# ============================================================================\r\n\"\"\"Preprocess dataset.\"\"\"\r\nimport random\r\nimport threading\r\nimport copy\r\n\r\nimport numpy as np\r\nfrom PIL import Image\r\nimport cv2\r\n\r\n# pylint: disable=locally-disables, unused-argument, invalid-name\r\n\r\n\r\ndef _rand(a=0., b=1.):\r\n    return np.random.rand() * (b - a) + a\r\n\r\n\r\ndef bbox_iou(bbox_a, bbox_b, offset=0):\r\n    \"\"\"Calculate Intersection-Over-Union(IOU) of two bounding boxes.\r\n\r\n    Parameters\r\n    ----------\r\n    bbox_a : numpy.ndarray\r\n        An ndarray with shape :math:`(N, 4)`.\r\n    bbox_b : numpy.ndarray\r\n        An ndarray with shape :math:`(M, 4)`.\r\n    offset : float or int, default is 0\r\n        The ``offset`` is used to control the whether the width(or height) is computed as\r\n        (right - left + ``offset``).\r\n        Note that the offset must be 0 for normalized bboxes, whose ranges are in ``[0, 1]``.\r\n\r\n    Returns\r\n    -------\r\n    numpy.ndarray\r\n        An ndarray with shape :math:`(N, M)` indicates IOU between each pairs of\r\n        bounding boxes in `bbox_a` and `bbox_b`.\r\n\r\n    \"\"\"\r\n    if bbox_a.shape[1] < 4 or bbox_b.shape[1] < 4:\r\n        raise IndexError(\"Bounding boxes axis 1 must have at least length 4\")\r\n\r\n    tl = np.maximum(bbox_a[:, None, :2], bbox_b[:, :2])\r\n    br = np.minimum(bbox_a[:, None, 2:4], bbox_b[:, 2:4])\r\n\r\n    area_i = np.prod(br - tl + offset, axis=2) * (tl < br).all(axis=2)\r\n    area_a = np.prod(bbox_a[:, 2:4] - bbox_a[:, :2] + offset, axis=1)\r\n    area_b = np.prod(bbox_b[:, 2:4] - bbox_b[:, :2] + offset, axis=1)\r\n    return area_i / (area_a[:, None] + area_b - area_i)\r\n\r\n\r\ndef statistic_normalize_img(img, statistic_norm):\r\n    \"\"\"Statistic normalize images.\"\"\"\r\n    # img: RGB\r\n    if isinstance(img, Image.Image):\r\n        img = np.array(img)\r\n    img = img/255.\r\n    mean = np.array([0.485, 0.456, 0.406])\r\n    std = np.array([0.229, 0.224, 0.225])\r\n    if statistic_norm:\r\n        img = (img - mean) / std\r\n    return img\r\n\r\n\r\ndef get_interp_method(interp, sizes=()):\r\n    \"\"\"\r\n    Get the interpolation method for resize functions.\r\n    The major purpose of this function is to wrap a random interp method selection\r\n    and a auto-estimation method.\r\n\r\n    Note:\r\n        When shrinking an image, it will generally look best with AREA-based\r\n        interpolation, whereas, when enlarging an image, it will generally look best\r\n        with Bicubic or Bilinear.\r\n\r\n    Args:\r\n        interp (int): Interpolation method for all resizing operations.\r\n\r\n            - 0: Nearest Neighbors Interpolation.\r\n            - 1: Bilinear interpolation.\r\n            - 2: Bicubic interpolation over 4x4 pixel neighborhood.\r\n            - 3: Nearest Neighbors. Originally it should be Area-based, as we cannot find Area-based,\r\n              so we use NN instead. Area-based (resampling using pixel area relation).\r\n              It may be a preferred method for image decimation, as it gives moire-free results.\r\n              But when the image is zoomed, it is similar to the Nearest Neighbors method. (used by default).\r\n            - 4: Lanczos interpolation over 8x8 pixel neighborhood.\r\n            - 9: Cubic for enlarge, area for shrink, bilinear for others.\r\n            - 10: Random select from interpolation method mentioned above.\r\n\r\n        sizes (tuple): Format should like (old_height, old_width, new_height, new_width),\r\n            if None provided, auto(9) will return Area(2) anyway. Default: ()\r\n\r\n    Returns:\r\n        int, interp method from 0 to 4.\r\n    \"\"\"\r\n    if interp == 9:\r\n        if sizes:\r\n            assert len(sizes) == 4\r\n            oh, ow, nh, nw = sizes\r\n            if nh > oh and nw > ow:\r\n                return 2\r\n            if nh < oh and nw < ow:\r\n                return 0\r\n            return 1\r\n        return 2\r\n    if interp == 10:\r\n        return random.randint(0, 4)\r\n    if interp not in (0, 1, 2, 3, 4):\r\n        raise ValueError('Unknown interp method %d' % interp)\r\n    return interp\r\n\r\n\r\ndef pil_image_reshape(interp):\r\n    \"\"\"Reshape pil image.\"\"\"\r\n    reshape_type = {\r\n        0: Image.NEAREST,\r\n        1: Image.BILINEAR,\r\n        2: Image.BICUBIC,\r\n        3: Image.NEAREST,\r\n        4: Image.LANCZOS,\r\n    }\r\n    return reshape_type[interp]\r\n\r\n\r\ndef _preprocess_true_boxes(true_boxes, anchors, in_shape, num_classes,\r\n                           max_boxes, label_smooth, label_smooth_factor=0.1):\r\n    \"\"\"Preprocess annotation boxes.\"\"\"\r\n    anchors = np.array(anchors)\r\n    num_layers = anchors.shape[0] // 3\r\n    anchor_mask = [[6, 7, 8], [3, 4, 5], [0, 1, 2]]\r\n    true_boxes = np.array(true_boxes, dtype='float32')\r\n    input_shape = np.array(in_shape, dtype='int32')\r\n    boxes_xy = (true_boxes[..., 0:2] + true_boxes[..., 2:4]) // 2.\r\n    # trans to box center point\r\n    boxes_wh = true_boxes[..., 2:4] - true_boxes[..., 0:2]\r\n    # input_shape is [h, w]\r\n    true_boxes[..., 0:2] = boxes_xy / input_shape[::-1]\r\n    true_boxes[..., 2:4] = boxes_wh / input_shape[::-1]\r\n    # true_boxes [x, y, w, h]\r\n\r\n    grid_shapes = [input_shape // 32, input_shape // 16, input_shape // 8]\r\n    # grid_shape [h, w]\r\n    y_true = [np.zeros((grid_shapes[l][0], grid_shapes[l][1], len(anchor_mask[l]),\r\n                        5 + num_classes), dtype='float32') for l in range(num_layers)]\r\n    # y_true [gridy, gridx]\r\n    anchors = np.expand_dims(anchors, 0)\r\n    anchors_max = anchors / 2.\r\n    anchors_min = -anchors_max\r\n    valid_mask = boxes_wh[..., 0] > 0\r\n\r\n    wh = boxes_wh[valid_mask]\r\n    if wh.size > 0:\r\n        wh = np.expand_dims(wh, -2)\r\n        boxes_max = wh / 2.\r\n        boxes_min = -boxes_max\r\n\r\n        intersect_min = np.maximum(boxes_min, anchors_min)\r\n        intersect_max = np.minimum(boxes_max, anchors_max)\r\n        intersect_wh = np.maximum(intersect_max - intersect_min, 0.)\r\n        intersect_area = intersect_wh[..., 0] * intersect_wh[..., 1]\r\n        box_area = wh[..., 0] * wh[..., 1]\r\n        anchor_area = anchors[..., 0] * anchors[..., 1]\r\n        iou = intersect_area / (box_area + anchor_area - intersect_area)\r\n\r\n        best_anchor = np.argmax(iou, axis=-1)\r\n        for t, n in enumerate(best_anchor):\r\n            for l in range(num_layers):\r\n                if n in anchor_mask[l]:\r\n                    i = np.floor(true_boxes[t, 0] * grid_shapes[l][1]).astype('int32')  # grid_y\r\n                    j = np.floor(true_boxes[t, 1] * grid_shapes[l][0]).astype('int32')  # grid_x\r\n\r\n                    k = anchor_mask[l].index(n)\r\n                    c = true_boxes[t, 4].astype('int32')\r\n                    y_true[l][j, i, k, 0:4] = true_boxes[t, 0:4]\r\n                    y_true[l][j, i, k, 4] = 1.\r\n\r\n                    # lable-smooth\r\n                    if label_smooth:\r\n                        sigma = label_smooth_factor/(num_classes-1)\r\n                        y_true[l][j, i, k, 5:] = sigma\r\n                        y_true[l][j, i, k, 5+c] = 1-label_smooth_factor\r\n                    else:\r\n                        y_true[l][j, i, k, 5 + c] = 1.\r\n\r\n    # pad_gt_boxes for avoiding dynamic shape\r\n    pad_gt_box0 = np.zeros(shape=[max_boxes, 4], dtype=np.float32)\r\n    pad_gt_box1 = np.zeros(shape=[max_boxes, 4], dtype=np.float32)\r\n    pad_gt_box2 = np.zeros(shape=[max_boxes, 4], dtype=np.float32)\r\n\r\n    mask0 = np.reshape(y_true[0][..., 4:5], [-1])\r\n    gt_box0 = np.reshape(y_true[0][..., 0:4], [-1, 4])\r\n    # gt_box [boxes, [x,y,w,h]]\r\n    gt_box0 = gt_box0[mask0 == 1]\r\n    # gt_box0: get all boxes which have object\r\n    pad_gt_box0[:gt_box0.shape[0]] = gt_box0\r\n    # gt_box0.shape[0]: total number of boxes in gt_box0\r\n    # top N of pad_gt_box0 is real box, and after are pad by zero\r\n\r\n    mask1 = np.reshape(y_true[1][..., 4:5], [-1])\r\n    gt_box1 = np.reshape(y_true[1][..., 0:4], [-1, 4])\r\n    gt_box1 = gt_box1[mask1 == 1]\r\n    pad_gt_box1[:gt_box1.shape[0]] = gt_box1\r\n\r\n    mask2 = np.reshape(y_true[2][..., 4:5], [-1])\r\n    gt_box2 = np.reshape(y_true[2][..., 0:4], [-1, 4])\r\n\r\n    gt_box2 = gt_box2[mask2 == 1]\r\n    pad_gt_box2[:gt_box2.shape[0]] = gt_box2\r\n    return y_true[0], y_true[1], y_true[2], pad_gt_box0, pad_gt_box1, pad_gt_box2\r\n\r\n\r\ndef _reshape_data(image, image_size):\r\n    \"\"\"Reshape image.\"\"\"\r\n    if not isinstance(image, Image.Image):\r\n        image = Image.fromarray(image)\r\n    ori_w, ori_h = image.size\r\n    ori_image_shape = np.array([ori_w, ori_h], np.int32)\r\n    # original image shape fir:H sec:W\r\n    h, w = image_size\r\n    interp = get_interp_method(interp=9, sizes=(ori_h, ori_w, h, w))\r\n    image = image.resize((w, h), pil_image_reshape(interp))\r\n    image_data = statistic_normalize_img(image, statistic_norm=True)\r\n    if len(image_data.shape) == 2:\r\n        image_data = np.expand_dims(image_data, axis=-1)\r\n        image_data = np.concatenate([image_data, image_data, image_data], axis=-1)\r\n    image_data = image_data.astype(np.float32)\r\n    return image_data, ori_image_shape\r\n\r\n\r\ndef color_distortion(img, hue, sat, val, device_num):\r\n    \"\"\"Color distortion.\"\"\"\r\n    hue = _rand(-hue, hue)\r\n    sat = _rand(1, sat) if _rand() < .5 else 1 / _rand(1, sat)\r\n    val = _rand(1, val) if _rand() < .5 else 1 / _rand(1, val)\r\n    if device_num != 1:\r\n        cv2.setNumThreads(1)\r\n    x = cv2.cvtColor(img, cv2.COLOR_RGB2HSV_FULL)\r\n    x = x / 255.\r\n    x[..., 0] += hue\r\n    x[..., 0][x[..., 0] > 1] -= 1\r\n    x[..., 0][x[..., 0] < 0] += 1\r\n    x[..., 1] *= sat\r\n    x[..., 2] *= val\r\n    x[x > 1] = 1\r\n    x[x < 0] = 0\r\n    x = x * 255.\r\n    x = x.astype(np.uint8)\r\n    image_data = cv2.cvtColor(x, cv2.COLOR_HSV2RGB_FULL)\r\n    return image_data\r\n\r\n\r\ndef filp_pil_image(img):\r\n    return img.transpose(Image.FLIP_LEFT_RIGHT)\r\n\r\n\r\ndef convert_gray_to_color(img):\r\n    if len(img.shape) == 2:\r\n        img = np.expand_dims(img, axis=-1)\r\n        img = np.concatenate([img, img, img], axis=-1)\r\n    return img\r\n\r\n\r\ndef _is_iou_satisfied_constraint(min_iou, max_iou, box, crop_box):\r\n    iou = bbox_iou(box, crop_box)\r\n    return min_iou <= iou.min() and max_iou >= iou.max()\r\n\r\n\r\ndef _choose_candidate_by_constraints(max_trial, input_w, input_h, image_w, image_h, jitter, box, use_constraints):\r\n    \"\"\"Choose candidate by constraints.\"\"\"\r\n    if use_constraints:\r\n        constraints = (\r\n            (0.1, None),\r\n            (0.3, None),\r\n            (0.5, None),\r\n            (0.7, None),\r\n            (0.9, None),\r\n            (None, 1),\r\n        )\r\n    else:\r\n        constraints = (\r\n            (None, None),\r\n        )\r\n    # add default candidate\r\n    candidates = [(0, 0, input_w, input_h)]\r\n    for constraint in constraints:\r\n        min_iou, max_iou = constraint\r\n        min_iou = -np.inf if min_iou is None else min_iou\r\n        max_iou = np.inf if max_iou is None else max_iou\r\n\r\n        for _ in range(max_trial):\r\n            # box_data should have at least one box\r\n            new_ar = float(input_w) / float(input_h) * _rand(1 - jitter, 1 + jitter) / _rand(1 - jitter, 1 + jitter)\r\n            scale = _rand(0.25, 2)\r\n\r\n            if new_ar < 1:\r\n                nh = int(scale * input_h)\r\n                nw = int(nh * new_ar)\r\n            else:\r\n                nw = int(scale * input_w)\r\n                nh = int(nw / new_ar)\r\n\r\n            dx = int(_rand(0, input_w - nw))\r\n            dy = int(_rand(0, input_h - nh))\r\n\r\n            if box.size > 0:\r\n                t_box = copy.deepcopy(box)\r\n                t_box[:, [0, 2]] = t_box[:, [0, 2]] * float(nw) / float(image_w) + dx\r\n                t_box[:, [1, 3]] = t_box[:, [1, 3]] * float(nh) / float(image_h) + dy\r\n\r\n                crop_box = np.array((0, 0, input_w, input_h))\r\n                if not _is_iou_satisfied_constraint(min_iou, max_iou, t_box, crop_box[np.newaxis]):\r\n                    continue\r\n                else:\r\n                    candidates.append((dx, dy, nw, nh))\r\n            else:\r\n                raise Exception(\"!!! annotation box is less than 1\")\r\n    return candidates\r\n\r\n\r\ndef _correct_bbox_by_candidates(candidates, input_w, input_h, image_w,\r\n                                image_h, flip, box, box_data, allow_outside_center):\r\n    \"\"\"Calculate correct boxes.\"\"\"\r\n    while candidates:\r\n        if len(candidates) > 1:\r\n            # ignore default candidate which do not crop\r\n            candidate = candidates.pop(np.random.randint(1, len(candidates)))\r\n        else:\r\n            candidate = candidates.pop(np.random.randint(0, len(candidates)))\r\n        dx, dy, nw, nh = candidate\r\n        t_box = copy.deepcopy(box)\r\n        t_box[:, [0, 2]] = t_box[:, [0, 2]] * float(nw) / float(image_w) + dx\r\n        t_box[:, [1, 3]] = t_box[:, [1, 3]] * float(nh) / float(image_h) + dy\r\n        if flip:\r\n            t_box[:, [0, 2]] = input_w - t_box[:, [2, 0]]\r\n\r\n        if allow_outside_center:\r\n            pass\r\n        else:\r\n            t_box = t_box[np.logical_and((t_box[:, 0] + t_box[:, 2])/2. >= 0., (t_box[:, 1] + t_box[:, 3])/2. >= 0.)]\r\n            t_box = t_box[np.logical_and((t_box[:, 0] + t_box[:, 2]) / 2. <= input_w,\r\n                                         (t_box[:, 1] + t_box[:, 3]) / 2. <= input_h)]\r\n\r\n        # recorrect x, y for case x,y < 0 reset to zero, after dx and dy, some box can smaller than zero\r\n        t_box[:, 0:2][t_box[:, 0:2] < 0] = 0\r\n        # recorrect w,h not higher than input size\r\n        t_box[:, 2][t_box[:, 2] > input_w] = input_w\r\n        t_box[:, 3][t_box[:, 3] > input_h] = input_h\r\n        box_w = t_box[:, 2] - t_box[:, 0]\r\n        box_h = t_box[:, 3] - t_box[:, 1]\r\n        # discard invalid box: w or h smaller than 1 pixel\r\n        t_box = t_box[np.logical_and(box_w > 1, box_h > 1)]\r\n\r\n        if t_box.shape[0] > 0:\r\n            # break if number of find t_box\r\n            box_data[: len(t_box)] = t_box\r\n            return box_data, candidate\r\n    raise Exception('all candidates can not satisfied re-correct bbox')\r\n\r\n\r\ndef _data_aug(image, box, jitter, hue, sat, val, image_input_size, max_boxes,\r\n              anchors, num_classes, max_trial=10, device_num=1):\r\n    \"\"\"Crop an image randomly with bounding box constraints.\r\n\r\n        This data augmentation is used in training of\r\n        Single Shot Multibox Detector [#]_. More details can be found in\r\n        data augmentation section of the original paper.\r\n        .. [#] Wei Liu, Dragomir Anguelov, Dumitru Erhan, Christian Szegedy,\r\n           Scott Reed, Cheng-Yang Fu, Alexander C. Berg.\r\n           SSD: Single Shot MultiBox Detector. ECCV 2016.\"\"\"\r\n\r\n    if not isinstance(image, Image.Image):\r\n        image = Image.fromarray(image)\r\n\r\n    image_w, image_h = image.size\r\n    input_h, input_w = image_input_size\r\n\r\n    np.random.shuffle(box)\r\n    if len(box) > max_boxes:\r\n        box = box[:max_boxes]\r\n    flip = _rand() < .5\r\n    box_data = np.zeros((max_boxes, 5))\r\n\r\n    candidates = _choose_candidate_by_constraints(use_constraints=False,\r\n                                                  max_trial=max_trial,\r\n                                                  input_w=input_w,\r\n                                                  input_h=input_h,\r\n                                                  image_w=image_w,\r\n                                                  image_h=image_h,\r\n                                                  jitter=jitter,\r\n                                                  box=box)\r\n    box_data, candidate = _correct_bbox_by_candidates(candidates=candidates,\r\n                                                      input_w=input_w,\r\n                                                      input_h=input_h,\r\n                                                      image_w=image_w,\r\n                                                      image_h=image_h,\r\n                                                      flip=flip,\r\n                                                      box=box,\r\n                                                      box_data=box_data,\r\n                                                      allow_outside_center=True)\r\n    dx, dy, nw, nh = candidate\r\n    interp = get_interp_method(interp=10)\r\n    image = image.resize((nw, nh), pil_image_reshape(interp))\r\n    # place image, gray color as back graoud\r\n    new_image = Image.new('RGB', (input_w, input_h), (128, 128, 128))\r\n    new_image.paste(image, (dx, dy))\r\n    image = new_image\r\n\r\n    if flip:\r\n        image = filp_pil_image(image)\r\n\r\n    image = np.array(image)\r\n\r\n    image = convert_gray_to_color(image)\r\n\r\n    image_data = color_distortion(image, hue, sat, val, device_num)\r\n    image_data = statistic_normalize_img(image_data, statistic_norm=True)\r\n\r\n    image_data = image_data.astype(np.float32)\r\n\r\n    return image_data, box_data\r\n\r\n\r\ndef preprocess_fn(image, box, config, input_size, device_num):\r\n    \"\"\"Preprocess data function.\"\"\"\r\n    config_anchors = config.anchor_scales\r\n    anchors = np.array([list(x) for x in config_anchors])\r\n    max_boxes = config.max_box\r\n    num_classes = config.num_classes\r\n    jitter = config.jitter\r\n    hue = config.hue\r\n    sat = config.saturation\r\n    val = config.value\r\n    image, anno = _data_aug(image, box, jitter=jitter, hue=hue, sat=sat, val=val,\r\n                            image_input_size=input_size, max_boxes=max_boxes,\r\n                            num_classes=num_classes, anchors=anchors, device_num=device_num)\r\n    return image, anno\r\n\r\n\r\ndef reshape_fn(image, img_id, config):\r\n    input_size = config.test_img_shape\r\n    image, ori_image_shape = _reshape_data(image, image_size=input_size)\r\n    return image, ori_image_shape, img_id\r\n\r\n\r\nclass MultiScaleTrans:\r\n    \"\"\"Multi scale transform.\"\"\"\r\n    def __init__(self, config, device_num):\r\n        self.config = config\r\n        self.seed = 0\r\n        self.size_list = []\r\n        self.resize_rate = config.resize_rate\r\n        self.dataset_size = config.dataset_size\r\n        self.size_dict = {}\r\n        self.seed_num = int(1e6)\r\n        self.seed_list = self.generate_seed_list(seed_num=self.seed_num)\r\n        self.resize_count_num = int(np.ceil(self.dataset_size / self.resize_rate))\r\n        self.device_num = device_num\r\n        self.anchor_scales = config.anchor_scales\r\n        self.num_classes = config.num_classes\r\n        self.max_box = config.max_box\r\n        self.label_smooth = config.label_smooth\r\n        self.label_smooth_factor = config.label_smooth_factor\r\n\r\n    def generate_seed_list(self, init_seed=1234, seed_num=int(1e6), seed_range=(1, 1000)):\r\n        seed_list = []\r\n        random.seed(init_seed)\r\n        for _ in range(seed_num):\r\n            seed = random.randint(seed_range[0], seed_range[1])\r\n            seed_list.append(seed)\r\n        return seed_list\r\n\r\n    def __call__(self, imgs, annos, x1, x2, x3, x4, x5, x6, batchInfo):\r\n        epoch_num = batchInfo.get_epoch_num()\r\n        size_idx = int(batchInfo.get_batch_num() / self.resize_rate)\r\n        seed_key = self.seed_list[(epoch_num * self.resize_count_num + size_idx) % self.seed_num]\r\n        ret_imgs = []\r\n        ret_annos = []\r\n\r\n        bbox1 = []\r\n        bbox2 = []\r\n        bbox3 = []\r\n        gt1 = []\r\n        gt2 = []\r\n        gt3 = []\r\n\r\n        if self.size_dict.get(seed_key, None) is None:\r\n            random.seed(seed_key)\r\n            new_size = random.choice(self.config.multi_scale)\r\n            self.size_dict[seed_key] = new_size\r\n        seed = seed_key\r\n\r\n        input_size = self.size_dict[seed]\r\n        for img, anno in zip(imgs, annos):\r\n            img, anno = preprocess_fn(img, anno, self.config, input_size, self.device_num)\r\n            ret_imgs.append(img.transpose(2, 0, 1).copy())\r\n            bbox_true_1, bbox_true_2, bbox_true_3, gt_box1, gt_box2, gt_box3 = \\\r\n                _preprocess_true_boxes(true_boxes=anno, anchors=self.anchor_scales, in_shape=img.shape[0:2],\r\n                                       num_classes=self.num_classes, max_boxes=self.max_box,\r\n                                       label_smooth=self.label_smooth, label_smooth_factor=self.label_smooth_factor)\r\n            bbox1.append(bbox_true_1)\r\n            bbox2.append(bbox_true_2)\r\n            bbox3.append(bbox_true_3)\r\n            gt1.append(gt_box1)\r\n            gt2.append(gt_box2)\r\n            gt3.append(gt_box3)\r\n            ret_annos.append(0)\r\n        return np.array(ret_imgs), np.array(ret_annos), np.array(bbox1), np.array(bbox2), np.array(bbox3), \\\r\n               np.array(gt1), np.array(gt2), np.array(gt3)\r\n\r\n\r\ndef thread_batch_preprocess_true_box(annos, config, input_shape, result_index, batch_bbox_true_1, batch_bbox_true_2,\r\n                                     batch_bbox_true_3, batch_gt_box1, batch_gt_box2, batch_gt_box3):\r\n    \"\"\"Preprocess true box for multi-thread.\"\"\"\r\n    i = 0\r\n    for anno in annos:\r\n        bbox_true_1, bbox_true_2, bbox_true_3, gt_box1, gt_box2, gt_box3 = \\\r\n            _preprocess_true_boxes(true_boxes=anno, anchors=config.anchor_scales, in_shape=input_shape,\r\n                                   num_classes=config.num_classes, max_boxes=config.max_box,\r\n                                   label_smooth=config.label_smooth, label_smooth_factor=config.label_smooth_factor)\r\n        batch_bbox_true_1[result_index + i] = bbox_true_1\r\n        batch_bbox_true_2[result_index + i] = bbox_true_2\r\n        batch_bbox_true_3[result_index + i] = bbox_true_3\r\n        batch_gt_box1[result_index + i] = gt_box1\r\n        batch_gt_box2[result_index + i] = gt_box2\r\n        batch_gt_box3[result_index + i] = gt_box3\r\n        i = i + 1\r\n\r\n\r\ndef batch_preprocess_true_box(annos, config, input_shape):\r\n    \"\"\"Preprocess true box with multi-thread.\"\"\"\r\n    batch_bbox_true_1 = []\r\n    batch_bbox_true_2 = []\r\n    batch_bbox_true_3 = []\r\n    batch_gt_box1 = []\r\n    batch_gt_box2 = []\r\n    batch_gt_box3 = []\r\n    threads = []\r\n\r\n    step = 4\r\n    for index in range(0, len(annos), step):\r\n        for _ in range(step):\r\n            batch_bbox_true_1.append(None)\r\n            batch_bbox_true_2.append(None)\r\n            batch_bbox_true_3.append(None)\r\n            batch_gt_box1.append(None)\r\n            batch_gt_box2.append(None)\r\n            batch_gt_box3.append(None)\r\n        step_anno = annos[index: index + step]\r\n        t = threading.Thread(target=thread_batch_preprocess_true_box,\r\n                             args=(step_anno, config, input_shape, index, batch_bbox_true_1, batch_bbox_true_2,\r\n                                   batch_bbox_true_3, batch_gt_box1, batch_gt_box2, batch_gt_box3))\r\n        t.start()\r\n        threads.append(t)\r\n\r\n    for t in threads:\r\n        t.join()\r\n\r\n    return np.array(batch_bbox_true_1), np.array(batch_bbox_true_2), np.array(batch_bbox_true_3), \\\r\n           np.array(batch_gt_box1), np.array(batch_gt_box2), np.array(batch_gt_box3)\r\n\r\n\r\ndef batch_preprocess_true_box_single(annos, config, input_shape):\r\n    \"\"\"Preprocess true boxes.\"\"\"\r\n    batch_bbox_true_1 = []\r\n    batch_bbox_true_2 = []\r\n    batch_bbox_true_3 = []\r\n    batch_gt_box1 = []\r\n    batch_gt_box2 = []\r\n    batch_gt_box3 = []\r\n    for anno in annos:\r\n        bbox_true_1, bbox_true_2, bbox_true_3, gt_box1, gt_box2, gt_box3 = \\\r\n            _preprocess_true_boxes(true_boxes=anno, anchors=config.anchor_scales, in_shape=input_shape,\r\n                                   num_classes=config.num_classes, max_boxes=config.max_box,\r\n                                   label_smooth=config.label_smooth, label_smooth_factor=config.label_smooth_factor)\r\n        batch_bbox_true_1.append(bbox_true_1)\r\n        batch_bbox_true_2.append(bbox_true_2)\r\n        batch_bbox_true_3.append(bbox_true_3)\r\n        batch_gt_box1.append(gt_box1)\r\n        batch_gt_box2.append(gt_box2)\r\n        batch_gt_box3.append(gt_box3)\r\n\r\n    return np.array(batch_bbox_true_1), np.array(batch_bbox_true_2), np.array(batch_bbox_true_3), \\\r\n           np.array(batch_gt_box1), np.array(batch_gt_box2), np.array(batch_gt_box3)\r\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/yolov3_darknet53/src/util.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"Util class or function.\"\"\"\nfrom mindspore.train.serialization import load_checkpoint\nimport mindspore.nn as nn\nimport mindspore.common.dtype as mstype\n\nfrom .yolo import YoloLossBlock\n\n\nclass AverageMeter:\n    \"\"\"Computes and stores the average and current value\"\"\"\n\n    def __init__(self, name, fmt=':f', tb_writer=None):\n        self.name = name\n        self.fmt = fmt\n        self.reset()\n        self.tb_writer = tb_writer\n        self.cur_step = 1\n        self.val = 0\n        self.avg = 0\n        self.sum = 0\n        self.count = 0\n\n    def reset(self):\n        self.val = 0\n        self.avg = 0\n        self.sum = 0\n        self.count = 0\n\n    def update(self, val, n=1):\n        self.val = val\n        self.sum += val * n\n        self.count += n\n        self.avg = self.sum / self.count\n        if self.tb_writer is not None:\n            self.tb_writer.add_scalar(self.name, self.val, self.cur_step)\n        self.cur_step += 1\n\n    def __str__(self):\n        fmtstr = '{name}:{avg' + self.fmt + '}'\n        return fmtstr.format(**self.__dict__)\n\n\ndef load_backbone(net, ckpt_path, args):\n    \"\"\"Load darknet53 backbone checkpoint.\"\"\"\n    param_dict = load_checkpoint(ckpt_path)\n    yolo_backbone_prefix = 'feature_map.backbone'\n    darknet_backbone_prefix = 'network.backbone'\n    find_param = []\n    not_found_param = []\n    net.init_parameters_data()\n    for name, cell in net.cells_and_names():\n        if name.startswith(yolo_backbone_prefix):\n            name = name.replace(yolo_backbone_prefix, darknet_backbone_prefix)\n            if isinstance(cell, (nn.Conv2d, nn.Dense)):\n                darknet_weight = '{}.weight'.format(name)\n                darknet_bias = '{}.bias'.format(name)\n                if darknet_weight in param_dict:\n                    cell.weight.set_data(param_dict[darknet_weight].data)\n                    find_param.append(darknet_weight)\n                else:\n                    not_found_param.append(darknet_weight)\n                if darknet_bias in param_dict:\n                    cell.bias.set_data(param_dict[darknet_bias].data)\n                    find_param.append(darknet_bias)\n                else:\n                    not_found_param.append(darknet_bias)\n            elif isinstance(cell, (nn.BatchNorm2d, nn.BatchNorm1d)):\n                darknet_moving_mean = '{}.moving_mean'.format(name)\n                darknet_moving_variance = '{}.moving_variance'.format(name)\n                darknet_gamma = '{}.gamma'.format(name)\n                darknet_beta = '{}.beta'.format(name)\n                if darknet_moving_mean in param_dict:\n                    cell.moving_mean.set_data(param_dict[darknet_moving_mean].data)\n                    find_param.append(darknet_moving_mean)\n                else:\n                    not_found_param.append(darknet_moving_mean)\n                if darknet_moving_variance in param_dict:\n                    cell.moving_variance.set_data(param_dict[darknet_moving_variance].data)\n                    find_param.append(darknet_moving_variance)\n                else:\n                    not_found_param.append(darknet_moving_variance)\n                if darknet_gamma in param_dict:\n                    cell.gamma.set_data(param_dict[darknet_gamma].data)\n                    find_param.append(darknet_gamma)\n                else:\n                    not_found_param.append(darknet_gamma)\n                if darknet_beta in param_dict:\n                    cell.beta.set_data(param_dict[darknet_beta].data)\n                    find_param.append(darknet_beta)\n                else:\n                    not_found_param.append(darknet_beta)\n\n    args.logger.info('================found_param {}========='.format(len(find_param)))\n    args.logger.info(find_param)\n    args.logger.info('================not_found_param {}========='.format(len(not_found_param)))\n    args.logger.info(not_found_param)\n    args.logger.info('=====load {} successfully ====='.format(ckpt_path))\n\n    return net\n\n\ndef default_wd_filter(x):\n    \"\"\"default weight decay filter.\"\"\"\n    parameter_name = x.name\n    if parameter_name.endswith('.bias'):\n        # all bias not using weight decay\n        return False\n    if parameter_name.endswith('.gamma'):\n        # bn weight bias not using weight decay, be carefully for now x not include BN\n        return False\n    if parameter_name.endswith('.beta'):\n        # bn weight bias not using weight decay, be carefully for now x not include BN\n        return False\n\n    return True\n\n\ndef get_param_groups(network):\n    \"\"\"Param groups for optimizer.\"\"\"\n    decay_params = []\n    no_decay_params = []\n    for x in network.trainable_params():\n        parameter_name = x.name\n        if parameter_name.endswith('.bias'):\n            # all bias not using weight decay\n            no_decay_params.append(x)\n        elif parameter_name.endswith('.gamma'):\n            # bn weight bias not using weight decay, be carefully for now x not include BN\n            no_decay_params.append(x)\n        elif parameter_name.endswith('.beta'):\n            # bn weight bias not using weight decay, be carefully for now x not include BN\n            no_decay_params.append(x)\n        else:\n            decay_params.append(x)\n\n    return [{'params': no_decay_params, 'weight_decay': 0.0}, {'params': decay_params}]\n\n\nclass ShapeRecord:\n    \"\"\"Log image shape.\"\"\"\n    def __init__(self):\n        self.shape_record = {\n            320: 0,\n            352: 0,\n            384: 0,\n            416: 0,\n            448: 0,\n            480: 0,\n            512: 0,\n            544: 0,\n            576: 0,\n            608: 0,\n            'total': 0\n        }\n\n    def set(self, shape):\n        if len(shape) > 1:\n            shape = shape[0]\n        shape = int(shape)\n        self.shape_record[shape] += 1\n        self.shape_record['total'] += 1\n\n    def show(self, logger):\n        for key in self.shape_record:\n            rate = self.shape_record[key] / float(self.shape_record['total'])\n            logger.info('shape {}: {:.2f}%'.format(key, rate*100))\n\n\ndef keep_loss_fp32(network):\n    \"\"\"Keep loss of network with float32\"\"\"\n    for _, cell in network.cells_and_names():\n        if isinstance(cell, (YoloLossBlock,)):\n            cell.to_float(mstype.float32)\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/yolov3_darknet53/src/yolo.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n# ============================================================================\r\n\"\"\"YOLOv3 based on DarkNet.\"\"\"\r\nimport mindspore as ms\r\nimport mindspore.nn as nn\r\nfrom mindspore.common.tensor import Tensor\r\nfrom mindspore import context\r\nfrom mindspore.context import ParallelMode\r\nfrom mindspore.parallel._auto_parallel_context import auto_parallel_context\r\nfrom mindspore.communication.management import get_group_size\r\nfrom mindspore.ops import operations as P\r\nfrom mindspore.ops import functional as F\r\nfrom mindspore.ops import composite as C\r\n\r\nfrom src.darknet import DarkNet, ResidualBlock\r\nfrom src.config import ConfigYOLOV3DarkNet53\r\nfrom src.loss import XYLoss, WHLoss, ConfidenceLoss, ClassLoss\r\n\r\n# pylint: disable=locally-disables, missing-docstring, invalid-name\r\n\r\n\r\ndef _conv_bn_relu(in_channel,\r\n                  out_channel,\r\n                  ksize,\r\n                  stride=1,\r\n                  padding=0,\r\n                  dilation=1,\r\n                  alpha=0.1,\r\n                  momentum=0.9,\r\n                  eps=1e-5,\r\n                  pad_mode=\"same\"):\r\n    \"\"\"Get a conv2d batchnorm and relu layer\"\"\"\r\n    return nn.SequentialCell(\r\n        [nn.Conv2d(in_channel,\r\n                   out_channel,\r\n                   kernel_size=ksize,\r\n                   stride=stride,\r\n                   padding=padding,\r\n                   dilation=dilation,\r\n                   pad_mode=pad_mode),\r\n         nn.BatchNorm2d(out_channel, momentum=momentum, eps=eps),\r\n         nn.LeakyReLU(alpha)]\r\n    )\r\n\r\n\r\nclass YoloBlock(nn.Cell):\r\n    \"\"\"\r\n    YoloBlock for YOLOv3.\r\n\r\n    Args:\r\n        in_channels: Integer. Input channel.\r\n        out_chls: Interger. Middle channel.\r\n        out_channels: Integer. Output channel.\r\n\r\n    Returns:\r\n        Tuple, tuple of output tensor,(f1,f2,f3).\r\n\r\n    Examples:\r\n        YoloBlock(1024, 512, 255)\r\n\r\n    \"\"\"\r\n    def __init__(self, in_channels, out_chls, out_channels):\r\n        super(YoloBlock, self).__init__()\r\n        out_chls_2 = out_chls*2\r\n\r\n        self.conv0 = _conv_bn_relu(in_channels, out_chls, ksize=1)\r\n        self.conv1 = _conv_bn_relu(out_chls, out_chls_2, ksize=3)\r\n\r\n        self.conv2 = _conv_bn_relu(out_chls_2, out_chls, ksize=1)\r\n        self.conv3 = _conv_bn_relu(out_chls, out_chls_2, ksize=3)\r\n\r\n        self.conv4 = _conv_bn_relu(out_chls_2, out_chls, ksize=1)\r\n        self.conv5 = _conv_bn_relu(out_chls, out_chls_2, ksize=3)\r\n\r\n        self.conv6 = nn.Conv2d(out_chls_2, out_channels, kernel_size=1, stride=1, has_bias=True)\r\n\r\n    def construct(self, x):\r\n        c1 = self.conv0(x)\r\n        c2 = self.conv1(c1)\r\n\r\n        c3 = self.conv2(c2)\r\n        c4 = self.conv3(c3)\r\n\r\n        c5 = self.conv4(c4)\r\n        c6 = self.conv5(c5)\r\n\r\n        out = self.conv6(c6)\r\n        return c5, out\r\n\r\n\r\nclass YOLOv3(nn.Cell):\r\n    \"\"\"\r\n     YOLOv3 Network.\r\n\r\n     Note:\r\n         backbone = darknet53\r\n\r\n     Args:\r\n         backbone_shape: List. Darknet output channels shape.\r\n         backbone: Cell. Backbone Network.\r\n         out_channel: Interger. Output channel.\r\n\r\n     Returns:\r\n         Tensor, output tensor.\r\n\r\n     Examples:\r\n         YOLOv3(backbone_shape=[64, 128, 256, 512, 1024]\r\n                backbone=darknet53(),\r\n                out_channel=255)\r\n     \"\"\"\r\n    def __init__(self, backbone_shape, backbone, out_channel):\r\n        super(YOLOv3, self).__init__()\r\n        self.out_channel = out_channel\r\n        self.backbone = backbone\r\n        self.backblock0 = YoloBlock(backbone_shape[-1], out_chls=backbone_shape[-2], out_channels=out_channel)\r\n\r\n        self.conv1 = _conv_bn_relu(in_channel=backbone_shape[-2], out_channel=backbone_shape[-2]//2, ksize=1)\r\n        self.backblock1 = YoloBlock(in_channels=backbone_shape[-2]+backbone_shape[-3],\r\n                                    out_chls=backbone_shape[-3],\r\n                                    out_channels=out_channel)\r\n\r\n        self.conv2 = _conv_bn_relu(in_channel=backbone_shape[-3], out_channel=backbone_shape[-3]//2, ksize=1)\r\n        self.backblock2 = YoloBlock(in_channels=backbone_shape[-3]+backbone_shape[-4],\r\n                                    out_chls=backbone_shape[-4],\r\n                                    out_channels=out_channel)\r\n        self.concat = P.Concat(axis=1)\r\n\r\n    def construct(self, x):\r\n        # input_shape of x is (batch_size, 3, h, w)\r\n        # feature_map1 is (batch_size, backbone_shape[2], h/8, w/8)\r\n        # feature_map2 is (batch_size, backbone_shape[3], h/16, w/16)\r\n        # feature_map3 is (batch_size, backbone_shape[4], h/32, w/32)\r\n        img_hight = P.Shape()(x)[2]\r\n        img_width = P.Shape()(x)[3]\r\n        feature_map1, feature_map2, feature_map3 = self.backbone(x)\r\n        con1, big_object_output = self.backblock0(feature_map3)\r\n\r\n        con1 = self.conv1(con1)\r\n        ups1 = P.ResizeNearestNeighbor((img_hight / 16, img_width / 16))(con1)\r\n        con1 = self.concat((ups1, feature_map2))\r\n        con2, medium_object_output = self.backblock1(con1)\r\n\r\n        con2 = self.conv2(con2)\r\n        ups2 = P.ResizeNearestNeighbor((img_hight / 8, img_width / 8))(con2)\r\n        con3 = self.concat((ups2, feature_map1))\r\n        _, small_object_output = self.backblock2(con3)\r\n\r\n        return big_object_output, medium_object_output, small_object_output\r\n\r\n\r\nclass DetectionBlock(nn.Cell):\r\n    \"\"\"\r\n     YOLOv3 detection Network. It will finally output the detection result.\r\n\r\n     Args:\r\n         scale: Character.\r\n         config: ConfigYOLOV3DarkNet53, Configuration instance.\r\n         is_training: Bool, Whether train or not, default True.\r\n\r\n     Returns:\r\n         Tuple, tuple of output tensor,(f1,f2,f3).\r\n\r\n     Examples:\r\n         DetectionBlock(scale='l',stride=32)\r\n     \"\"\"\r\n\r\n    def __init__(self, scale, config=ConfigYOLOV3DarkNet53(), is_training=True):\r\n        super(DetectionBlock, self).__init__()\r\n        self.config = config\r\n        if scale == 's':\r\n            idx = (0, 1, 2)\r\n        elif scale == 'm':\r\n            idx = (3, 4, 5)\r\n        elif scale == 'l':\r\n            idx = (6, 7, 8)\r\n        else:\r\n            raise KeyError(\"Invalid scale value for DetectionBlock\")\r\n        self.anchors = Tensor([self.config.anchor_scales[i] for i in idx], ms.float32)\r\n        self.num_anchors_per_scale = 3\r\n        self.num_attrib = 4+1+self.config.num_classes\r\n        self.lambda_coord = 1\r\n\r\n        self.sigmoid = nn.Sigmoid()\r\n        self.reshape = P.Reshape()\r\n        self.tile = P.Tile()\r\n        self.concat = P.Concat(axis=-1)\r\n        self.conf_training = is_training\r\n\r\n    def construct(self, x, input_shape):\r\n        num_batch = P.Shape()(x)[0]\r\n        grid_size = P.Shape()(x)[2:4]\r\n\r\n        # Reshape and transpose the feature to [n, grid_size[0], grid_size[1], 3, num_attrib]\r\n        prediction = P.Reshape()(x, (num_batch,\r\n                                     self.num_anchors_per_scale,\r\n                                     self.num_attrib,\r\n                                     grid_size[0],\r\n                                     grid_size[1]))\r\n        prediction = P.Transpose()(prediction, (0, 3, 4, 1, 2))\r\n\r\n        range_x = range(grid_size[1])\r\n        range_y = range(grid_size[0])\r\n        grid_x = P.Cast()(F.tuple_to_array(range_x), ms.float32)\r\n        grid_y = P.Cast()(F.tuple_to_array(range_y), ms.float32)\r\n        # Tensor of shape [grid_size[0], grid_size[1], 1, 1] representing the coordinate of x/y axis for each grid\r\n        # [batch, gridx, gridy, 1, 1]\r\n        grid_x = self.tile(self.reshape(grid_x, (1, 1, -1, 1, 1)), (1, grid_size[0], 1, 1, 1))\r\n        grid_y = self.tile(self.reshape(grid_y, (1, -1, 1, 1, 1)), (1, 1, grid_size[1], 1, 1))\r\n        # Shape is [grid_size[0], grid_size[1], 1, 2]\r\n        grid = self.concat((grid_x, grid_y))\r\n\r\n        box_xy = prediction[:, :, :, :, :2]\r\n        box_wh = prediction[:, :, :, :, 2:4]\r\n        box_confidence = prediction[:, :, :, :, 4:5]\r\n        box_probs = prediction[:, :, :, :, 5:]\r\n\r\n        # gridsize1 is x\r\n        # gridsize0 is y\r\n        box_xy = (self.sigmoid(box_xy) + grid) / P.Cast()(F.tuple_to_array((grid_size[1], grid_size[0])), ms.float32)\r\n        # box_wh is w->h\r\n        box_wh = P.Exp()(box_wh) * self.anchors / input_shape\r\n        box_confidence = self.sigmoid(box_confidence)\r\n        box_probs = self.sigmoid(box_probs)\r\n\r\n        if self.conf_training:\r\n            return grid, prediction, box_xy, box_wh\r\n        return self.concat((box_xy, box_wh, box_confidence, box_probs))\r\n\r\n\r\nclass Iou(nn.Cell):\r\n    \"\"\"Calculate the iou of boxes\"\"\"\r\n    def __init__(self):\r\n        super(Iou, self).__init__()\r\n        self.min = P.Minimum()\r\n        self.max = P.Maximum()\r\n\r\n    def construct(self, box1, box2):\r\n        # box1: pred_box [batch, gx, gy, anchors, 1,      4] ->4: [x_center, y_center, w, h]\r\n        # box2: gt_box   [batch, 1,  1,  1,       maxbox, 4]\r\n        # convert to topLeft and rightDown\r\n        box1_xy = box1[:, :, :, :, :, :2]\r\n        box1_wh = box1[:, :, :, :, :, 2:4]\r\n        box1_mins = box1_xy - box1_wh / F.scalar_to_array(2.0) # topLeft\r\n        box1_maxs = box1_xy + box1_wh / F.scalar_to_array(2.0) # rightDown\r\n\r\n        box2_xy = box2[:, :, :, :, :, :2]\r\n        box2_wh = box2[:, :, :, :, :, 2:4]\r\n        box2_mins = box2_xy - box2_wh / F.scalar_to_array(2.0)\r\n        box2_maxs = box2_xy + box2_wh / F.scalar_to_array(2.0)\r\n\r\n        intersect_mins = self.max(box1_mins, box2_mins)\r\n        intersect_maxs = self.min(box1_maxs, box2_maxs)\r\n        intersect_wh = self.max(intersect_maxs - intersect_mins, F.scalar_to_array(0.0))\r\n        # P.squeeze: for effiecient slice\r\n        intersect_area = P.Squeeze(-1)(intersect_wh[:, :, :, :, :, 0:1]) * \\\r\n                         P.Squeeze(-1)(intersect_wh[:, :, :, :, :, 1:2])\r\n        box1_area = P.Squeeze(-1)(box1_wh[:, :, :, :, :, 0:1]) * P.Squeeze(-1)(box1_wh[:, :, :, :, :, 1:2])\r\n        box2_area = P.Squeeze(-1)(box2_wh[:, :, :, :, :, 0:1]) * P.Squeeze(-1)(box2_wh[:, :, :, :, :, 1:2])\r\n        iou = intersect_area / (box1_area + box2_area - intersect_area)\r\n        # iou : [batch, gx, gy, anchors, maxboxes]\r\n        return iou\r\n\r\n\r\nclass YoloLossBlock(nn.Cell):\r\n    \"\"\"\r\n    Loss block cell of YOLOV3 network.\r\n    \"\"\"\r\n    def __init__(self, scale, config=ConfigYOLOV3DarkNet53()):\r\n        super(YoloLossBlock, self).__init__()\r\n        self.config = config\r\n        if scale == 's':\r\n            # anchor mask\r\n            idx = (0, 1, 2)\r\n        elif scale == 'm':\r\n            idx = (3, 4, 5)\r\n        elif scale == 'l':\r\n            idx = (6, 7, 8)\r\n        else:\r\n            raise KeyError(\"Invalid scale value for DetectionBlock\")\r\n        self.anchors = Tensor([self.config.anchor_scales[i] for i in idx], ms.float32)\r\n        self.ignore_threshold = Tensor(self.config.ignore_threshold, ms.float32)\r\n        self.concat = P.Concat(axis=-1)\r\n        self.iou = Iou()\r\n        self.reduce_max = P.ReduceMax(keep_dims=False)\r\n        self.xy_loss = XYLoss()\r\n        self.wh_loss = WHLoss()\r\n        self.confidenceLoss = ConfidenceLoss()\r\n        self.classLoss = ClassLoss()\r\n\r\n    def construct(self, grid, prediction, pred_xy, pred_wh, y_true, gt_box, input_shape):\r\n        # prediction : origin output from yolo\r\n        # pred_xy: (sigmoid(xy)+grid)/grid_size\r\n        # pred_wh: (exp(wh)*anchors)/input_shape\r\n        # y_true : after normalize\r\n        # gt_box: [batch, maxboxes, xyhw] after normalize\r\n\r\n        object_mask = y_true[:, :, :, :, 4:5]\r\n        class_probs = y_true[:, :, :, :, 5:]\r\n\r\n        grid_shape = P.Shape()(prediction)[1:3]\r\n        grid_shape = P.Cast()(F.tuple_to_array(grid_shape[::-1]), ms.float32)\r\n\r\n        pred_boxes = self.concat((pred_xy, pred_wh))\r\n        true_xy = y_true[:, :, :, :, :2] * grid_shape - grid\r\n        true_wh = y_true[:, :, :, :, 2:4]\r\n        true_wh = P.Select()(P.Equal()(true_wh, 0.0),\r\n                             P.Fill()(P.DType()(true_wh),\r\n                                      P.Shape()(true_wh), 1.0),\r\n                             true_wh)\r\n        true_wh = P.Log()(true_wh / self.anchors * input_shape)\r\n        # 2-w*h for large picture, use small scale, since small obj need more precise\r\n        box_loss_scale = 2 - y_true[:, :, :, :, 2:3] * y_true[:, :, :, :, 3:4]\r\n\r\n        gt_shape = P.Shape()(gt_box)\r\n        gt_box = P.Reshape()(gt_box, (gt_shape[0], 1, 1, 1, gt_shape[1], gt_shape[2]))\r\n\r\n        # add one more dimension for broadcast\r\n        iou = self.iou(P.ExpandDims()(pred_boxes, -2), gt_box)\r\n        # gt_box is x,y,h,w after normalize\r\n        # [batch, grid[0], grid[1], num_anchor, num_gt]\r\n        best_iou = self.reduce_max(iou, -1)\r\n        # [batch, grid[0], grid[1], num_anchor]\r\n\r\n        # ignore_mask IOU too small\r\n        ignore_mask = best_iou < self.ignore_threshold\r\n        ignore_mask = P.Cast()(ignore_mask, ms.float32)\r\n        ignore_mask = P.ExpandDims()(ignore_mask, -1)\r\n        # ignore_mask backpro will cause a lot maximunGrad and minimumGrad time consume.\r\n        # so we turn off its gradient\r\n        ignore_mask = F.stop_gradient(ignore_mask)\r\n\r\n        xy_loss = self.xy_loss(object_mask, box_loss_scale, prediction[:, :, :, :, :2], true_xy)\r\n        wh_loss = self.wh_loss(object_mask, box_loss_scale, prediction[:, :, :, :, 2:4], true_wh)\r\n        confidence_loss = self.confidenceLoss(object_mask, prediction[:, :, :, :, 4:5], ignore_mask)\r\n        class_loss = self.classLoss(object_mask, prediction[:, :, :, :, 5:], class_probs)\r\n        loss = xy_loss + wh_loss + confidence_loss + class_loss\r\n        batch_size = P.Shape()(prediction)[0]\r\n        return loss / batch_size\r\n\r\n\r\nclass YOLOV3DarkNet53(nn.Cell):\r\n    \"\"\"\r\n    Darknet based YOLOV3 network.\r\n\r\n    Args:\r\n        is_training: Bool. Whether train or not.\r\n\r\n    Returns:\r\n        Cell, cell instance of Darknet based YOLOV3 neural network.\r\n\r\n    Examples:\r\n        YOLOV3DarkNet53(True)\r\n    \"\"\"\r\n\r\n    def __init__(self, is_training):\r\n        super(YOLOV3DarkNet53, self).__init__()\r\n        self.config = ConfigYOLOV3DarkNet53()\r\n\r\n        # YOLOv3 network\r\n        self.feature_map = YOLOv3(backbone=DarkNet(ResidualBlock, self.config.backbone_layers,\r\n                                                   self.config.backbone_input_shape,\r\n                                                   self.config.backbone_shape,\r\n                                                   detect=True),\r\n                                  backbone_shape=self.config.backbone_shape,\r\n                                  out_channel=self.config.out_channel)\r\n\r\n        # prediction on the default anchor boxes\r\n        self.detect_1 = DetectionBlock('l', is_training=is_training)\r\n        self.detect_2 = DetectionBlock('m', is_training=is_training)\r\n        self.detect_3 = DetectionBlock('s', is_training=is_training)\r\n\r\n    def construct(self, x, input_shape):\r\n        big_object_output, medium_object_output, small_object_output = self.feature_map(x)\r\n        output_big = self.detect_1(big_object_output, input_shape)\r\n        output_me = self.detect_2(medium_object_output, input_shape)\r\n        output_small = self.detect_3(small_object_output, input_shape)\r\n        # big is the final output which has smallest feature map\r\n        return output_big, output_me, output_small\r\n\r\n\r\nclass YoloWithLossCell(nn.Cell):\r\n    \"\"\"YOLOV3 loss.\"\"\"\r\n    def __init__(self, network):\r\n        super(YoloWithLossCell, self).__init__()\r\n        self.yolo_network = network\r\n        self.config = ConfigYOLOV3DarkNet53()\r\n        self.loss_big = YoloLossBlock('l', self.config)\r\n        self.loss_me = YoloLossBlock('m', self.config)\r\n        self.loss_small = YoloLossBlock('s', self.config)\r\n\r\n    def construct(self, x, y_true_0, y_true_1, y_true_2, gt_0, gt_1, gt_2, input_shape):\r\n        yolo_out = self.yolo_network(x, input_shape)\r\n        loss_l = self.loss_big(*yolo_out[0], y_true_0, gt_0, input_shape)\r\n        loss_m = self.loss_me(*yolo_out[1], y_true_1, gt_1, input_shape)\r\n        loss_s = self.loss_small(*yolo_out[2], y_true_2, gt_2, input_shape)\r\n        return loss_l + loss_m + loss_s\r\n\r\n\r\nclass TrainingWrapper(nn.Cell):\r\n    \"\"\"Training wrapper.\"\"\"\r\n    def __init__(self, network, optimizer, sens=1.0):\r\n        super(TrainingWrapper, self).__init__(auto_prefix=False)\r\n        self.network = network\r\n        self.network.set_grad()\r\n        self.weights = optimizer.parameters\r\n        self.optimizer = optimizer\r\n        self.grad = C.GradOperation(get_by_list=True, sens_param=True)\r\n        self.sens = sens\r\n        self.reducer_flag = False\r\n        self.grad_reducer = None\r\n        self.parallel_mode = context.get_auto_parallel_context(\"parallel_mode\")\r\n        if self.parallel_mode in [ParallelMode.DATA_PARALLEL, ParallelMode.HYBRID_PARALLEL]:\r\n            self.reducer_flag = True\r\n        if self.reducer_flag:\r\n            mean = context.get_auto_parallel_context(\"gradients_mean\")\r\n            if auto_parallel_context().get_device_num_is_set():\r\n                degree = context.get_auto_parallel_context(\"device_num\")\r\n            else:\r\n                degree = get_group_size()\r\n            self.grad_reducer = nn.DistributedGradReducer(optimizer.parameters, mean, degree)\r\n\r\n    def construct(self, *args):\r\n        weights = self.weights\r\n        loss = self.network(*args)\r\n        sens = P.Fill()(P.DType()(loss), P.Shape()(loss), self.sens)\r\n        grads = self.grad(self.network, weights)(*args, sens)\r\n        if self.reducer_flag:\r\n            grads = self.grad_reducer(grads)\r\n        return F.depend(loss, self.optimizer(grads))\r\n"
  },
  {
    "path": "examples/model_security/model_attacks/cv/yolov3_darknet53/src/yolo_dataset.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n# ============================================================================\r\n\"\"\"YOLOV3 dataset.\"\"\"\r\nimport os\r\n\r\nimport multiprocessing\r\nimport cv2\r\nfrom PIL import Image\r\nfrom pycocotools.coco import COCO\r\nimport mindspore.dataset as de\r\nimport mindspore.dataset.vision as CV\r\n\r\nfrom src.distributed_sampler import DistributedSampler\r\nfrom src.transforms import reshape_fn, MultiScaleTrans\r\n\r\n# pylint: disable=locally-disables, invalid-name\r\n\r\n\r\nmin_keypoints_per_image = 10\r\n\r\n\r\ndef _has_only_empty_bbox(anno):\r\n    return all(any(o <= 1 for o in obj[\"bbox\"][2:]) for obj in anno)\r\n\r\n\r\ndef _count_visible_keypoints(anno):\r\n    return sum(sum(1 for v in ann[\"keypoints\"][2::3] if v > 0) for ann in anno)\r\n\r\n\r\ndef has_valid_annotation(anno):\r\n    \"\"\"Check annotation file.\"\"\"\r\n    # if it's empty, there is no annotation\r\n    if not anno:\r\n        return False\r\n    # if all boxes have close to zero area, there is no annotation\r\n    if _has_only_empty_bbox(anno):\r\n        return False\r\n    # keypoints task have a slight different critera for considering\r\n    # if an annotation is valid\r\n    if \"keypoints\" not in anno[0]:\r\n        return True\r\n    # for keypoint detection tasks, only consider valid images those\r\n    # containing at least min_keypoints_per_image\r\n    if _count_visible_keypoints(anno) >= min_keypoints_per_image:\r\n        return True\r\n    return False\r\n\r\n\r\nclass COCOYoloDataset:\r\n    \"\"\"YOLOV3 Dataset for COCO.\"\"\"\r\n    def __init__(self, root, ann_file, remove_images_without_annotations=True,\r\n                 filter_crowd_anno=True, is_training=True):\r\n        self.coco = COCO(ann_file)\r\n        self.root = root\r\n        self.img_ids = list(sorted(self.coco.imgs.keys()))\r\n        self.filter_crowd_anno = filter_crowd_anno\r\n        self.is_training = is_training\r\n\r\n        # filter images without any annotations\r\n        if remove_images_without_annotations:\r\n            img_ids = []\r\n            for img_id in self.img_ids:\r\n                ann_ids = self.coco.getAnnIds(imgIds=img_id, iscrowd=None)\r\n                anno = self.coco.loadAnns(ann_ids)\r\n                if has_valid_annotation(anno):\r\n                    img_ids.append(img_id)\r\n            self.img_ids = img_ids\r\n\r\n        self.categories = {cat[\"id\"]: cat[\"name\"] for cat in self.coco.cats.values()}\r\n\r\n        self.cat_ids_to_continuous_ids = {\r\n            v: i for i, v in enumerate(self.coco.getCatIds())\r\n        }\r\n        self.continuous_ids_cat_ids = {\r\n            v: k for k, v in self.cat_ids_to_continuous_ids.items()\r\n        }\r\n\r\n    def __getitem__(self, index):\r\n        \"\"\"\r\n        Args:\r\n            index (int): Index\r\n\r\n        Returns:\r\n            (img, target) (tuple): target is a dictionary contains \"bbox\", \"segmentation\" or \"keypoints\",\r\n                generated by the image's annotation. img is a PIL image.\r\n        \"\"\"\r\n        coco = self.coco\r\n        img_id = self.img_ids[index]\r\n        img_path = coco.loadImgs(img_id)[0][\"file_name\"]\r\n        img = Image.open(os.path.join(self.root, img_path)).convert(\"RGB\")\r\n        if not self.is_training:\r\n            return img, img_id\r\n\r\n        ann_ids = coco.getAnnIds(imgIds=img_id)\r\n        target = coco.loadAnns(ann_ids)\r\n        # filter crowd annotations\r\n        if self.filter_crowd_anno:\r\n            annos = [anno for anno in target if anno[\"iscrowd\"] == 0]\r\n        else:\r\n            annos = [anno for anno in target]\r\n\r\n        target = {}\r\n        boxes = [anno[\"bbox\"] for anno in annos]\r\n        target[\"bboxes\"] = boxes\r\n\r\n        classes = [anno[\"category_id\"] for anno in annos]\r\n        classes = [self.cat_ids_to_continuous_ids[cl] for cl in classes]\r\n        target[\"labels\"] = classes\r\n\r\n        bboxes = target['bboxes']\r\n        labels = target['labels']\r\n        out_target = []\r\n        for bbox, label in zip(bboxes, labels):\r\n            tmp = []\r\n            # convert to [x_min y_min x_max y_max]\r\n            bbox = self._convetTopDown(bbox)\r\n            tmp.extend(bbox)\r\n            tmp.append(int(label))\r\n            # tmp [x_min y_min x_max y_max, label]\r\n            out_target.append(tmp)\r\n        return img, out_target, [], [], [], [], [], []\r\n\r\n    def __len__(self):\r\n        return len(self.img_ids)\r\n\r\n    def _convetTopDown(self, bbox):\r\n        x_min = bbox[0]\r\n        y_min = bbox[1]\r\n        w = bbox[2]\r\n        h = bbox[3]\r\n        return [x_min, y_min, x_min+w, y_min+h]\r\n\r\n\r\ndef create_yolo_dataset(image_dir, anno_path, batch_size, max_epoch, device_num, rank,\r\n                        config=None, is_training=True, shuffle=True):\r\n    \"\"\"Create dataset for YOLOV3.\"\"\"\r\n    cv2.setNumThreads(0)\r\n\r\n    if is_training:\r\n        filter_crowd = True\r\n        remove_empty_anno = True\r\n    else:\r\n        filter_crowd = False\r\n        remove_empty_anno = False\r\n\r\n    yolo_dataset = COCOYoloDataset(root=image_dir, ann_file=anno_path, filter_crowd_anno=filter_crowd,\r\n                                   remove_images_without_annotations=remove_empty_anno, is_training=is_training)\r\n    distributed_sampler = DistributedSampler(len(yolo_dataset), device_num, rank, shuffle=shuffle)\r\n    hwc_to_chw = CV.HWC2CHW()\r\n\r\n    config.dataset_size = len(yolo_dataset)\r\n    cores = multiprocessing.cpu_count()\r\n    num_parallel_workers = int(cores / device_num)\r\n    if is_training:\r\n        multi_scale_trans = MultiScaleTrans(config, device_num)\r\n        dataset_column_names = [\"image\", \"annotation\", \"bbox1\", \"bbox2\", \"bbox3\",\r\n                                \"gt_box1\", \"gt_box2\", \"gt_box3\"]\r\n        if device_num != 8:\r\n            ds = de.GeneratorDataset(yolo_dataset, column_names=dataset_column_names,\r\n                                     num_parallel_workers=min(32, num_parallel_workers),\r\n                                     sampler=distributed_sampler)\r\n            ds = ds.batch(batch_size, per_batch_map=multi_scale_trans, input_columns=dataset_column_names,\r\n                          num_parallel_workers=min(32, num_parallel_workers), drop_remainder=True)\r\n        else:\r\n            ds = de.GeneratorDataset(yolo_dataset, column_names=dataset_column_names, sampler=distributed_sampler)\r\n            ds = ds.batch(batch_size, per_batch_map=multi_scale_trans, input_columns=dataset_column_names,\r\n                          num_parallel_workers=min(8, num_parallel_workers), drop_remainder=True)\r\n    else:\r\n        ds = de.GeneratorDataset(yolo_dataset, column_names=[\"image\", \"img_id\"],\r\n                                 sampler=distributed_sampler)\r\n        compose_map_func = (lambda image, img_id: reshape_fn(image, img_id, config))\r\n        ds = ds.map(operations=compose_map_func, input_columns=[\"image\", \"img_id\"],\r\n                    output_columns=[\"image\", \"image_shape\", \"img_id\"],\r\n                    column_order=[\"image\", \"image_shape\", \"img_id\"],\r\n                    num_parallel_workers=8)\r\n        ds = ds.map(operations=hwc_to_chw, input_columns=[\"image\"], num_parallel_workers=8)\r\n        ds = ds.batch(batch_size, drop_remainder=True)\r\n    ds = ds.repeat(max_epoch)\r\n\r\n    return ds, len(yolo_dataset)\r\n"
  },
  {
    "path": "examples/model_security/model_attacks/white_box/__init__.py",
    "content": ""
  },
  {
    "path": "examples/model_security/model_attacks/white_box/mnist_attack_cw.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport time\nimport numpy as np\nfrom scipy.special import softmax\n\nfrom mindspore import Model\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\n\nfrom mindarmour.adv_robustness.attacks import CarliniWagnerL2Attack\nfrom mindarmour.adv_robustness.evaluations import AttackEvaluate\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'CW_Test'\n\n\ndef test_carlini_wagner_attack():\n    \"\"\"\n    CW-Attack test\n    \"\"\"\n    # upload trained network\n    ckpt_path = '../../../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get test data\n    data_list = \"../../../common/dataset/MNIST/test\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size=batch_size)\n\n    # prediction accuracy before attack\n    model = Model(net)\n    batch_num = 3  # the number of batches of attacking samples\n    test_images = []\n    test_labels = []\n    predict_labels = []\n    i = 0\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        i += 1\n        images = data[0].astype(np.float32)\n        labels = data[1]\n        test_images.append(images)\n        test_labels.append(labels)\n        pred_labels = np.argmax(model.predict(Tensor(images)).asnumpy(),\n                                axis=1)\n        predict_labels.append(pred_labels)\n        if i >= batch_num:\n            break\n    predict_labels = np.concatenate(predict_labels)\n    true_labels = np.concatenate(test_labels)\n    accuracy = np.mean(np.equal(predict_labels, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %s\", accuracy)\n\n    # attacking\n    num_classes = 10\n    attack = CarliniWagnerL2Attack(net, num_classes, targeted=False)\n    start_time = time.clock()\n    adv_data = attack.batch_generate(np.concatenate(test_images),\n                                     np.concatenate(test_labels), batch_size=32)\n    stop_time = time.clock()\n    pred_logits_adv = model.predict(Tensor(adv_data)).asnumpy()\n    # rescale predict confidences into (0, 1).\n    pred_logits_adv = softmax(pred_logits_adv, axis=1)\n    pred_labels_adv = np.argmax(pred_logits_adv, axis=1)\n    accuracy_adv = np.mean(np.equal(pred_labels_adv, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy after attacking is : %s\",\n                accuracy_adv)\n    test_labels = np.eye(10)[np.concatenate(test_labels)]\n    attack_evaluate = AttackEvaluate(np.concatenate(test_images).transpose(0, 2, 3, 1),\n                                     test_labels, adv_data.transpose(0, 2, 3, 1),\n                                     pred_logits_adv)\n    LOGGER.info(TAG, 'mis-classification rate of adversaries is : %s',\n                attack_evaluate.mis_classification_rate())\n    LOGGER.info(TAG, 'The average confidence of adversarial class is : %s',\n                attack_evaluate.avg_conf_adv_class())\n    LOGGER.info(TAG, 'The average confidence of true class is : %s',\n                attack_evaluate.avg_conf_true_class())\n    LOGGER.info(TAG, 'The average distance (l0, l2, linf) between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_lp_distance())\n    LOGGER.info(TAG, 'The average structural similarity between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_ssim())\n    LOGGER.info(TAG, 'The average costing time is %s',\n                (stop_time - start_time)/(batch_num*batch_size))\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    test_carlini_wagner_attack()\n"
  },
  {
    "path": "examples/model_security/model_attacks/white_box/mnist_attack_deepfool.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport time\nimport numpy as np\nfrom scipy.special import softmax\n\nfrom mindspore import Model\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\n\nfrom mindarmour.adv_robustness.attacks.deep_fool import DeepFool\nfrom mindarmour.adv_robustness.evaluations import AttackEvaluate\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'DeepFool_Test'\n\n\ndef test_deepfool_attack():\n    \"\"\"\n    DeepFool-Attack test\n    \"\"\"\n    # upload trained network\n    ckpt_path = '../../../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get test data\n    data_list = \"../../../common/dataset/MNIST/test\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size=batch_size)\n\n    # prediction accuracy before attack\n    model = Model(net)\n    batch_num = 3  # the number of batches of attacking samples\n    test_images = []\n    test_labels = []\n    predict_labels = []\n    i = 0\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        i += 1\n        images = data[0].astype(np.float32)\n        labels = data[1]\n        test_images.append(images)\n        test_labels.append(labels)\n        pred_labels = np.argmax(model.predict(Tensor(images)).asnumpy(),\n                                axis=1)\n        predict_labels.append(pred_labels)\n        if i >= batch_num:\n            break\n    predict_labels = np.concatenate(predict_labels)\n    true_labels = np.concatenate(test_labels)\n    accuracy = np.mean(np.equal(predict_labels, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %s\", accuracy)\n\n    # attacking\n    classes = 10\n    attack = DeepFool(net, classes, norm_level=2,\n                      bounds=(0.0, 1.0))\n    start_time = time.clock()\n    adv_data = attack.batch_generate(np.concatenate(test_images),\n                                     np.concatenate(test_labels), batch_size=32)\n    stop_time = time.clock()\n    pred_logits_adv = model.predict(Tensor(adv_data)).asnumpy()\n    # rescale predict confidences into (0, 1).\n    pred_logits_adv = softmax(pred_logits_adv, axis=1)\n    pred_labels_adv = np.argmax(pred_logits_adv, axis=1)\n    accuracy_adv = np.mean(np.equal(pred_labels_adv, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy after attacking is : %s\",\n                accuracy_adv)\n    test_labels = np.eye(10)[np.concatenate(test_labels)]\n    attack_evaluate = AttackEvaluate(np.concatenate(test_images).transpose(0, 2, 3, 1),\n                                     test_labels, adv_data.transpose(0, 2, 3, 1),\n                                     pred_logits_adv)\n    LOGGER.info(TAG, 'mis-classification rate of adversaries is : %s',\n                attack_evaluate.mis_classification_rate())\n    LOGGER.info(TAG, 'The average confidence of adversarial class is : %s',\n                attack_evaluate.avg_conf_adv_class())\n    LOGGER.info(TAG, 'The average confidence of true class is : %s',\n                attack_evaluate.avg_conf_true_class())\n    LOGGER.info(TAG, 'The average distance (l0, l2, linf) between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_lp_distance())\n    LOGGER.info(TAG, 'The average structural similarity between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_ssim())\n    LOGGER.info(TAG, 'The average costing time is %s',\n                (stop_time - start_time)/(batch_num*batch_size))\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    test_deepfool_attack()\n"
  },
  {
    "path": "examples/model_security/model_attacks/white_box/mnist_attack_fgsm.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport time\nimport numpy as np\nfrom scipy.special import softmax\n\nfrom mindspore import Model\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nfrom mindspore.nn import SoftmaxCrossEntropyWithLogits\n\nfrom mindarmour.adv_robustness.attacks import FastGradientSignMethod\nfrom mindarmour.adv_robustness.evaluations import AttackEvaluate\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'FGSM_Test'\n\n\ndef test_fast_gradient_sign_method():\n    \"\"\"\n    FGSM-Attack test for CPU device.\n    \"\"\"\n    # upload trained network\n    ckpt_path = '../../../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get test data\n    data_list = \"../../../common/dataset/MNIST/test\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size)\n\n    # prediction accuracy before attack\n    model = Model(net)\n    batch_num = 3  # the number of batches of attacking samples\n    test_images = []\n    test_labels = []\n    predict_labels = []\n    i = 0\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        i += 1\n        images = data[0].astype(np.float32)\n        labels = data[1]\n        test_images.append(images)\n        test_labels.append(labels)\n        pred_labels = np.argmax(model.predict(Tensor(images)).asnumpy(),\n                                axis=1)\n        predict_labels.append(pred_labels)\n        if i >= batch_num:\n            break\n    predict_labels = np.concatenate(predict_labels)\n    true_labels = np.concatenate(test_labels)\n    accuracy = np.mean(np.equal(predict_labels, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %s\", accuracy)\n\n    # attacking\n    loss = SoftmaxCrossEntropyWithLogits(sparse=True)\n    attack = FastGradientSignMethod(net, eps=0.3, loss_fn=loss)\n    start_time = time.clock()\n    adv_data = attack.batch_generate(np.concatenate(test_images),\n                                     true_labels, batch_size=32)\n    stop_time = time.clock()\n    np.save('./adv_data', adv_data)\n    pred_logits_adv = model.predict(Tensor(adv_data)).asnumpy()\n    # rescale predict confidences into (0, 1).\n    pred_logits_adv = softmax(pred_logits_adv, axis=1)\n    pred_labels_adv = np.argmax(pred_logits_adv, axis=1)\n    accuracy_adv = np.mean(np.equal(pred_labels_adv, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy after attacking is : %s\", accuracy_adv)\n    attack_evaluate = AttackEvaluate(np.concatenate(test_images).transpose(0, 2, 3, 1),\n                                     np.eye(10)[true_labels],\n                                     adv_data.transpose(0, 2, 3, 1),\n                                     pred_logits_adv)\n    LOGGER.info(TAG, 'mis-classification rate of adversaries is : %s',\n                attack_evaluate.mis_classification_rate())\n    LOGGER.info(TAG, 'The average confidence of adversarial class is : %s',\n                attack_evaluate.avg_conf_adv_class())\n    LOGGER.info(TAG, 'The average confidence of true class is : %s',\n                attack_evaluate.avg_conf_true_class())\n    LOGGER.info(TAG, 'The average distance (l0, l2, linf) between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_lp_distance())\n    LOGGER.info(TAG, 'The average structural similarity between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_ssim())\n    LOGGER.info(TAG, 'The average costing time is %s',\n                (stop_time - start_time)/(batch_num*batch_size))\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    test_fast_gradient_sign_method()\n"
  },
  {
    "path": "examples/model_security/model_attacks/white_box/mnist_attack_jsma.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport time\nimport numpy as np\nfrom scipy.special import softmax\n\nfrom mindspore import Model\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\n\nfrom mindarmour.adv_robustness.attacks import JSMAAttack\nfrom mindarmour.adv_robustness.evaluations import AttackEvaluate\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'JSMA_Test'\n\n\ndef test_jsma_attack():\n    \"\"\"\n    JSMA-Attack test\n    \"\"\"\n    # upload trained network\n    ckpt_path = '../../../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get test data\n    data_list = \"../../../common/dataset/MNIST/test\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size=batch_size)\n\n    # prediction accuracy before attack\n    model = Model(net)\n    batch_num = 3  # the number of batches of attacking samples\n    test_images = []\n    test_labels = []\n    predict_labels = []\n    i = 0\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        i += 1\n        images = data[0].astype(np.float32)\n        labels = data[1]\n        test_images.append(images)\n        test_labels.append(labels)\n        pred_labels = np.argmax(model.predict(Tensor(images)).asnumpy(),\n                                axis=1)\n        predict_labels.append(pred_labels)\n        if i >= batch_num:\n            break\n    predict_labels = np.concatenate(predict_labels)\n    true_labels = np.concatenate(test_labels)\n    targeted_labels = np.random.randint(0, 10, size=len(true_labels))\n    for i, true_l in enumerate(true_labels):\n        if targeted_labels[i] == true_l:\n            targeted_labels[i] = (targeted_labels[i] + 1) % 10\n    accuracy = np.mean(np.equal(predict_labels, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %g\", accuracy)\n\n    # attacking\n    classes = 10\n    attack = JSMAAttack(net, classes)\n    start_time = time.clock()\n    adv_data = attack.batch_generate(np.concatenate(test_images),\n                                     targeted_labels, batch_size=32)\n    stop_time = time.clock()\n    pred_logits_adv = model.predict(Tensor(adv_data)).asnumpy()\n    # rescale predict confidences into (0, 1).\n    pred_logits_adv = softmax(pred_logits_adv, axis=1)\n    pred_lables_adv = np.argmax(pred_logits_adv, axis=1)\n    accuracy_adv = np.mean(np.equal(pred_lables_adv, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy after attacking is : %g\",\n                accuracy_adv)\n    test_labels = np.eye(10)[np.concatenate(test_labels)]\n    attack_evaluate = AttackEvaluate(\n        np.concatenate(test_images).transpose(0, 2, 3, 1),\n        test_labels, adv_data.transpose(0, 2, 3, 1),\n        pred_logits_adv, targeted=True, target_label=targeted_labels)\n    LOGGER.info(TAG, 'mis-classification rate of adversaries is : %s',\n                attack_evaluate.mis_classification_rate())\n    LOGGER.info(TAG, 'The average confidence of adversarial class is : %s',\n                attack_evaluate.avg_conf_adv_class())\n    LOGGER.info(TAG, 'The average confidence of true class is : %s',\n                attack_evaluate.avg_conf_true_class())\n    LOGGER.info(TAG, 'The average distance (l0, l2, linf) between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_lp_distance())\n    LOGGER.info(TAG, 'The average structural similarity between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_ssim())\n    LOGGER.info(TAG, 'The average costing time is %s',\n                (stop_time - start_time) / (batch_num*batch_size))\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    test_jsma_attack()\n"
  },
  {
    "path": "examples/model_security/model_attacks/white_box/mnist_attack_lbfgs.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport time\nimport numpy as np\nfrom scipy.special import softmax\n\nfrom mindspore import Model\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nfrom mindspore.nn import SoftmaxCrossEntropyWithLogits\n\nfrom mindarmour.adv_robustness.attacks import LBFGS\nfrom mindarmour.adv_robustness.evaluations import AttackEvaluate\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'LBFGS_Test'\n\n\ndef test_lbfgs_attack():\n    \"\"\"\n    LBFGS-Attack test for CPU device.\n    \"\"\"\n    # upload trained network\n    ckpt_path = '../../../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get test data\n    data_list = \"../../../common/dataset/MNIST/test\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size=batch_size)\n\n    # prediction accuracy before attack\n    model = Model(net)\n    batch_num = 3  # the number of batches of attacking samples\n    test_images = []\n    test_labels = []\n    predict_labels = []\n    i = 0\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        i += 1\n        images = data[0].astype(np.float32)\n        labels = data[1]\n        test_images.append(images)\n        test_labels.append(labels)\n        pred_labels = np.argmax(model.predict(Tensor(images)).asnumpy(),\n                                axis=1)\n        predict_labels.append(pred_labels)\n        if i >= batch_num:\n            break\n    predict_labels = np.concatenate(predict_labels)\n    true_labels = np.concatenate(test_labels)\n    accuracy = np.mean(np.equal(predict_labels, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %s\", accuracy)\n\n    # attacking\n    is_targeted = True\n    if is_targeted:\n        targeted_labels = np.random.randint(0, 10, size=len(true_labels)).astype(np.int32)\n        for i, true_l in enumerate(true_labels):\n            if targeted_labels[i] == true_l:\n                targeted_labels[i] = (targeted_labels[i] + 1) % 10\n    else:\n        targeted_labels = true_labels.astype(np.int32)\n    loss = SoftmaxCrossEntropyWithLogits(sparse=True)\n    attack = LBFGS(net, is_targeted=is_targeted, loss_fn=loss)\n    start_time = time.clock()\n    adv_data = attack.batch_generate(np.concatenate(test_images),\n                                     targeted_labels,\n                                     batch_size=batch_size)\n    stop_time = time.clock()\n    pred_logits_adv = model.predict(Tensor(adv_data)).asnumpy()\n    # rescale predict confidences into (0, 1).\n    pred_logits_adv = softmax(pred_logits_adv, axis=1)\n    pred_labels_adv = np.argmax(pred_logits_adv, axis=1)\n\n    accuracy_adv = np.mean(np.equal(pred_labels_adv, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy after attacking is : %s\",\n                accuracy_adv)\n    attack_evaluate = AttackEvaluate(np.concatenate(test_images).transpose(0, 2, 3, 1),\n                                     np.eye(10)[true_labels],\n                                     adv_data.transpose(0, 2, 3, 1),\n                                     pred_logits_adv,\n                                     targeted=is_targeted,\n                                     target_label=targeted_labels)\n    LOGGER.info(TAG, 'mis-classification rate of adversaries is : %s',\n                attack_evaluate.mis_classification_rate())\n    LOGGER.info(TAG, 'The average confidence of adversarial class is : %s',\n                attack_evaluate.avg_conf_adv_class())\n    LOGGER.info(TAG, 'The average confidence of true class is : %s',\n                attack_evaluate.avg_conf_true_class())\n    LOGGER.info(TAG, 'The average distance (l0, l2, linf) between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_lp_distance())\n    LOGGER.info(TAG, 'The average structural similarity between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_ssim())\n    LOGGER.info(TAG, 'The average costing time is %s',\n                (stop_time - start_time)/(batch_num*batch_size))\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    test_lbfgs_attack()\n"
  },
  {
    "path": "examples/model_security/model_attacks/white_box/mnist_attack_mdi2fgsm.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport time\nimport numpy as np\nfrom scipy.special import softmax\n\nfrom mindspore import Model\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nfrom mindspore.nn import SoftmaxCrossEntropyWithLogits\n\nfrom mindarmour.adv_robustness.attacks import MomentumDiverseInputIterativeMethod\nfrom mindarmour.adv_robustness.evaluations import AttackEvaluate\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\n\nLOGGER = LogUtil.get_instance()\nTAG = 'M_DI2_FGSM_Test'\nLOGGER.set_level('INFO')\n\n\ndef test_momentum_diverse_input_iterative_method():\n    \"\"\"\n    M-DI2-FGSM Attack Test for CPU device.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    # upload trained network\n    ckpt_path = '../../../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get test data\n    data_list = \"../../../common/dataset/MNIST/test\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size)\n\n    # prediction accuracy before attack\n    model = Model(net)\n    batch_num = 32  # the number of batches of attacking samples\n    test_images = []\n    test_labels = []\n    predict_labels = []\n    i = 0\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        i += 1\n        images = data[0].astype(np.float32)\n        labels = data[1]\n        test_images.append(images)\n        test_labels.append(labels)\n        pred_labels = np.argmax(model.predict(Tensor(images)).asnumpy(),\n                                axis=1)\n        predict_labels.append(pred_labels)\n        if i >= batch_num:\n            break\n    predict_labels = np.concatenate(predict_labels)\n    true_labels = np.concatenate(test_labels)\n    accuracy = np.mean(np.equal(predict_labels, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %s\", accuracy)\n\n    # attacking\n    loss = SoftmaxCrossEntropyWithLogits(sparse=True)\n    attack = MomentumDiverseInputIterativeMethod(net, loss_fn=loss)\n    start_time = time.clock()\n    adv_data = attack.batch_generate(np.concatenate(test_images),\n                                     true_labels, batch_size=32)\n    stop_time = time.clock()\n    pred_logits_adv = model.predict(Tensor(adv_data)).asnumpy()\n    # rescale predict confidences into (0, 1).\n    pred_logits_adv = softmax(pred_logits_adv, axis=1)\n    pred_labels_adv = np.argmax(pred_logits_adv, axis=1)\n    accuracy_adv = np.mean(np.equal(pred_labels_adv, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy after attacking is : %s\", accuracy_adv)\n    attack_evaluate = AttackEvaluate(np.concatenate(test_images).transpose(0, 2, 3, 1),\n                                     np.eye(10)[true_labels],\n                                     adv_data.transpose(0, 2, 3, 1),\n                                     pred_logits_adv)\n    LOGGER.info(TAG, 'mis-classification rate of adversaries is : %s',\n                attack_evaluate.mis_classification_rate())\n    LOGGER.info(TAG, 'The average confidence of adversarial class is : %s',\n                attack_evaluate.avg_conf_adv_class())\n    LOGGER.info(TAG, 'The average confidence of true class is : %s',\n                attack_evaluate.avg_conf_true_class())\n    LOGGER.info(TAG, 'The average distance (l0, l2, linf) between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_lp_distance())\n    LOGGER.info(TAG, 'The average structural similarity between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_ssim())\n    LOGGER.info(TAG, 'The average costing time is %s',\n                (stop_time - start_time)/(batch_num*batch_size))\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    test_momentum_diverse_input_iterative_method()\n"
  },
  {
    "path": "examples/model_security/model_attacks/white_box/mnist_attack_pgd.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport time\nimport numpy as np\nfrom scipy.special import softmax\n\nfrom mindspore import Model\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nfrom mindspore.nn import SoftmaxCrossEntropyWithLogits\n\nfrom mindarmour.adv_robustness.attacks import ProjectedGradientDescent\nfrom mindarmour.adv_robustness.evaluations import AttackEvaluate\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'PGD_Test'\n\n\ndef test_projected_gradient_descent_method():\n    \"\"\"\n    PGD-Attack test for CPU device.\n    \"\"\"\n    # upload trained network\n    ckpt_path = '../../../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get test data\n    data_list = \"../../../common/dataset/MNIST/test\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size)\n\n    # prediction accuracy before attack\n    model = Model(net)\n    batch_num = 32  # the number of batches of attacking samples\n    test_images = []\n    test_labels = []\n    predict_labels = []\n    i = 0\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        i += 1\n        images = data[0].astype(np.float32)\n        labels = data[1]\n        test_images.append(images)\n        test_labels.append(labels)\n        pred_labels = np.argmax(model.predict(Tensor(images)).asnumpy(),\n                                axis=1)\n        predict_labels.append(pred_labels)\n        if i >= batch_num:\n            break\n    predict_labels = np.concatenate(predict_labels)\n    true_labels = np.concatenate(test_labels)\n    accuracy = np.mean(np.equal(predict_labels, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %s\", accuracy)\n\n    # attacking\n    loss = SoftmaxCrossEntropyWithLogits(sparse=True)\n    attack = ProjectedGradientDescent(net, eps=0.3, loss_fn=loss)\n    start_time = time.process_time()\n    adv_data = attack.batch_generate(np.concatenate(test_images),\n                                     true_labels, batch_size=32)\n    stop_time = time.process_time()\n    np.save('./adv_data', adv_data)\n    pred_logits_adv = model.predict(Tensor(adv_data)).asnumpy()\n    # rescale predict confidences into (0, 1).\n    pred_logits_adv = softmax(pred_logits_adv, axis=1)\n    pred_labels_adv = np.argmax(pred_logits_adv, axis=1)\n    accuracy_adv = np.mean(np.equal(pred_labels_adv, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy after attacking is : %s\", accuracy_adv)\n    attack_evaluate = AttackEvaluate(np.concatenate(test_images).transpose(0, 2, 3, 1),\n                                     np.eye(10)[true_labels],\n                                     adv_data.transpose(0, 2, 3, 1),\n                                     pred_logits_adv)\n    LOGGER.info(TAG, 'mis-classification rate of adversaries is : %s',\n                attack_evaluate.mis_classification_rate())\n    LOGGER.info(TAG, 'The average confidence of adversarial class is : %s',\n                attack_evaluate.avg_conf_adv_class())\n    LOGGER.info(TAG, 'The average confidence of true class is : %s',\n                attack_evaluate.avg_conf_true_class())\n    LOGGER.info(TAG, 'The average distance (l0, l2, linf) between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_lp_distance())\n    LOGGER.info(TAG, 'The average structural similarity between original '\n                     'samples and adversarial samples are: %s',\n                attack_evaluate.avg_ssim())\n    LOGGER.info(TAG, 'The average costing time is %s',\n                (stop_time - start_time)/(batch_num*batch_size))\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    test_projected_gradient_descent_method()\n"
  },
  {
    "path": "examples/model_security/model_attacks/white_box/mnist_attack_vmifgsm.py",
    "content": "# Copyright 2023 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\nimport time\r\nimport numpy as np\r\nfrom scipy.special import softmax\r\n\r\nfrom mindspore import Model\r\nfrom mindspore import Tensor\r\nfrom mindspore import context\r\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\r\nfrom mindspore.nn import SoftmaxCrossEntropyWithLogits\r\n\r\nfrom mindarmour.adv_robustness.attacks import VarianceTuningMomentumIterativeMethod\r\nfrom mindarmour.adv_robustness.evaluations import AttackEvaluate\r\nfrom mindarmour.utils.logger import LogUtil\r\n\r\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\r\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\r\n\r\nLOGGER = LogUtil.get_instance()\r\nLOGGER.set_level('INFO')\r\nTAG = 'VMI_Test'\r\n\r\n\r\n\r\ndef test_variance_tuning_momentum_iterative_method():\r\n    \"\"\"\r\n    test for CPU device.\r\n    \"\"\"\r\n    # upload trained network\r\n    ckpt_path = '../../../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\r\n    net = LeNet5()\r\n    load_dict = load_checkpoint(ckpt_path)\r\n    load_param_into_net(net, load_dict)\r\n\r\n    # get test data\r\n    data_list = \"../../../common/dataset/MNIST/test\"\r\n    batch_size = 32\r\n    ds = generate_mnist_dataset(data_list, batch_size)\r\n\r\n    # prediction accuracy before attack\r\n    model = Model(net)\r\n    batch_num = 32  # the number of batches of attacking samples\r\n    test_images = []\r\n    test_labels = []\r\n    predict_labels = []\r\n    i = 0\r\n    for data in ds.create_tuple_iterator(output_numpy=True):\r\n        i += 1\r\n        images = data[0].astype(np.float32)\r\n        labels = data[1]\r\n        test_images.append(images)\r\n        test_labels.append(labels)\r\n        pred_labels = np.argmax(model.predict(Tensor(images)).asnumpy(),\r\n                                axis=1)\r\n        predict_labels.append(pred_labels)\r\n        if i >= batch_num:\r\n            break\r\n    predict_labels = np.concatenate(predict_labels)\r\n    true_labels = np.concatenate(test_labels)\r\n    accuracy = np.mean(np.equal(predict_labels, true_labels))\r\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %s\", accuracy)\r\n\r\n    # attacking\r\n    loss = SoftmaxCrossEntropyWithLogits(sparse=True)\r\n    attack = VarianceTuningMomentumIterativeMethod(net, eps=0.3, loss_fn=loss)\r\n    start_time = time.process_time()\r\n    adv_data = attack.batch_generate(np.concatenate(test_images),\r\n                                     true_labels, batch_size=32)\r\n    stop_time = time.process_time()\r\n    np.save('./adv_data', adv_data)\r\n    pred_logits_adv = model.predict(Tensor(adv_data)).asnumpy()\r\n    # rescale predict confidences into (0, 1).\r\n    pred_logits_adv = softmax(pred_logits_adv, axis=1)\r\n    pred_labels_adv = np.argmax(pred_logits_adv, axis=1)\r\n    accuracy_adv = np.mean(np.equal(pred_labels_adv, true_labels))\r\n    LOGGER.info(TAG, \"prediction accuracy after attacking is : %s\", accuracy_adv)\r\n    attack_evaluate = AttackEvaluate(np.concatenate(test_images).transpose(0, 2, 3, 1),\r\n                                     np.eye(10)[true_labels],\r\n                                     adv_data.transpose(0, 2, 3, 1),\r\n                                     pred_logits_adv)\r\n    LOGGER.info(TAG, 'mis-classification rate of adversaries is : %s',\r\n                attack_evaluate.mis_classification_rate())\r\n    LOGGER.info(TAG, 'The average confidence of adversarial class is : %s',\r\n                attack_evaluate.avg_conf_adv_class())\r\n    LOGGER.info(TAG, 'The average confidence of true class is : %s',\r\n                attack_evaluate.avg_conf_true_class())\r\n    LOGGER.info(TAG, 'The average distance (l0, l2, linf) between original '\r\n                     'samples and adversarial samples are: %s',\r\n                attack_evaluate.avg_lp_distance())\r\n    LOGGER.info(TAG, 'The average structural similarity between original '\r\n                     'samples and adversarial samples are: %s',\r\n                attack_evaluate.avg_ssim())\r\n    LOGGER.info(TAG, 'The average costing time is %s',\r\n                (stop_time - start_time)/(batch_num*batch_size))\r\n\r\n\r\nif __name__ == '__main__':\r\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\r\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\r\n    test_variance_tuning_momentum_iterative_method()\r\n"
  },
  {
    "path": "examples/model_security/model_defenses/__init__.py",
    "content": ""
  },
  {
    "path": "examples/model_security/model_defenses/mnist_defense_nad.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"defense example using nad\"\"\"\nimport os\n\nimport numpy as np\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore import nn, Model\nfrom mindspore.nn import SoftmaxCrossEntropyWithLogits\nfrom mindspore.train.callback import LossMonitor\n\nfrom mindarmour.adv_robustness.attacks import FastGradientSignMethod\nfrom mindarmour.adv_robustness.defenses import NaturalAdversarialDefense\nfrom mindarmour.utils import LogUtil\n\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\n\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level(\"INFO\")\nTAG = 'Nad_Example'\n\n\ndef test_nad_method():\n    \"\"\"\n    NAD-Defense test.\n    \"\"\"\n    mnist_path = \"../../common/dataset/MNIST\"\n    batch_size = 32\n    # 1. train original model\n    ds_train = generate_mnist_dataset(os.path.join(mnist_path, \"train\"),\n                                      batch_size=batch_size, repeat_size=1)\n    net = LeNet5()\n    loss = SoftmaxCrossEntropyWithLogits(sparse=True)\n    opt = nn.Momentum(net.trainable_params(), 0.01, 0.09)\n    model = Model(net, loss, opt, metrics=None)\n    model.train(10, ds_train, callbacks=[LossMonitor()],\n                dataset_sink_mode=False)\n\n    # 2. get test data\n    ds_test = generate_mnist_dataset(os.path.join(mnist_path, \"test\"),\n                                     batch_size=batch_size, repeat_size=1)\n    inputs = []\n    labels = []\n    for data in ds_test.create_tuple_iterator(output_numpy=True):\n        inputs.append(data[0].astype(np.float32))\n        labels.append(data[1])\n    inputs = np.concatenate(inputs)\n    labels = np.concatenate(labels)\n\n    # 3. get accuracy of test data on original model\n    net.set_train(False)\n    logits = net(Tensor(inputs)).asnumpy()\n    label_pred = np.argmax(logits, axis=1)\n    acc = np.mean(labels == label_pred)\n    LOGGER.info(TAG, 'accuracy of TEST data on original model is : %s', acc)\n\n    # 4. get adv of test data\n    attack = FastGradientSignMethod(net, eps=0.3, loss_fn=loss)\n    adv_data = attack.batch_generate(inputs, labels)\n    LOGGER.info(TAG, 'adv_data.shape is : %s', adv_data.shape)\n\n    # 5. get accuracy of adv data on original model\n    net.set_train(False)\n    logits = net(Tensor(adv_data)).asnumpy()\n    label_pred = np.argmax(logits, axis=1)\n    acc = np.mean(labels == label_pred)\n    LOGGER.info(TAG, 'accuracy of adv data on original model is : %s', acc)\n\n    # 6. defense\n    ds_train = generate_mnist_dataset(os.path.join(mnist_path, \"train\"),\n                                      batch_size=batch_size, repeat_size=1)\n    inputs_train = []\n    labels_train = []\n    for data in ds_train.create_tuple_iterator(output_numpy=True):\n        inputs_train.append(data[0].astype(np.float32))\n        labels_train.append(data[1])\n    inputs_train = np.concatenate(inputs_train)\n    labels_train = np.concatenate(labels_train)\n    net.set_train()\n    nad = NaturalAdversarialDefense(net, loss_fn=loss, optimizer=opt,\n                                    bounds=(0.0, 1.0), eps=0.3)\n    nad.batch_defense(inputs_train, labels_train, batch_size=32, epochs=10)\n\n    # 7. get accuracy of test data on defensed model\n    net.set_train(False)\n    logits = net(Tensor(inputs)).asnumpy()\n    label_pred = np.argmax(logits, axis=1)\n    acc = np.mean(labels == label_pred)\n    LOGGER.info(TAG, 'accuracy of TEST data on defensed model is : %s', acc)\n\n    # 8. get accuracy of adv data on defensed model\n    logits = net(Tensor(adv_data)).asnumpy()\n    label_pred = np.argmax(logits, axis=1)\n    acc = np.mean(labels == label_pred)\n    LOGGER.info(TAG, 'accuracy of adv data on defensed model is : %s', acc)\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    test_nad_method()\n"
  },
  {
    "path": "examples/model_security/model_defenses/mnist_evaluation.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n\"\"\"evaluate example\"\"\"\r\nimport os\r\nimport time\r\n\r\nimport numpy as np\r\nfrom mindspore import Model\r\nfrom mindspore import Tensor\r\nfrom mindspore import context\r\nfrom mindspore import nn\r\nfrom mindspore.nn import Cell\r\nfrom mindspore.nn import SoftmaxCrossEntropyWithLogits\r\nfrom mindspore.ops.operations import Add\r\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\r\nfrom scipy.special import softmax\r\n\r\nfrom mindarmour.adv_robustness.attacks import FastGradientSignMethod\r\nfrom mindarmour.adv_robustness.attacks import GeneticAttack\r\nfrom mindarmour.adv_robustness.attacks.black.black_model import BlackModel\r\nfrom mindarmour.adv_robustness.defenses import NaturalAdversarialDefense\r\nfrom mindarmour.adv_robustness.detectors import SimilarityDetector\r\nfrom mindarmour.adv_robustness.evaluations import BlackDefenseEvaluate\r\nfrom mindarmour.adv_robustness.evaluations import DefenseEvaluate\r\nfrom mindarmour.utils.logger import LogUtil\r\n\r\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\r\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\r\n\r\nLOGGER = LogUtil.get_instance()\r\nLOGGER.set_level('INFO')\r\nTAG = 'Defense_Evaluate_Example'\r\n\r\n\r\ndef get_detector(train_images):\r\n    encoder = Model(EncoderNet(encode_dim=256))\r\n    detector = SimilarityDetector(max_k_neighbor=50, trans_model=encoder)\r\n    detector.fit(inputs=train_images)\r\n    return detector\r\n\r\n\r\nclass EncoderNet(Cell):\r\n    \"\"\"\r\n    Similarity encoder for input data\r\n    \"\"\"\r\n\r\n    def __init__(self, encode_dim):\r\n        super(EncoderNet, self).__init__()\r\n        self._encode_dim = encode_dim\r\n        self.add = Add()\r\n\r\n    def construct(self, inputs):\r\n        \"\"\"\r\n        construct the neural network\r\n        Args:\r\n            inputs (Tensor): input data to neural network.\r\n        Returns:\r\n            Tensor, output of neural network.\r\n        \"\"\"\r\n        return self.add(inputs, inputs)\r\n\r\n    def get_encode_dim(self):\r\n        \"\"\"\r\n        Get the dimension of encoded inputs\r\n\r\n        Returns:\r\n            int, dimension of encoded inputs.\r\n        \"\"\"\r\n        return self._encode_dim\r\n\r\n\r\nclass ModelToBeAttacked(BlackModel):\r\n    \"\"\"\r\n    model to be attack\r\n    \"\"\"\r\n\r\n    def __init__(self, network, defense=False, train_images=None):\r\n        super(ModelToBeAttacked, self).__init__()\r\n        self._network = network\r\n        self._queries = []\r\n        self._defense = defense\r\n        self._detector = None\r\n        self._detected_res = []\r\n        if self._defense:\r\n            self._detector = get_detector(train_images)\r\n\r\n    def predict(self, inputs):\r\n        \"\"\"\r\n        predict function\r\n        \"\"\"\r\n        if len(inputs.shape) == 3:\r\n            inputs = np.expand_dims(inputs, axis=0)\r\n        query_num = inputs.shape[0]\r\n        results = []\r\n        if self._detector:\r\n            for i in range(query_num):\r\n                query = np.expand_dims(inputs[i].astype(np.float32), axis=0)\r\n                result = self._network(Tensor(query)).asnumpy()\r\n                det_num = len(self._detector.get_detected_queries())\r\n                self._detector.detect(np.array([query]))\r\n                new_det_num = len(self._detector.get_detected_queries())\r\n                # If attack query detected, return random predict result\r\n                if new_det_num > det_num:\r\n                    results.append(result + np.random.rand(*result.shape))\r\n                    self._detected_res.append(True)\r\n                else:\r\n                    results.append(result)\r\n                    self._detected_res.append(False)\r\n            results = np.concatenate(results)\r\n        else:\r\n            if len(inputs.shape) == 3:\r\n                inputs = np.expand_dims(inputs, axis=0)\r\n            results = self._network(Tensor(inputs.astype(np.float32))).asnumpy()\r\n        return results\r\n\r\n    def get_detected_result(self):\r\n        return self._detected_res\r\n\r\n\r\ndef test_defense_evaluation():\r\n    # load trained network\r\n    current_dir = os.path.dirname(os.path.abspath(__file__))\r\n    ckpt_path = os.path.abspath(os.path.join(\r\n        current_dir, '../../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'))\r\n    wb_net = LeNet5()\r\n    load_dict = load_checkpoint(ckpt_path)\r\n    load_param_into_net(wb_net, load_dict)\r\n\r\n    # get test data\r\n    data_list = \"../../common/dataset/MNIST/test\"\r\n    batch_size = 32\r\n    ds_test = generate_mnist_dataset(data_list, batch_size=batch_size)\r\n    inputs = []\r\n    labels = []\r\n    for data in ds_test.create_tuple_iterator(output_numpy=True):\r\n        inputs.append(data[0].astype(np.float32))\r\n        labels.append(data[1])\r\n    inputs = np.concatenate(inputs).astype(np.float32)\r\n    labels = np.concatenate(labels).astype(np.int32)\r\n\r\n    target_label = np.random.randint(0, 10, size=labels.shape[0])\r\n    for idx in range(labels.shape[0]):\r\n        while target_label[idx] == labels[idx]:\r\n            target_label[idx] = np.random.randint(0, 10)\r\n    target_label = np.eye(10)[target_label].astype(np.float32)\r\n\r\n    attacked_size = 50\r\n    benign_size = 500\r\n\r\n    attacked_sample = inputs[:attacked_size]\r\n    attacked_true_label = labels[:attacked_size]\r\n    benign_sample = inputs[attacked_size:attacked_size + benign_size]\r\n\r\n    wb_model = ModelToBeAttacked(wb_net)\r\n\r\n    # gen white-box adversarial examples of test data\r\n    loss = SoftmaxCrossEntropyWithLogits(sparse=True)\r\n    wb_attack = FastGradientSignMethod(wb_net, eps=0.3, loss_fn=loss)\r\n    wb_adv_sample = wb_attack.generate(attacked_sample,\r\n                                       attacked_true_label)\r\n\r\n    wb_raw_preds = softmax(wb_model.predict(wb_adv_sample), axis=1)\r\n    accuracy_test = np.mean(\r\n        np.equal(np.argmax(wb_model.predict(attacked_sample), axis=1),\r\n                 attacked_true_label))\r\n    LOGGER.info(TAG, \"prediction accuracy before white-box attack is : %s\",\r\n                accuracy_test)\r\n    accuracy_adv = np.mean(np.equal(np.argmax(wb_raw_preds, axis=1),\r\n                                    attacked_true_label))\r\n    LOGGER.info(TAG, \"prediction accuracy after white-box attack is : %s\",\r\n                accuracy_adv)\r\n\r\n    # improve the robustness of model with white-box adversarial examples\r\n    opt = nn.Momentum(wb_net.trainable_params(), 0.01, 0.09)\r\n\r\n    nad = NaturalAdversarialDefense(wb_net, loss_fn=loss, optimizer=opt,\r\n                                    bounds=(0.0, 1.0), eps=0.3)\r\n    wb_net.set_train(False)\r\n    nad.batch_defense(inputs[:5000], labels[:5000], batch_size=32, epochs=10)\r\n\r\n    wb_def_preds = wb_net(Tensor(wb_adv_sample)).asnumpy()\r\n    wb_def_preds = softmax(wb_def_preds, axis=1)\r\n    accuracy_def = np.mean(np.equal(np.argmax(wb_def_preds, axis=1),\r\n                                    attacked_true_label))\r\n    LOGGER.info(TAG, \"prediction accuracy after defense is : %s\", accuracy_def)\r\n\r\n    # calculate defense evaluation metrics for defense against white-box attack\r\n    wb_def_evaluate = DefenseEvaluate(wb_raw_preds, wb_def_preds,\r\n                                      attacked_true_label)\r\n    LOGGER.info(TAG, 'defense evaluation for white-box adversarial attack')\r\n    LOGGER.info(TAG,\r\n                'classification accuracy variance (CAV) is : {:.2f}'.format(\r\n                    wb_def_evaluate.cav()))\r\n    LOGGER.info(TAG, 'classification rectify ratio (CRR) is : {:.2f}'.format(\r\n        wb_def_evaluate.crr()))\r\n    LOGGER.info(TAG, 'classification sacrifice ratio (CSR) is : {:.2f}'.format(\r\n        wb_def_evaluate.csr()))\r\n    LOGGER.info(TAG,\r\n                'classification confidence variance (CCV) is : {:.2f}'.format(\r\n                    wb_def_evaluate.ccv()))\r\n    LOGGER.info(TAG, 'classification output stability is : {:.2f}'.format(\r\n        wb_def_evaluate.cos()))\r\n\r\n    # calculate defense evaluation metrics for defense against black-box attack\r\n    LOGGER.info(TAG, 'defense evaluation for black-box adversarial attack')\r\n    bb_raw_preds = []\r\n    bb_def_preds = []\r\n    raw_query_counts = []\r\n    raw_query_time = []\r\n    def_query_counts = []\r\n    def_query_time = []\r\n    def_detection_counts = []\r\n\r\n    # gen black-box adversarial examples of test data\r\n    bb_net = LeNet5()\r\n    load_param_into_net(bb_net, load_dict)\r\n    bb_model = ModelToBeAttacked(bb_net, defense=False)\r\n    attack_rm = GeneticAttack(model=bb_model, pop_size=6, mutation_rate=0.05,\r\n                              per_bounds=0.5, step_size=0.25, temp=0.1,\r\n                              sparse=False)\r\n    attack_target_label = target_label[:attacked_size]\r\n    true_label = labels[:attacked_size + benign_size]\r\n    # evaluate robustness of original model\r\n    # gen black-box adversarial examples of test data\r\n    for idx in range(attacked_size):\r\n        raw_st = time.time()\r\n        _, raw_a, raw_qc = attack_rm.generate(\r\n            np.expand_dims(attacked_sample[idx], axis=0),\r\n            np.expand_dims(attack_target_label[idx], axis=0))\r\n        raw_t = time.time() - raw_st\r\n        bb_raw_preds.extend(softmax(bb_model.predict(raw_a), axis=1))\r\n        raw_query_counts.extend(raw_qc)\r\n        raw_query_time.append(raw_t)\r\n\r\n    for idx in range(benign_size):\r\n        raw_st = time.time()\r\n        bb_raw_pred = softmax(\r\n            bb_model.predict(np.expand_dims(benign_sample[idx], axis=0)),\r\n            axis=1)\r\n        raw_t = time.time() - raw_st\r\n        bb_raw_preds.extend(bb_raw_pred)\r\n        raw_query_counts.extend([0])\r\n        raw_query_time.append(raw_t)\r\n\r\n    accuracy_test = np.mean(\r\n        np.equal(np.argmax(bb_raw_preds[0:len(attack_target_label)], axis=1),\r\n                 np.argmax(attack_target_label, axis=1)))\r\n    LOGGER.info(TAG, \"attack success before adv defense is : %s\",\r\n                accuracy_test)\r\n\r\n    # improve the robustness of model with similarity-based detector\r\n    bb_def_model = ModelToBeAttacked(bb_net, defense=True,\r\n                                     train_images=inputs[0:6000])\r\n    # attack defensed model\r\n    attack_dm = GeneticAttack(model=bb_def_model, pop_size=6,\r\n                              mutation_rate=0.05,\r\n                              per_bounds=0.5, step_size=0.25, temp=0.1,\r\n                              sparse=False)\r\n    for idx in range(attacked_size):\r\n        def_st = time.time()\r\n        _, def_a, def_qc = attack_dm.generate(\r\n            np.expand_dims(attacked_sample[idx], axis=0),\r\n            np.expand_dims(attack_target_label[idx], axis=0))\r\n        def_t = time.time() - def_st\r\n        det_res = bb_def_model.get_detected_result()\r\n        def_detection_counts.append(np.sum(det_res[-def_qc[0]:]))\r\n        bb_def_preds.extend(softmax(bb_def_model.predict(def_a), axis=1))\r\n        def_query_counts.extend(def_qc)\r\n        def_query_time.append(def_t)\r\n\r\n    for idx in range(benign_size):\r\n        def_st = time.time()\r\n        bb_def_pred = softmax(\r\n            bb_def_model.predict(np.expand_dims(benign_sample[idx], axis=0)),\r\n            axis=1)\r\n        def_t = time.time() - def_st\r\n        det_res = bb_def_model.get_detected_result()\r\n        def_detection_counts.append(np.sum(det_res[-1]))\r\n        bb_def_preds.extend(bb_def_pred)\r\n        def_query_counts.extend([0])\r\n        def_query_time.append(def_t)\r\n\r\n    accuracy_adv = np.mean(\r\n        np.equal(np.argmax(bb_def_preds[0:len(attack_target_label)], axis=1),\r\n                 np.argmax(attack_target_label, axis=1)))\r\n    LOGGER.info(TAG, \"attack success rate after adv defense is : %s\",\r\n                accuracy_adv)\r\n\r\n    bb_raw_preds = np.array(bb_raw_preds).astype(np.float32)\r\n    bb_def_preds = np.array(bb_def_preds).astype(np.float32)\r\n    # check evaluate data\r\n    max_queries = 6000\r\n\r\n    def_evaluate = BlackDefenseEvaluate(bb_raw_preds, bb_def_preds,\r\n                                        np.array(raw_query_counts),\r\n                                        np.array(def_query_counts),\r\n                                        np.array(raw_query_time),\r\n                                        np.array(def_query_time),\r\n                                        np.array(def_detection_counts),\r\n                                        true_label, max_queries)\r\n\r\n    LOGGER.info(TAG, 'query count variance of adversaries is : {:.2f}'.format(\r\n        def_evaluate.qcv()))\r\n    LOGGER.info(TAG, 'attack success rate variance of adversaries '\r\n                     'is : {:.2f}'.format(def_evaluate.asv()))\r\n    LOGGER.info(TAG, 'false positive rate (FPR) of the query-based detector '\r\n                     'is : {:.2f}'.format(def_evaluate.fpr()))\r\n    LOGGER.info(TAG, 'the benign query response time variance (QRV) '\r\n                     'is : {:.2f}'.format(def_evaluate.qrv()))\r\n\r\n\r\nif __name__ == '__main__':\r\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\r\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"GPU\")\r\n    DEVICE = context.get_context(\"device_target\")\r\n    if DEVICE in (\"Ascend\", \"GPU\"):\r\n        test_defense_evaluation()\r\n"
  },
  {
    "path": "examples/model_security/model_defenses/mnist_similarity_detector.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport numpy as np\nfrom scipy.special import softmax\n\nfrom mindspore import Model\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.nn import Cell\nfrom mindspore.ops.operations import Add\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\n\nfrom mindarmour import BlackModel\nfrom mindarmour.adv_robustness.attacks.black.pso_attack import PSOAttack\nfrom mindarmour.adv_robustness.detectors import SimilarityDetector\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'Similarity Detector test'\n\n\nclass ModelToBeAttacked(BlackModel):\n    \"\"\"\n    model to be attack\n    \"\"\"\n\n    def __init__(self, network):\n        super(ModelToBeAttacked, self).__init__()\n        self._network = network\n        self._queries = []\n\n    def predict(self, inputs):\n        \"\"\"\n        predict function\n        \"\"\"\n        query_num = inputs.shape[0]\n        for i in range(query_num):\n            if len(inputs[i].shape) == 2:\n                temp = np.expand_dims(inputs[i], axis=0)\n            else:\n                temp = inputs[i]\n            self._queries.append(temp.astype(np.float32))\n        if len(inputs.shape) == 3:\n            inputs = np.expand_dims(inputs, axis=0)\n        result = self._network(Tensor(inputs.astype(np.float32)))\n        return result.asnumpy()\n\n    def get_queries(self):\n        return self._queries\n\n\nclass EncoderNet(Cell):\n    \"\"\"\n    Similarity encoder for input data\n    \"\"\"\n\n    def __init__(self, encode_dim):\n        super(EncoderNet, self).__init__()\n        self._encode_dim = encode_dim\n        self.add = Add()\n\n    def construct(self, inputs):\n        \"\"\"\n        construct the neural network\n        Args:\n            inputs (Tensor): input data to neural network.\n        Returns:\n            Tensor, output of neural network.\n        \"\"\"\n        return self.add(inputs, inputs)\n\n    def get_encode_dim(self):\n        \"\"\"\n        Get the dimension of encoded inputs\n\n        Returns:\n            int, dimension of encoded inputs.\n        \"\"\"\n        return self._encode_dim\n\n\ndef test_similarity_detector():\n    \"\"\"\n    Similarity Detector test.\n    \"\"\"\n    # load trained network\n    ckpt_path = '../../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get mnist data\n    data_list = \"../../common/dataset/MNIST/test\"\n    batch_size = 1000\n    ds = generate_mnist_dataset(data_list, batch_size=batch_size)\n    model = ModelToBeAttacked(net)\n\n    batch_num = 10  # the number of batches of input samples\n    all_images = []\n    true_labels = []\n    predict_labels = []\n    i = 0\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        i += 1\n        images = data[0].astype(np.float32)\n        labels = data[1]\n        all_images.append(images)\n        true_labels.append(labels)\n        pred_labels = np.argmax(model.predict(images), axis=1)\n        predict_labels.append(pred_labels)\n        if i >= batch_num:\n            break\n    all_images = np.concatenate(all_images)\n    true_labels = np.concatenate(true_labels)\n    predict_labels = np.concatenate(predict_labels)\n    accuracy = np.mean(np.equal(predict_labels, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %s\", accuracy)\n\n    train_images = all_images[0:6000, :, :, :]\n    attacked_images = all_images[0:10, :, :, :]\n    attacked_labels = true_labels[0:10]\n\n    # generate malicious query sequence of black attack\n    attack = PSOAttack(model, bounds=(0.0, 1.0), pm=0.5, sparse=True,\n                       t_max=1000)\n    success_list, adv_data, query_list = attack.generate(attacked_images,\n                                                         attacked_labels)\n    LOGGER.info(TAG, 'pso attack success_list: %s', success_list)\n    LOGGER.info(TAG, 'average of query counts is : %s', np.mean(query_list))\n    pred_logits_adv = model.predict(adv_data)\n    # rescale predict confidences into (0, 1).\n    pred_logits_adv = softmax(pred_logits_adv, axis=1)\n    pred_lables_adv = np.argmax(pred_logits_adv, axis=1)\n    accuracy_adv = np.mean(np.equal(pred_lables_adv, attacked_labels))\n    LOGGER.info(TAG, \"prediction accuracy after attacking is : %g\",\n                accuracy_adv)\n\n    benign_queries = all_images[6000:10000, :, :, :]\n    suspicious_queries = model.get_queries()\n\n    # explicit threshold not provided, calculate threshold for K\n    encoder = Model(EncoderNet(encode_dim=256))\n    detector = SimilarityDetector(max_k_neighbor=50, trans_model=encoder)\n    detector.fit(inputs=train_images)\n\n    # test benign queries\n    detector.detect(benign_queries)\n    fpr = len(detector.get_detected_queries()) / benign_queries.shape[0]\n    LOGGER.info(TAG, 'Number of false positive of attack detector is : %s',\n                len(detector.get_detected_queries()))\n    LOGGER.info(TAG, 'False positive rate of attack detector is : %s', fpr)\n\n    # test attack queries\n    detector.clear_buffer()\n    detector.detect(np.array(suspicious_queries))\n    LOGGER.info(TAG, 'Number of detected attack queries is : %s',\n                len(detector.get_detected_queries()))\n    LOGGER.info(TAG, 'The detected attack query indexes are : %s',\n                detector.get_detected_queries())\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"GPU\")\n    DEVICE = context.get_context(\"device_target\")\n    if DEVICE in (\"Ascend\", \"GPU\"):\n        test_similarity_detector()\n"
  },
  {
    "path": "examples/model_security/neuron_sensitivity/mnist_neuron_sensitivity.py",
    "content": "# Copyright 2023 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"\nTest neuron sensitivity\n\"\"\"\n\nimport time\nimport numpy as np\nfrom scipy.special import softmax\n\nfrom mindspore import Model\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nfrom mindspore.nn import SoftmaxCrossEntropyWithLogits\n\nfrom mindarmour.adv_robustness.attacks import FastGradientSignMethod\nfrom mindarmour.adv_robustness.evaluations import NeuronMetric\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level(\"INFO\")\nTAG = \"NS_Test\"\n\n\ndef test_neuron_sensitivity():\n    \"\"\"\n    Neuron sensitivity test for CPU device.\n    \"\"\"\n    # upload trained network\n    ckpt_path = (\n        \"../../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt\"\n    )\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get test data\n    data_list = \"../../common/dataset/MNIST/test\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size)\n\n    # prediction accuracy before attack\n    model = Model(net)\n    batch_num = 3  # the number of batches of attacking samples\n    test_images = []\n    test_labels = []\n    predict_labels = []\n    i = 0\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        i += 1\n        images = data[0].astype(np.float32)\n        labels = data[1]\n        test_images.append(images)\n        test_labels.append(labels)\n        pred_labels = np.argmax(model.predict(Tensor(images)).asnumpy(), axis=1)\n        predict_labels.append(pred_labels)\n        if i >= batch_num:\n            break\n    predict_labels = np.concatenate(predict_labels)\n    true_labels = np.concatenate(test_labels)\n    accuracy = np.mean(np.equal(predict_labels, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %s\", accuracy)\n\n    # attacking\n    loss = SoftmaxCrossEntropyWithLogits(sparse=True)\n    attack = FastGradientSignMethod(net, eps=0.3, loss_fn=loss)\n    start_time = time.process_time()\n    adv_data = attack.batch_generate(\n        np.concatenate(test_images), true_labels, batch_size=32\n    )\n    stop_time = time.process_time()\n    pred_logits_adv = model.predict(Tensor(adv_data)).asnumpy()\n    # rescale predict confidences into (0, 1).\n    pred_logits_adv = softmax(pred_logits_adv, axis=1)\n    pred_labels_adv = np.argmax(pred_logits_adv, axis=1)\n    accuracy_adv = np.mean(np.equal(pred_labels_adv, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy after attacking is : %s\", accuracy_adv)\n\n    neuron_sensitivity = NeuronMetric(\n        net,\n        np.concatenate(test_images),\n        adv_data,\n        [\"conv1\", \"conv2\", \"fc1\", \"fc2\"],\n    )\n    nsense = neuron_sensitivity.neuron_sensitivity()\n    print(nsense)\n    LOGGER.info(\n        TAG,\n        \"The average costing time is %s\",\n        (stop_time - start_time) / (batch_num * batch_size),\n    )\n\n\nif __name__ == \"__main__\":\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.PYNATIVE_MODE, device_target=\"CPU\")\n    test_neuron_sensitivity()\n"
  },
  {
    "path": "examples/natural_robustness/__init__.py",
    "content": ""
  },
  {
    "path": "examples/natural_robustness/natural_robustness_example.py",
    "content": "# Copyright 2022 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"Example for natural robustness methods.\"\"\"\n\nimport numpy as np\nimport cv2\n\nfrom mindarmour.natural_robustness.transform.image import Translate, Curve, Perspective, Scale, Shear, Rotate, SaltAndPepperNoise, \\\n    NaturalNoise, GaussianNoise, UniformNoise, MotionBlur, GaussianBlur, GradientBlur, Contrast, GradientLuminance\n\n\ndef test_perspective(image):\n    \"\"\"Test perspective.\"\"\"\n    ori_pos = [[0, 0], [0, 800], [800, 0], [800, 800]]\n    dst_pos = [[50, 0], [0, 800], [780, 0], [800, 800]]\n    trans = Perspective(ori_pos, dst_pos)\n    dst = trans(image)\n    cv2.imshow('dst', dst)\n    cv2.waitKey()\n\n\ndef test_uniform_noise(image):\n    \"\"\"Test uniform noise.\"\"\"\n    trans = UniformNoise(factor=0.1)\n    dst = trans(image)\n    cv2.imshow('dst', dst)\n    cv2.waitKey()\n\n\ndef test_gaussian_noise(image):\n    \"\"\"Test gaussian noise.\"\"\"\n    trans = GaussianNoise(factor=0.1)\n    dst = trans(image)\n    cv2.imshow('dst', dst)\n    cv2.waitKey()\n\n\ndef test_contrast(image):\n    \"\"\"Test contrast.\"\"\"\n    trans = Contrast(alpha=2, beta=0)\n    dst = trans(image)\n    cv2.imshow('dst', dst)\n    cv2.waitKey()\n\n\ndef test_gaussian_blur(image):\n    \"\"\"Test gaussian blur.\"\"\"\n    trans = GaussianBlur(ksize=5)\n    dst = trans(image)\n    cv2.imshow('dst', dst)\n    cv2.waitKey()\n\n\ndef test_salt_and_pepper_noise(image):\n    \"\"\"Test salt and pepper noise.\"\"\"\n    trans = SaltAndPepperNoise(factor=0.01)\n    dst = trans(image)\n    cv2.imshow('dst', dst)\n    cv2.waitKey()\n\n\ndef test_translate(image):\n    \"\"\"Test translate.\"\"\"\n    trans = Translate(x_bias=0.1, y_bias=0.1)\n    dst = trans(image)\n    cv2.imshow('dst', dst)\n    cv2.waitKey()\n\n\ndef test_scale(image):\n    \"\"\"Test scale.\"\"\"\n    trans = Scale(factor_x=0.7, factor_y=0.7)\n    dst = trans(image)\n    cv2.imshow('dst', dst)\n    cv2.waitKey()\n\n\ndef test_shear(image):\n    \"\"\"Test shear.\"\"\"\n    trans = Shear(factor=0.2)\n    dst = trans(image)\n    cv2.imshow('dst', dst)\n    cv2.waitKey()\n\n\ndef test_rotate(image):\n    \"\"\"Test rotate.\"\"\"\n    trans = Rotate(angle=20)\n    dst = trans(image)\n    cv2.imshow('dst', dst)\n    cv2.waitKey()\n\n\ndef test_curve(image):\n    \"\"\"Test curve.\"\"\"\n    trans = Curve(curves=2, depth=1.5, mode='horizontal')\n    dst = trans(image)\n    cv2.imshow('dst', dst)\n    cv2.waitKey()\n\n\ndef test_natural_noise(image):\n    \"\"\"Test natural noise.\"\"\"\n    trans = NaturalNoise(ratio=0.0001, k_x_range=(1, 30), k_y_range=(1, 10), auto_param=True)\n    dst = trans(image)\n    cv2.imshow('dst', dst)\n    cv2.waitKey()\n\n\ndef test_gradient_luminance(image):\n    \"\"\"Test gradient luminance.\"\"\"\n    height, width = image.shape[:2]\n    point = (height // 4, width // 2)\n    start = (255, 255, 255)\n    end = (0, 0, 0)\n    scope = 0.3\n    bright_rate = 0.4\n    trans = GradientLuminance(start, end, start_point=point, scope=scope, pattern='dark', bright_rate=bright_rate,\n                              mode='horizontal')\n    dst = trans(image)\n    cv2.imshow('dst', dst)\n    cv2.waitKey()\n\n\ndef test_motion_blur(image):\n    \"\"\"Test motion blur.\"\"\"\n    angle = -10.5\n    i = 10\n    trans = MotionBlur(degree=i, angle=angle)\n    dst = trans(image)\n    cv2.imshow('dst', dst)\n    cv2.waitKey()\n\n\ndef test_gradient_blur(image):\n    \"\"\"Test gradient blur.\"\"\"\n    number = 10\n    h, w = image.shape[:2]\n    point = (int(h / 5), int(w / 5))\n    center = False\n    trans = GradientBlur(point, number, center)\n    dst = trans(image)\n    cv2.imshow('dst', dst)\n    cv2.waitKey()\n\n\nif __name__ == '__main__':\n    img = cv2.imread('1.jpeg')\n    img = np.array(img)\n    test_uniform_noise(img)\n    test_gaussian_noise(img)\n    test_motion_blur(img)\n    test_gradient_blur(img)\n    test_gradient_luminance(img)\n    test_natural_noise(img)\n    test_curve(img)\n    test_rotate(img)\n    test_shear(img)\n    test_scale(img)\n    test_translate(img)\n    test_salt_and_pepper_noise(img)\n    test_gaussian_blur(img)\n    test_contrast(img)\n    test_perspective(img)\n"
  },
  {
    "path": "examples/natural_robustness/serving/README.md",
    "content": "# 自然扰动样本生成serving服务\r\n\r\n提供自然扰动样本生成在线服务。客户端传入图片和扰动参数，服务端返回扰动后的图片数据。\r\n\r\n## 环境准备\r\n\r\n硬件环境：Ascend 910，GPU\r\n\r\n操作系统：Linux-x86_64\r\n\r\n软件环境：\r\n\r\n1. python 3.7.5或python 3.9.0\r\n\r\n2. 安装MindSpore 1.6.0可以参考[MindSpore安装页面](https://www.mindspore.cn/install)\r\n\r\n3. 安装MindSpore Serving 1.6.0可以参考[MindSpore Serving 安装页面](https://www.mindspore.cn/serving/docs/zh-CN/r1.5/serving_install.html)\r\n\r\n4. 安装serving分支的MindArmour:\r\n\r\n   - 从Gitee下载源码\r\n\r\n     `git clone https://gitee.com/mindspore/mindarmour.git`\r\n\r\n   - 编译并安装MindArmour\r\n\r\n     `python setup.py install`\r\n\r\n### 文件结构说明\r\n\r\n```bash\r\nserving\r\n├── server\r\n│   ├── serving_server.py   # 启动serving服务脚本\r\n│   └── perturbation\r\n│       └── serverable_config.py    # 服务端接收客户端数据后的处理脚本\r\n└── client\r\n    ├── serving_client.py   # 启动客户端脚本\r\n    └── perturb_config.py   # 扰动方法配置文件\r\n```\r\n\r\n## 脚本说明及使用\r\n\r\n### 部署Serving推理服务\r\n\r\n1. #### `servable_config.py`说明。\r\n\r\n   ```python\r\n   ···\r\n\r\n   # 客户端可以请求的方法，包含4个返回值：\"results\", \"file_names\", \"file_length\", \"names_dict\"\r\n\r\n   @register.register_method(output_names=[\"results\", \"file_names\", \"file_length\", \"names_dict\"])\r\n   def natural_perturbation(img, perturb_config, methods_number, outputs_number):\r\n       \"\"\"method natural_perturbation data flow definition, only preprocessing and call model\"\"\"\r\n       res = register.add_stage(perturb, img, perturb_config, methods_number, outputs_number, outputs_count=4)\r\n       return res\r\n   ```\r\n\r\n   方法`natural_perturbation`为对外提供服务的接口。\r\n\r\n   **输入：**\r\n\r\n   - img：输入为图片，格式为bytes。\r\n   - perturb_config：扰动配置项，具体配置参考`perturb_config.py`。\r\n   - methods_number：每次扰动随机从配置项中选择方法的个数。\r\n   - outputs_number：对于每张图片，生成的扰动图片数量。\r\n\r\n   **输出**res中包含4个参数：\r\n\r\n   - results：拼接后的图像bytes；\r\n\r\n   - file_names：图像名，格式为`xxx.png`，其中‘xxx’为A-Za-z中随机选择20个字符构成的字符串。\r\n\r\n   - file_length：每张图片的bytes长度。\r\n\r\n   - names_dict: 图片名和图片使用扰动方法构成的字典。格式为：\r\n\r\n     ```bash\r\n     {\r\n     picture1.png: [[method1, parameters of method1], [method2, parameters of method2], ...]],\r\n     picture2.png: [[method3, parameters of method3], [method4, parameters of method4], ...]],\r\n     ...\r\n     }\r\n     ```\r\n\r\n2. #### 启动server。\r\n\r\n   ```python\r\n   ···\r\n\r\n   def start(address):\r\n       servable_dir = os.path.dirname(os.path.realpath(sys.argv[0]))\r\n       # 服务配置\r\n       servable_config = server.ServableStartConfig(servable_directory=servable_dir, servable_name=\"perturbation\", device_ids=(0, 1), num_parallel_workers=4)\r\n       # 启动服务\r\n       server.start_servables(servable_configs=servable_config)\r\n\r\n       # 启动启动gRPC服务，用于客户端和服务端之间通信\r\n       server.start_grpc_server(address=address, max_msg_mb_size=200)   # ip和最大的传输数据量，单位MB\r\n       # 启动启动Restful服务，用于客户端和服务端之间通信\r\n       server.start_restful_server(address=address)\r\n   ```\r\n\r\n   gRPC传输性能更好，Restful更适合用于web服务，根据需要选择。\r\n\r\n   执行命令`python serverong_server.py`启动服务。\r\n\r\n   当服务端打印日志`Serving RESTful server start success, listening on *.*.*.*:****`时，表示Serving RESTful服务启动成功，推理模型已成功加载。\r\n\r\n### 客户端进行推理\r\n\r\n1. 在`perturb_config.py`中设置扰动方法及参数。下面是个例子：\r\n\r\n   ```python\r\n   PerturbConfig = [{\"method\": \"Contrast\", \"params\": {\"alpha\": 1.5, \"beta\": 0}},\r\n                    {\"method\": \"GaussianBlur\", \"params\": {\"ksize\": 5}},\r\n                    {\"method\": \"SaltAndPepperNoise\", \"params\": {\"factor\": 0.05}},\r\n                    {\"method\": \"Translate\", \"params\": {\"x_bias\": 0.1, \"y_bias\": -0.2}},\r\n                    {\"method\": \"Scale\", \"params\": {\"factor_x\": 0.7, \"factor_y\": 0.7}},\r\n                    {\"method\": \"Shear\", \"params\": {\"factor\": 2, \"director\": \"horizontal\"}},\r\n                    {\"method\": \"Rotate\", \"params\": {\"angle\": 40}},\r\n                    {\"method\": \"MotionBlur\", \"params\": {\"degree\": 5, \"angle\": 45}},\r\n                    {\"method\": \"GradientBlur\", \"params\": {\"point\": [50, 100], \"kernel_num\": 3, \"center\": True}},\r\n                    {\"method\": \"GradientLuminance\",\r\n                     \"params\": {\"color_start\": [255, 255, 255],\r\n                                \"color_end\": [0, 0, 0],\r\n                                \"start_point\": [100, 150], \"scope\": 0.3,\r\n                                \"bright_rate\": 0.3, \"pattern\": \"light\",\r\n                                \"mode\": \"circle\"}},\r\n                    {\"method\": \"Curve\", \"params\": {\"curves\": 5, \"depth\": 10,\r\n                                                    \"mode\": \"vertical\"}},\r\n                    {\"method\": \"Perspective\",\r\n                     \"params\": {\"ori_pos\": [[0, 0], [0, 800], [800, 0], [800, 800]],\r\n                                \"dst_pos\": [[50, 0], [0, 800], [780, 0], [800, 800]]}},\r\n                   ]\r\n   ```\r\n\r\n   其中`method`为扰动方法名，`params`为对应方法的参数。可用的扰动方法及对应参数可在`mindarmour/natural_robustness/natural_noise.py`中查询。\r\n\r\n2. 在`serving_client.py`中写客户端的处理脚本，包含输入输出的处理、服务端的调用，可以参考下面的例子。\r\n\r\n   ```python\r\n   ···\r\n\r\n   def perturb(perturb_config, address):\r\n       \"\"\"invoke servable perturbation method natural_perturbation\"\"\"\r\n\r\n       # 请求的服务端ip及端口、请求的服务名、请求的方法名\r\n       client = Client(address, \"perturbation\", \"natural_perturbation\")\r\n\r\n       # 输入数据\r\n       instances = []\r\n       img_path = '/root/mindarmour/example/adversarial/test_data/1.png'\r\n       result_path = '/root/mindarmour/example/adv/result/'\r\n       methods_number = 2\r\n       outputs_number = 3\r\n       img = cv2.imread(img_path)\r\n       img = cv2.imencode('.png', img)[1].tobytes()    # 图片传输用bytes格式，不支持numpy.ndarray格式\r\n       perturb_config = json.dumps(perturb_config) # 配置方法转成json格式\r\n       instances.append({\"img\": img, 'perturb_config': perturb_config, \"methods_number\": methods_number,\r\n                      \"outputs_number\": outputs_number})   # instances中可添加多个输入\r\n\r\n       # 请求服务，返回结果\r\n       result = client.infer(instances)\r\n\r\n       # 对服务请求得到的结果进行处理，将返回的图片字节流存成图片\r\n       file_names = result[0]['file_names'].split(';')\r\n       length = result[0]['file_length'].tolist()\r\n       before = 0\r\n       for name, leng in zip(file_names, length):\r\n           res_img = result[0]['results']\r\n           res_img = res_img[before:before + leng]\r\n           before = before + leng\r\n           print('name: ', name)\r\n           image = Image.open(BytesIO(res_img))\r\n           image.save(os.path.join(result_path, name))\r\n\r\n       names_dict = result[0]['names_dict']\r\n       with open('names_dict.json', 'w') as file:\r\n           file.write(names_dict)\r\n   ```\r\n\r\n   启动client前，需将服务端的IP地址改成部署server的IP地址，图片路径、结果存储路基替换成用户数据路径。\r\n\r\n   目前serving数据传输支持的数据类型包括：python的int、float、bool、str、bytes，numpy number, numpy array object。\r\n\r\n   输入命令`python serving_client.py`开启客户端，如果对应目录下生成扰动样本图片则说明serving服务正确执行。\r\n\r\n   ### 其他\r\n\r\n   在`serving_logs`目录下可以查看运行日志，辅助debug。\r\n"
  },
  {
    "path": "examples/natural_robustness/serving/client/perturb_config.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n\r\n\"\"\"\r\nConfiguration of natural robustness methods for server.\r\n\"\"\"\r\n\r\nperturb_configs = [{\"method\": \"Contrast\", \"params\": {\"alpha\": 1.5, \"beta\": 0}},\r\n                   {\"method\": \"GaussianBlur\", \"params\": {\"ksize\": 5}},\r\n                   {\"method\": \"SaltAndPepperNoise\", \"params\": {\"factor\": 0.05}},\r\n                   {\"method\": \"Translate\", \"params\": {\"x_bias\": 0.1, \"y_bias\": -0.2}},\r\n                   {\"method\": \"Scale\", \"params\": {\"factor_x\": 0.7, \"factor_y\": 0.7}},\r\n                   {\"method\": \"Shear\", \"params\": {\"factor\": 2, \"direction\": \"horizontal\"}},\r\n                   {\"method\": \"Rotate\", \"params\": {\"angle\": 40}},\r\n                   {\"method\": \"MotionBlur\", \"params\": {\"degree\": 5, \"angle\": 45}},\r\n                   {\"method\": \"GradientBlur\", \"params\": {\"point\": [50, 100], \"kernel_num\": 3, \"center\": True}},\r\n                   {\"method\": \"GradientLuminance\", \"params\": {\"color_start\": [255, 255, 255], \"color_end\": [0, 0, 0],\r\n                                                              \"start_point\": [100, 150], \"scope\": 0.3,\r\n                                                              \"bright_rate\": 0.3, \"pattern\": \"light\",\r\n                                                              \"mode\": \"circle\"}},\r\n                   {\"method\": \"GradientLuminance\", \"params\": {\"color_start\": [255, 255, 255],\r\n                                                              \"color_end\": [0, 0, 0], \"start_point\": [150, 200],\r\n                                                              \"scope\": 0.3, \"pattern\": \"light\", \"mode\": \"horizontal\"}},\r\n                   {\"method\": \"GradientLuminance\", \"params\": {\"color_start\": [255, 255, 255], \"color_end\": [0, 0, 0],\r\n                                                              \"start_point\": [150, 200], \"scope\": 0.3,\r\n                                                              \"pattern\": \"light\", \"mode\": \"vertical\"}},\r\n                   {\"method\": \"Curve\", \"params\": {\"curves\": 10, \"depth\": 10, \"mode\": \"vertical\"}},\r\n                   {\"method\": \"Perspective\", \"params\": {\"ori_pos\": [[0, 0], [0, 800], [800, 0], [800, 800]],\r\n                                                        \"dst_pos\": [[50, 0], [0, 800], [780, 0], [800, 800]]}},\r\n                   ]\r\n"
  },
  {
    "path": "examples/natural_robustness/serving/client/serving_client.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"The client of example add.\"\"\"\nimport os\nimport sys\nimport json\nfrom io import BytesIO\n\nimport cv2\nfrom PIL import Image\nfrom mindspore_serving.client import Client\n\nfrom perturb_config import perturb_configs\n\n\ndef perturb(perturb_config, address):\n    \"\"\"Invoke servable perturbation method natural_perturbation\"\"\"\n    client = Client(address, \"perturbation\", \"natural_perturbation\")\n    instances = []\n    img_path = 'test_data/1.png'\n    result_path = 'result/'\n    if not os.path.exists(result_path):\n        os.mkdir(result_path)\n    methods_number = 2\n    outputs_number = 10\n    img = cv2.imread(img_path)\n    img = cv2.imencode('.png', img)[1].tobytes()\n    perturb_config = json.dumps(perturb_config)\n    instances.append({\"img\": img, 'perturb_config': perturb_config, \"methods_number\": methods_number,\n                      \"outputs_number\": outputs_number})\n\n    result = client.infer(instances)\n\n    file_names = result[0]['file_names'].split(';')\n    length = result[0]['file_length'].tolist()\n    before = 0\n    for name, leng in zip(file_names, length):\n        res_img = result[0]['results']\n        res_img = res_img[before:before + leng]\n        before = before + leng\n        print('name: ', name)\n        image = Image.open(BytesIO(res_img))\n        image.save(os.path.join(result_path, name))\n    names_dict = result[0]['names_dict']\n    with open('names_dict.json', 'w') as file:\n        file.write(names_dict)\n\n\nif __name__ == '__main__':\n    if len(sys.argv) != 3:\n        print(\"Usage: python serving_client.py <ip> <port>\")\n        sys.exit(1)\n    ip, port = sys.argv[1], sys.argv[2]\n    address = f\"{ip}:{port}\"\n    perturb(perturb_configs, address)\n"
  },
  {
    "path": "examples/natural_robustness/serving/server/perturbation/servable_config.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"perturbation servable config\"\"\"\nimport json\nimport copy\nimport random\nfrom io import BytesIO\nimport cv2\nimport numpy as np\nfrom PIL import Image\nfrom mindspore_serving.server import register\nfrom mindarmour.natural_robustness.transform.image import Contrast, GaussianBlur, SaltAndPepperNoise, Scale, Shear, \\\n    Translate, Rotate, MotionBlur, GradientBlur, GradientLuminance, NaturalNoise, Curve, Perspective\n\n\nCHARACTERS = [chr(i) for i in range(65, 91)]+[chr(j) for j in range(97, 123)]\n\nmethods_dict = {'Contrast': Contrast,\n                'GaussianBlur': GaussianBlur,\n                'SaltAndPepperNoise': SaltAndPepperNoise,\n                'Translate': Translate,\n                'Scale': Scale,\n                'Shear': Shear,\n                'Rotate': Rotate,\n                'MotionBlur': MotionBlur,\n                'GradientBlur': GradientBlur,\n                'GradientLuminance': GradientLuminance,\n                'NaturalNoise': NaturalNoise,\n                'Curve': Curve,\n                'Perspective': Perspective}\n\n\ndef check_inputs(img, perturb_config, methods_number, outputs_number):\n    \"\"\"Check inputs.\"\"\"\n    if not np.any(img):\n        raise ValueError(\"img cannot be empty.\")\n    img = Image.open(BytesIO(img))\n    if img.mode == \"L\":\n        img = img.convert('RGB')\n    img = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)\n\n    config = json.loads(perturb_config)\n    if not config:\n        raise ValueError(\"perturb_config cannot be empty.\")\n    for item in config:\n        if item['method'] not in methods_dict.keys():\n            raise ValueError(\"{} is not a valid method.\".format(item['method']))\n\n    methods_number = int(methods_number)\n    if methods_number < 1:\n        raise ValueError(\"methods_number must more than 0.\")\n    outputs_number = int(outputs_number)\n    if outputs_number < 1:\n        raise ValueError(\"outputs_number must more than 0.\")\n\n    return img, config, methods_number, outputs_number\n\n\ndef perturb(img, perturb_config, methods_number, outputs_number):\n    \"\"\"Perturb given image.\"\"\"\n    img, config, methods_number, outputs_number = check_inputs(img, perturb_config, methods_number, outputs_number)\n    res_img_bytes = b''\n    file_names = []\n    file_length = []\n    names_dict = {}\n    for _ in range(outputs_number):\n        dst = copy.deepcopy(img)\n        used_methods = []\n        for _ in range(methods_number):\n            item = np.random.choice(config)\n            method_name = item['method']\n            method = methods_dict[method_name]\n            params = item['params']\n            dst = method(**params)(img)\n            method_params = params\n\n            used_methods.append([method_name, method_params])\n        name = ''.join(random.sample(CHARACTERS, 20))\n        name += '.png'\n        file_names.append(name)\n        names_dict[name] = used_methods\n\n        res_img = cv2.imencode('.png', dst)[1].tobytes()\n        res_img_bytes += res_img\n        file_length.append(len(res_img))\n\n    names_dict = json.dumps(names_dict)\n\n    return res_img_bytes, ';'.join(file_names), file_length, names_dict\n\n\n@register.register_method(output_names=[\"results\", \"file_names\", \"file_length\", \"names_dict\"])\ndef natural_perturbation(img, perturb_config, methods_number, outputs_number):\n    \"\"\"method natural_perturbation data flow definition, only preprocessing and call model\"\"\"\n    res = register.add_stage(perturb, img, perturb_config, methods_number, outputs_number, outputs_count=4)\n    return res\n"
  },
  {
    "path": "examples/natural_robustness/serving/server/serving_server.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"The server of example perturbation\"\"\"\n\nimport os\nimport sys\nfrom mindspore_serving import server\n\n\ndef start(address):\n    \"\"\"Start server.\"\"\"\n    servable_dir = os.path.dirname(os.path.realpath(sys.argv[0]))\n\n    servable_config = server.ServableStartConfig(servable_directory=servable_dir, servable_name=\"perturbation\",\n                                                 device_ids=(0, 1), num_parallel_workers=4)\n    server.start_servables(servable_configs=servable_config)\n\n    server.start_grpc_server(address=address, max_msg_mb_size=200)\n    # server.start_restful_server(address=address)\n\n\nif __name__ == \"__main__\":\n    if len(sys.argv) != 3:\n        print(\"Usage: python serving_server.py <ip> <port>\")\n        sys.exit(1)\n    ip, port = sys.argv[1], sys.argv[2]\n    address = f\"{ip}:{port}\"\n    start(address)\n"
  },
  {
    "path": "examples/privacy/README.md",
    "content": "# Application demos of privacy stealing and privacy protection\n\n## Introduction\n\nAlthough machine learning could obtain a generic model based on training data, it has been proved that the trained\n model may disclose the information of training data (such as the membership inference attack).\nDifferential privacy training is an effective method proposed to overcome this problem, in which Gaussian noise is\n added while training. There are mainly three parts for differential privacy(DP) training: noise-generating\n mechanism, DP optimizer and DP monitor. We have implemented a novel noise-generating mechanisms: adaptive decay\n noise mechanism. DP monitor is used to compute the privacy budget while training.\nSuppress Privacy training is a novel method to protect privacy distinct from the noise addition method\n (such as DP), in which the negligible model parameter is removed gradually to achieve a better balance between\n accuracy and privacy.\n\n## 1. Adaptive decay DP training\n\nWith adaptive decay mechanism, the magnitude of the Gaussian noise would be decayed as the training step grows, which\n resulting a stable convergence.\n\n```sh\ncd examples/privacy/diff_privacy\npython lenet5_dp_ada_gaussian.py\n```\n\n## 2. Adaptive norm clip training\n\nWith adaptive norm clip mechanism, the norm clip of the gradients would be changed according to the norm values of\n them, which can adjust the ratio of noise and original gradients.\n\n```sh\ncd examples/privacy/diff_privacy\npython lenet5_dp.py\n```\n\n## 3. Membership inference evaluation\n\nBy this evaluation method, we could judge whether a sample is belongs to training dataset or not.\n\n```sh\ncd examples/privacy/membership_inference_attack\npython train.py --data_path home_path_to_cifar100 --ckpt_path ./\npython example_vgg_cifar.py --data_path home_path_to_cifar100 --pre_trained 0-100_781.ckpt\n```\n\n## 4. Suppress privacy training\n\nWith suppress privacy mechanism, the values of some trainable parameters  (such as conv layers and fully connected\n layers) are set to zero as the training step grows, which can\n achieve a better balance between accuracy and privacy\n\n```sh\ncd examples/privacy/sup_privacy\npython sup_privacy.py\n```\n\n## 5. Image inversion attack\n\nInversion attack means reconstructing an image based on its deep representations. For example,\nreconstruct a MNIST image based on its output through LeNet5. The mechanism behind it is that well-trained\nmodel can \"remember\" those training dataset. Therefore, inversion attack can be used to estimate the privacy\nleakage of training tasks.\n\n```sh\ncd examples/privacy/inversion_attack\npython mnist_inversion_attack.py\n```"
  },
  {
    "path": "examples/privacy/__init__.py",
    "content": ""
  },
  {
    "path": "examples/privacy/diff_privacy/__init__.py",
    "content": ""
  },
  {
    "path": "examples/privacy/diff_privacy/dp_ada_gaussian_config.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nnetwork config setting, will be used in train.py\n\"\"\"\n\nfrom easydict import EasyDict as edict\n\nmnist_cfg = edict({\n    'num_classes': 10,  # the number of classes of model's output\n    'lr': 0.01,  # the learning rate of model's optimizer\n    'momentum': 0.9,  # the momentum value of model's optimizer\n    'epoch_size': 5,  # training epochs\n    'batch_size': 256,  # batch size for training\n    'image_height': 32,  # the height of training samples\n    'image_width': 32,  # the width of training samples\n    'save_checkpoint_steps': 234,  # the interval steps for saving checkpoint file of the model\n    'keep_checkpoint_max': 10,  # the maximum number of checkpoint files would be saved\n    'device_target': 'Ascend',  # device used\n    'data_path': '../../common/dataset/MNIST',  # the path of training and testing data set\n    'dataset_sink_mode': False,  # whether deliver all training data to device one time\n    'micro_batches': 32,  # the number of small batches split from an original batch\n    'norm_bound': 1.0,  # the clip bound of the gradients of model's training parameters\n    'initial_noise_multiplier': 0.05,  # the initial multiplication coefficient of the noise added to training\n    # parameters' gradients\n    'noise_mechanisms': 'AdaGaussian',  # the method of adding noise in gradients while training\n    'optimizer': 'Momentum'  # the base optimizer used for Differential privacy training\n})\n"
  },
  {
    "path": "examples/privacy/diff_privacy/dp_ada_sgd_graph_config.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nnetwork config setting, will be used in train.py\n\"\"\"\n\nfrom easydict import EasyDict as edict\n\nmnist_cfg = edict({\n    'num_classes': 10,  # the number of classes of model's output\n    'lr': 0.001,  # the learning rate of model's optimizer\n    'momentum': 0.9,  # the momentum value of model's optimizer\n    'epoch_size': 20,  # training epochs\n    'batch_size': 256,  # batch size for training\n    'image_height': 32,  # the height of training samples\n    'image_width': 32,  # the width of training samples\n    'save_checkpoint_steps': 234,  # the interval steps for saving checkpoint file of the model\n    'keep_checkpoint_max': 10,  # the maximum number of checkpoint files would be saved\n    'device_target': 'Ascend',  # device used\n    'data_path': '../../common/dataset/MNIST',  # the path of training and testing data set\n    'dataset_sink_mode': False,  # whether deliver all training data to device one time\n    'micro_batches': 16,  # the number of small batches split from an original batch\n    'norm_bound': 1.0,  # the clip bound of the gradients of model's training parameters\n    'initial_noise_multiplier': 0.05,  # the initial multiplication coefficient of the noise added to training\n    # parameters' gradients\n    'decay_policy': 'Step',\n    'noise_mechanisms': 'AdaGaussian',  # the method of adding noise in gradients while training\n    'optimizer': 'SGD'  # the base optimizer used for Differential privacy training\n})\n"
  },
  {
    "path": "examples/privacy/diff_privacy/lenet5_config.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nnetwork config setting, will be used in train.py\n\"\"\"\n\nfrom easydict import EasyDict as edict\n\nmnist_cfg = edict({\n    'num_classes': 10,  # the number of classes of model's output\n    'lr': 0.01,  # the learning rate of model's optimizer\n    'momentum': 0.9,  # the momentum value of model's optimizer\n    'epoch_size': 10,  # training epochs\n    'batch_size': 256,  # batch size for training\n    'image_height': 32,  # the height of training samples\n    'image_width': 32,  # the width of training samples\n    'save_checkpoint_steps': 234,  # the interval steps for saving checkpoint file of the model\n    'keep_checkpoint_max': 10,  # the maximum number of checkpoint files would be saved\n    'device_target': 'Ascend',  # device used\n    'data_path': '../../common/dataset/MNIST',  # the path of training and testing data set\n    'dataset_sink_mode': False,  # whether deliver all training data to device one time\n    'micro_batches': 32,  # the number of small batches split from an original batch\n    'norm_bound': 1.0,  # the clip bound of the gradients of model's training parameters\n    'initial_noise_multiplier': 0.4,  # the initial multiplication coefficient of the noise added to training\n    # parameters' gradients\n    'noise_mechanisms': 'Gaussian',  # the method of adding noise in gradients while training\n    'clip_mechanisms': 'Gaussian',  # the method of adaptive clipping gradients while training\n    'clip_decay_policy': 'Linear', # Decay policy of adaptive clipping, decay_policy must be in ['Linear', 'Geometric'].\n    'clip_learning_rate': 0.001, # Learning rate of update norm clip.\n    'target_unclipped_quantile': 0.9, # Target quantile of norm clip.\n    'fraction_stddev': 0.01, # The stddev of Gaussian normal which used in empirical_fraction.\n    'optimizer': 'Momentum',  # the base optimizer used for Differential privacy training\n    'target_delta': 1e-5   # the target delta budget for DP training\n})\n"
  },
  {
    "path": "examples/privacy/diff_privacy/lenet5_dp.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nTraining example of adaClip-mechanism differential privacy.\n\"\"\"\nimport os\n\nfrom mindspore import nn\nfrom mindspore import context\nfrom mindspore import load_checkpoint, load_param_into_net\nfrom mindspore import dtype as mstype\nfrom mindspore.train.callback import ModelCheckpoint\nfrom mindspore.train.callback import CheckpointConfig\nfrom mindspore.train.callback import LossMonitor\nfrom mindspore.nn import Accuracy\nimport mindspore.dataset as ds\nimport mindspore.dataset.vision as CV\nimport mindspore.dataset.transforms as C\nfrom mindspore.dataset.vision import Inter\nfrom mindarmour.privacy.diff_privacy import DPModel\nfrom mindarmour.privacy.diff_privacy import PrivacyMonitorFactory\nfrom mindarmour.privacy.diff_privacy import NoiseMechanismsFactory\nfrom mindarmour.privacy.diff_privacy import ClipMechanismsFactory\nfrom mindarmour.utils import LogUtil\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\nfrom lenet5_config import mnist_cfg as cfg\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'Lenet5_train'\n\n\ndef generate_mnist_dataset(data_path, batch_size=32, repeat_size=1,\n                           num_parallel_workers=1, sparse=True):\n    \"\"\"\n    create dataset for training or testing\n    \"\"\"\n    # define dataset\n    ds1 = ds.MnistDataset(data_path)\n\n    # define operation parameters\n    resize_height, resize_width = 32, 32\n    rescale = 1.0 / 255.0\n    shift = 0.0\n\n    # define map operations\n    resize_op = CV.Resize((resize_height, resize_width),\n                          interpolation=Inter.LINEAR)\n    rescale_op = CV.Rescale(rescale, shift)\n    hwc2chw_op = CV.HWC2CHW()\n    type_cast_op = C.TypeCast(mstype.int32)\n\n    # apply map operations on images\n    if not sparse:\n        one_hot_enco = C.OneHot(10)\n        ds1 = ds1.map(input_columns=\"label\", operations=one_hot_enco,\n                      num_parallel_workers=num_parallel_workers)\n        type_cast_op = C.TypeCast(mstype.float32)\n    ds1 = ds1.map(input_columns=\"label\", operations=type_cast_op,\n                  num_parallel_workers=num_parallel_workers)\n    ds1 = ds1.map(input_columns=\"image\", operations=resize_op,\n                  num_parallel_workers=num_parallel_workers)\n    ds1 = ds1.map(input_columns=\"image\", operations=rescale_op,\n                  num_parallel_workers=num_parallel_workers)\n    ds1 = ds1.map(input_columns=\"image\", operations=hwc2chw_op,\n                  num_parallel_workers=num_parallel_workers)\n\n    # apply DatasetOps\n    buffer_size = 10000\n    ds1 = ds1.shuffle(buffer_size=buffer_size)\n    ds1 = ds1.batch(batch_size, drop_remainder=True)\n    ds1 = ds1.repeat(repeat_size)\n\n    return ds1\n\n\nif __name__ == \"__main__\":\n    # This configure can run both in pynative mode and graph mode\n    context.set_context(mode=context.GRAPH_MODE,\n                        device_target=cfg.device_target)\n    network = LeNet5()\n    net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction=\"mean\")\n    config_ck = CheckpointConfig(\n        save_checkpoint_steps=cfg.save_checkpoint_steps,\n        keep_checkpoint_max=cfg.keep_checkpoint_max)\n    ckpoint_cb = ModelCheckpoint(prefix=\"checkpoint_lenet\",\n                                 directory='./trained_ckpt_file/',\n                                 config=config_ck)\n\n    # get training dataset\n    ds_train = generate_mnist_dataset(os.path.join(cfg.data_path, \"train\"),\n                                      cfg.batch_size)\n\n    if cfg.micro_batches and cfg.batch_size % cfg.micro_batches != 0:\n        raise ValueError(\n            \"Number of micro_batches should divide evenly batch_size\")\n    # Create a factory class of DP noise mechanisms, this method is adding noise\n    # in gradients while training. Mechanisms can be 'Gaussian'\n    # or 'AdaGaussian', in which noise would be decayed with 'AdaGaussian'\n    # mechanism while be constant with 'Gaussian' mechanism.\n    noise_mech = NoiseMechanismsFactory().create(cfg.noise_mechanisms,\n                                                 norm_bound=cfg.norm_bound,\n                                                 initial_noise_multiplier=cfg.initial_noise_multiplier,\n                                                 decay_policy=None)\n    # Create a factory class of clip mechanisms, this method is to adaptive clip\n    # gradients while training, decay_policy support 'Linear' and 'Geometric',\n    # learning_rate is the learning rate to update clip_norm,\n    # target_unclipped_quantile is the target quantile of norm clip,\n    # fraction_stddev is the stddev of Gaussian normal which used in\n    # empirical_fraction, the formula is\n    # $empirical_fraction + N(0, fraction_stddev)$.\n    clip_mech = ClipMechanismsFactory().create(cfg.clip_mechanisms,\n                                               decay_policy=cfg.clip_decay_policy,\n                                               learning_rate=cfg.clip_learning_rate,\n                                               target_unclipped_quantile=cfg.target_unclipped_quantile,\n                                               fraction_stddev=cfg.fraction_stddev)\n    net_opt = nn.Momentum(params=network.trainable_params(),\n                          learning_rate=cfg.lr, momentum=cfg.momentum)\n    # Create a monitor for DP training. The function of the monitor is to\n    # compute and print the privacy budget(eps and delta) while training.\n    rdp_monitor = PrivacyMonitorFactory.create('rdp',\n                                               num_samples=60000,\n                                               batch_size=cfg.batch_size,\n                                               initial_noise_multiplier=cfg.initial_noise_multiplier,\n                                               per_print_times=234,\n                                               target_delta=cfg.target_delta,\n                                               noise_decay_mode=None)\n    # Create the DP model for training.\n    model = DPModel(micro_batches=cfg.micro_batches,\n                    norm_bound=cfg.norm_bound,\n                    noise_mech=noise_mech,\n                    clip_mech=clip_mech,\n                    network=network,\n                    loss_fn=net_loss,\n                    optimizer=net_opt,\n                    metrics={\"Accuracy\": Accuracy()})\n\n    LOGGER.info(TAG, \"============== Starting Training ==============\")\n    model.train(cfg['epoch_size'], ds_train,\n                callbacks=[ckpoint_cb, LossMonitor(), rdp_monitor],\n                dataset_sink_mode=cfg.dataset_sink_mode)\n\n    LOGGER.info(TAG, \"============== Starting Testing ==============\")\n    ckpt_file_name = 'trained_ckpt_file/checkpoint_lenet-10_234.ckpt'\n    param_dict = load_checkpoint(ckpt_file_name)\n    load_param_into_net(network, param_dict)\n    ds_eval = generate_mnist_dataset(os.path.join(cfg.data_path, 'test'),\n                                     batch_size=cfg.batch_size)\n    acc = model.eval(ds_eval, dataset_sink_mode=False)\n    LOGGER.info(TAG, \"============== Accuracy: %s  ==============\", acc)\n"
  },
  {
    "path": "examples/privacy/diff_privacy/lenet5_dp_ada_gaussian.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nTraining example of adaGaussian-mechanism differential privacy.\n\"\"\"\nimport os\n\nimport mindspore.nn as nn\nfrom mindspore import context\nfrom mindspore.train.callback import ModelCheckpoint\nfrom mindspore.train.callback import CheckpointConfig\nfrom mindspore.train.callback import LossMonitor\nfrom mindspore.nn.metrics import Accuracy\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nimport mindspore.dataset as ds\nimport mindspore.dataset.vision as CV\nimport mindspore.dataset.transforms as C\nfrom mindspore.dataset.vision import Inter\nimport mindspore.common.dtype as mstype\n\nfrom mindarmour.privacy.diff_privacy import DPModel\nfrom mindarmour.privacy.diff_privacy import PrivacyMonitorFactory\nfrom mindarmour.privacy.diff_privacy import NoiseMechanismsFactory\nfrom mindarmour.utils.logger import LogUtil\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\nfrom dp_ada_gaussian_config import mnist_cfg as cfg\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'Lenet5_train'\n\n\ndef generate_mnist_dataset(data_path, batch_size=32, repeat_size=1,\n                           num_parallel_workers=1, sparse=True):\n    \"\"\"\n    create dataset for training or testing\n    \"\"\"\n    # define dataset\n    ds1 = ds.MnistDataset(data_path)\n\n    # define operation parameters\n    resize_height, resize_width = 32, 32\n    rescale = 1.0 / 255.0\n    shift = 0.0\n\n    # define map operations\n    resize_op = CV.Resize((resize_height, resize_width),\n                          interpolation=Inter.LINEAR)\n    rescale_op = CV.Rescale(rescale, shift)\n    hwc2chw_op = CV.HWC2CHW()\n    type_cast_op = C.TypeCast(mstype.int32)\n\n    # apply map operations on images\n    if not sparse:\n        one_hot_enco = C.OneHot(10)\n        ds1 = ds1.map(input_columns=\"label\", operations=one_hot_enco,\n                      num_parallel_workers=num_parallel_workers)\n        type_cast_op = C.TypeCast(mstype.float32)\n    ds1 = ds1.map(input_columns=\"label\", operations=type_cast_op,\n                  num_parallel_workers=num_parallel_workers)\n    ds1 = ds1.map(input_columns=\"image\", operations=resize_op,\n                  num_parallel_workers=num_parallel_workers)\n    ds1 = ds1.map(input_columns=\"image\", operations=rescale_op,\n                  num_parallel_workers=num_parallel_workers)\n    ds1 = ds1.map(input_columns=\"image\", operations=hwc2chw_op,\n                  num_parallel_workers=num_parallel_workers)\n\n    # apply DatasetOps\n    buffer_size = 10000\n    ds1 = ds1.shuffle(buffer_size=buffer_size)\n    ds1 = ds1.batch(batch_size, drop_remainder=True)\n    ds1 = ds1.repeat(repeat_size)\n\n    return ds1\n\n\nif __name__ == \"__main__\":\n    # This configure can run both in pynative mode and graph mode\n    context.set_context(mode=context.GRAPH_MODE,\n                        device_target=cfg.device_target)\n    network = LeNet5()\n    net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction=\"mean\")\n    config_ck = CheckpointConfig(\n        save_checkpoint_steps=cfg.save_checkpoint_steps,\n        keep_checkpoint_max=cfg.keep_checkpoint_max)\n    ckpoint_cb = ModelCheckpoint(prefix=\"checkpoint_lenet\",\n                                 directory='./trained_ckpt_file/',\n                                 config=config_ck)\n\n    # get training dataset\n    ds_train = generate_mnist_dataset(os.path.join(cfg.data_path, \"train\"),\n                                      cfg.batch_size)\n\n    if cfg.micro_batches and cfg.batch_size % cfg.micro_batches != 0:\n        raise ValueError(\n            \"Number of micro_batches should divide evenly batch_size\")\n    # Create a factory class of DP noise mechanisms, this method is adding noise\n    # in gradients while training. Mechanisms can be 'Gaussian'\n    # or 'AdaGaussian', in which noise would be decayed with 'AdaGaussian'\n    # mechanism while be constant with 'Gaussian' mechanism.\n    noise_mech = NoiseMechanismsFactory().create(cfg.noise_mechanisms,\n                                                 norm_bound=cfg.norm_bound,\n                                                 initial_noise_multiplier=cfg.initial_noise_multiplier,\n                                                 decay_policy='Exp')\n\n    net_opt = nn.Momentum(params=network.trainable_params(),\n                          learning_rate=cfg.lr, momentum=cfg.momentum)\n    # Create a monitor for DP training. The function of the monitor is to\n    # compute and print the privacy budget(eps and delta) while training.\n    rdp_monitor = PrivacyMonitorFactory.create('rdp',\n                                               num_samples=60000,\n                                               batch_size=cfg.batch_size,\n                                               initial_noise_multiplier=cfg.initial_noise_multiplier,\n                                               per_print_times=234,\n                                               target_delta=1e-5)\n    # Create the DP model for training.\n    model = DPModel(micro_batches=cfg.micro_batches,\n                    norm_bound=cfg.norm_bound,\n                    noise_mech=noise_mech,\n                    network=network,\n                    loss_fn=net_loss,\n                    optimizer=net_opt,\n                    metrics={\"Accuracy\": Accuracy()})\n\n    LOGGER.info(TAG, \"============== Starting Training ==============\")\n    model.train(cfg['epoch_size'], ds_train,\n                callbacks=[ckpoint_cb, LossMonitor(), rdp_monitor],\n                dataset_sink_mode=cfg.dataset_sink_mode)\n\n    LOGGER.info(TAG, \"============== Starting Testing ==============\")\n    ckpt_file_name = 'trained_ckpt_file/checkpoint_lenet-5_234.ckpt'\n    param_dict = load_checkpoint(ckpt_file_name)\n    load_param_into_net(network, param_dict)\n    ds_eval = generate_mnist_dataset(os.path.join(cfg.data_path, 'test'),\n                                     batch_size=cfg.batch_size)\n    acc = model.eval(ds_eval, dataset_sink_mode=False)\n    LOGGER.info(TAG, \"============== Accuracy: %s  ==============\", acc)\n"
  },
  {
    "path": "examples/privacy/diff_privacy/lenet5_dp_ada_sgd_graph.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nTraining example of adaGaussian-mechanism differential privacy.\n\"\"\"\nimport os\n\nimport mindspore.nn as nn\nfrom mindspore import context\nfrom mindspore.train.callback import ModelCheckpoint\nfrom mindspore.train.callback import CheckpointConfig\nfrom mindspore.train.callback import LossMonitor\nfrom mindspore.nn.metrics import Accuracy\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nimport mindspore.dataset as ds\nimport mindspore.dataset.vision as CV\nimport mindspore.dataset.transforms as C\nfrom mindspore.dataset.vision import Inter\nimport mindspore.common.dtype as mstype\n\nfrom mindarmour.privacy.diff_privacy import DPModel\nfrom mindarmour.privacy.diff_privacy import PrivacyMonitorFactory\nfrom mindarmour.privacy.diff_privacy import NoiseMechanismsFactory\nfrom mindarmour.utils.logger import LogUtil\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\nfrom dp_ada_sgd_graph_config import mnist_cfg as cfg\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'Lenet5_train'\n\n\ndef generate_mnist_dataset(data_path, batch_size=32, repeat_size=1,\n                           num_parallel_workers=1, sparse=True):\n    \"\"\"\n    create dataset for training or testing\n    \"\"\"\n    # define dataset\n    ds1 = ds.MnistDataset(data_path)\n\n    # define operation parameters\n    resize_height, resize_width = 32, 32\n    rescale = 1.0 / 255.0\n    shift = 0.0\n\n    # define map operations\n    resize_op = CV.Resize((resize_height, resize_width),\n                          interpolation=Inter.LINEAR)\n    rescale_op = CV.Rescale(rescale, shift)\n    hwc2chw_op = CV.HWC2CHW()\n    type_cast_op = C.TypeCast(mstype.int32)\n\n    # apply map operations on images\n    if not sparse:\n        one_hot_enco = C.OneHot(10)\n        ds1 = ds1.map(input_columns=\"label\", operations=one_hot_enco,\n                      num_parallel_workers=num_parallel_workers)\n        type_cast_op = C.TypeCast(mstype.float32)\n    ds1 = ds1.map(input_columns=\"label\", operations=type_cast_op,\n                  num_parallel_workers=num_parallel_workers)\n    ds1 = ds1.map(input_columns=\"image\", operations=resize_op,\n                  num_parallel_workers=num_parallel_workers)\n    ds1 = ds1.map(input_columns=\"image\", operations=rescale_op,\n                  num_parallel_workers=num_parallel_workers)\n    ds1 = ds1.map(input_columns=\"image\", operations=hwc2chw_op,\n                  num_parallel_workers=num_parallel_workers)\n\n    # apply DatasetOps\n    buffer_size = 10000\n    ds1 = ds1.shuffle(buffer_size=buffer_size)\n    ds1 = ds1.batch(batch_size, drop_remainder=True)\n    ds1 = ds1.repeat(repeat_size)\n\n    return ds1\n\n\nif __name__ == \"__main__\":\n    # This configure can run both in pynative mode and graph mode\n    context.set_context(mode=context.GRAPH_MODE,\n                        device_target=cfg.device_target)\n    network = LeNet5()\n    net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction=\"mean\")\n    config_ck = CheckpointConfig(\n        save_checkpoint_steps=cfg.save_checkpoint_steps,\n        keep_checkpoint_max=cfg.keep_checkpoint_max)\n    ckpoint_cb = ModelCheckpoint(prefix=\"checkpoint_lenet\",\n                                 directory='./trained_ckpt_file/',\n                                 config=config_ck)\n\n    # get training dataset\n    ds_train = generate_mnist_dataset(os.path.join(cfg.data_path, \"train\"),\n                                      cfg.batch_size)\n\n    if cfg.micro_batches and cfg.batch_size % cfg.micro_batches != 0:\n        raise ValueError(\n            \"Number of micro_batches should divide evenly batch_size\")\n    # Create a factory class of DP noise mechanisms, this method is adding noise\n    # in gradients while training. Mechanisms can be 'Gaussian'\n    # or 'AdaGaussian', in which noise would be decayed with 'AdaGaussian'\n    # mechanism while be constant with 'Gaussian' mechanism.\n    noise_mech = NoiseMechanismsFactory().create(cfg.noise_mechanisms,\n                                                 norm_bound=cfg.norm_bound,\n                                                 initial_noise_multiplier=cfg.initial_noise_multiplier,\n                                                 decay_policy=cfg.decay_policy)\n\n    net_opt = nn.SGD(params=network.trainable_params(),\n                     learning_rate=cfg.lr, momentum=cfg.momentum)\n    # Create a monitor for DP training. The function of the monitor is to\n    # compute and print the privacy budget(eps and delta) while training.\n    rdp_monitor = PrivacyMonitorFactory.create('rdp',\n                                               num_samples=60000,\n                                               batch_size=cfg.batch_size,\n                                               initial_noise_multiplier=cfg.initial_noise_multiplier,\n                                               per_print_times=234,\n                                               target_delta=1e-5)\n    # Create the DP model for training.\n    model = DPModel(micro_batches=cfg.micro_batches,\n                    norm_bound=cfg.norm_bound,\n                    noise_mech=noise_mech,\n                    network=network,\n                    loss_fn=net_loss,\n                    optimizer=net_opt,\n                    metrics={\"Accuracy\": Accuracy()})\n\n    LOGGER.info(TAG, \"============== Starting Training ==============\")\n    model.train(cfg['epoch_size'], ds_train,\n                callbacks=[ckpoint_cb, LossMonitor(), rdp_monitor],\n                dataset_sink_mode=cfg.dataset_sink_mode)\n\n    LOGGER.info(TAG, \"============== Starting Testing ==============\")\n    ckpt_file_name = 'trained_ckpt_file/checkpoint_lenet-' + str(cfg.epoch_size) + '_234.ckpt'\n    param_dict = load_checkpoint(ckpt_file_name)\n    load_param_into_net(network, param_dict)\n    ds_eval = generate_mnist_dataset(os.path.join(cfg.data_path, 'test'),\n                                     batch_size=cfg.batch_size)\n    acc = model.eval(ds_eval, dataset_sink_mode=False)\n    LOGGER.info(TAG, \"============== Accuracy: %s  ==============\", acc)\n"
  },
  {
    "path": "examples/privacy/diff_privacy/lenet5_dp_optimizer.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\npython lenet5_dp_pynative_model.py --data_path /YourDataPath --micro_batches=2\n\"\"\"\nimport os\n\nimport mindspore.nn as nn\nfrom mindspore import context\nfrom mindspore.train.callback import ModelCheckpoint\nfrom mindspore.train.callback import CheckpointConfig\nfrom mindspore.train.callback import LossMonitor\nfrom mindspore.nn.metrics import Accuracy\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nimport mindspore.dataset as ds\nimport mindspore.dataset.vision as CV\nimport mindspore.dataset.transforms as C\nfrom mindspore.dataset.vision import Inter\nimport mindspore.common.dtype as mstype\n\nfrom mindarmour.privacy.diff_privacy import DPModel\nfrom mindarmour.privacy.diff_privacy import PrivacyMonitorFactory\nfrom mindarmour.privacy.diff_privacy import DPOptimizerClassFactory\nfrom mindarmour.privacy.diff_privacy import ClipMechanismsFactory\nfrom mindarmour.utils.logger import LogUtil\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\nfrom lenet5_config import mnist_cfg as cfg\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'Lenet5_train'\n\n\ndef generate_mnist_dataset(data_path, batch_size=32, repeat_size=1,\n                           num_parallel_workers=1, sparse=True):\n    \"\"\"\n    create dataset for training or testing\n    \"\"\"\n    # define dataset\n    ds1 = ds.MnistDataset(data_path)\n\n    # define operation parameters\n    resize_height, resize_width = 32, 32\n    rescale = 1.0 / 255.0\n    shift = 0.0\n\n    # define map operations\n    resize_op = CV.Resize((resize_height, resize_width),\n                          interpolation=Inter.LINEAR)\n    rescale_op = CV.Rescale(rescale, shift)\n    hwc2chw_op = CV.HWC2CHW()\n    type_cast_op = C.TypeCast(mstype.int32)\n\n    # apply map operations on images\n    if not sparse:\n        one_hot_enco = C.OneHot(10)\n        ds1 = ds1.map(input_columns=\"label\", operations=one_hot_enco,\n                      num_parallel_workers=num_parallel_workers)\n        type_cast_op = C.TypeCast(mstype.float32)\n    ds1 = ds1.map(input_columns=\"label\", operations=type_cast_op,\n                  num_parallel_workers=num_parallel_workers)\n    ds1 = ds1.map(input_columns=\"image\", operations=resize_op,\n                  num_parallel_workers=num_parallel_workers)\n    ds1 = ds1.map(input_columns=\"image\", operations=rescale_op,\n                  num_parallel_workers=num_parallel_workers)\n    ds1 = ds1.map(input_columns=\"image\", operations=hwc2chw_op,\n                  num_parallel_workers=num_parallel_workers)\n\n    # apply DatasetOps\n    buffer_size = 10000\n    ds1 = ds1.shuffle(buffer_size=buffer_size)\n    ds1 = ds1.batch(batch_size, drop_remainder=True)\n    ds1 = ds1.repeat(repeat_size)\n\n    return ds1\n\n\nif __name__ == \"__main__\":\n    context.set_context(mode=context.GRAPH_MODE, device_target=cfg.device_target)\n    network = LeNet5()\n    net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction=\"mean\")\n    config_ck = CheckpointConfig(save_checkpoint_steps=cfg.save_checkpoint_steps,\n                                 keep_checkpoint_max=cfg.keep_checkpoint_max)\n    ckpoint_cb = ModelCheckpoint(prefix=\"checkpoint_lenet\",\n                                 directory='./trained_ckpt_file/',\n                                 config=config_ck)\n\n    # get training dataset\n    ds_train = generate_mnist_dataset(os.path.join(cfg.data_path, \"train\"),\n                                      cfg.batch_size)\n\n    if cfg.micro_batches and cfg.batch_size % cfg.micro_batches != 0:\n        raise ValueError(\"Number of micro_batches should divide evenly batch_size\")\n    # Create a factory class of DP mechanisms, this method is adding noise in gradients while training.\n    # Mechanisms can be 'Gaussian' or 'AdaGaussian', in which noise\n    # would be decayed with 'AdaGaussian' mechanism while be constant with 'Gaussian' mechanism.\n    dp_opt = DPOptimizerClassFactory(micro_batches=cfg.micro_batches)\n    dp_opt.set_mechanisms(cfg.noise_mechanisms,\n                          norm_bound=cfg.norm_bound,\n                          initial_noise_multiplier=cfg.initial_noise_multiplier,\n                          decay_policy=None)\n    # Create a factory class of clip mechanisms, this method is to adaptive clip\n    # gradients while training, decay_policy support 'Linear' and 'Geometric',\n    # learning_rate is the learning rate to update clip_norm,\n    # target_unclipped_quantile is the target quantile of norm clip,\n    # fraction_stddev is the stddev of Gaussian normal which used in\n    # empirical_fraction, the formula is\n    # $empirical_fraction + N(0, fraction_stddev)$.\n    clip_mech = ClipMechanismsFactory().create(cfg.clip_mechanisms,\n                                               decay_policy=cfg.clip_decay_policy,\n                                               learning_rate=cfg.clip_learning_rate,\n                                               target_unclipped_quantile=cfg.target_unclipped_quantile,\n                                               fraction_stddev=cfg.fraction_stddev)\n    net_opt = dp_opt.create('Momentum')(params=network.trainable_params(), learning_rate=cfg.lr, momentum=cfg.momentum)\n    # Create a monitor for DP training. The function of the monitor is to compute and print the privacy budget(eps\n    # and delta) while training.\n    rdp_monitor = PrivacyMonitorFactory.create('rdp',\n                                               num_samples=60000,\n                                               batch_size=cfg.batch_size,\n                                               initial_noise_multiplier=cfg.initial_noise_multiplier*cfg.norm_bound,\n                                               per_print_times=10,\n                                               target_delta=1e-5)\n    # Create the DP model for training.\n    model = DPModel(micro_batches=cfg.micro_batches,\n                    norm_bound=cfg.norm_bound,\n                    noise_mech=None,\n                    clip_mech=clip_mech,\n                    network=network,\n                    loss_fn=net_loss,\n                    optimizer=net_opt,\n                    metrics={\"Accuracy\": Accuracy()})\n\n    LOGGER.info(TAG, \"============== Starting Training ==============\")\n    model.train(cfg['epoch_size'], ds_train, callbacks=[ckpoint_cb, LossMonitor(), rdp_monitor],\n                dataset_sink_mode=cfg.dataset_sink_mode)\n\n    LOGGER.info(TAG, \"============== Starting Testing ==============\")\n    ckpt_file_name = 'trained_ckpt_file/checkpoint_lenet-5_234.ckpt'\n    param_dict = load_checkpoint(ckpt_file_name)\n    load_param_into_net(network, param_dict)\n    ds_eval = generate_mnist_dataset(os.path.join(cfg.data_path, 'test'), batch_size=cfg.batch_size)\n    acc = model.eval(ds_eval, dataset_sink_mode=False)\n    LOGGER.info(TAG, \"============== Accuracy: %s  ==============\", acc)\n"
  },
  {
    "path": "examples/privacy/inversion_attack/README.md",
    "content": "# 模型逆向攻击\n\n使用MindSpore框架和MindArmour工具包实现的CIFAR-10图像反演攻击的Python脚本。该脚本利用深度学习模型对CIFAR-10数据集中的图像进行反演攻击，以评估模型的隐私保护能力。构造原始模型相应的逆向模型进行训练，将原始模型输出作为逆向模型输入，原始模型输入作为逆向模型输出。也可使用mindarmour-master\\examples\\privacy\\inversion_attack目录下的cifar-black-box.py进行测试。\n\n## 脚本说明\n\n### 1. 加载模型参数及数据集（数据集由此网站下载http://www.cs.toronto.edu/~kriz/cifar.html      数据集共有60000张32*32的彩色图像，分为10个类别，每类有6000张图集一共有50000张训练图片和10000张评估图片。）\n\n```python\n# 加载训练好的网络参数\nload_dict = load_checkpoint(ckptpath)\nload_param_into_net(net, load_dict)\n# 获取原始数据\nds = generate_dataset_cifar(data_list, 32, repeat_num=1)\nds_test = generate_dataset_cifar(data_list, 32, repeat_num=1)\n```\n此处要求写明数据集路径，并定义参数，举例\n    # get original data and their inferred fearures\n    data_list = \"../../common/dataset/CIFAR10\" #/train\n    ds = generate_dataset_cifar(data_list, 32, usage=\"train\", repeat_num=1)\n    data_list = \"../../common/dataset/CIFAR10\" #/test\n    ds_test = generate_dataset_cifar(data_list, 32, usage=\"test\", repeat_num=1)\n### 1.1.\n定义逆向网络inv_net需满足：\n\n输入/输出匹配\n\n输入维度 = 原始模型在split_layer的特征维度（如conv11输出）\n\n输出维度 = 原始模型输入维度（如CIFAR-10为3×32×32）\n\n结构对称性\n\n原始模型卷积层 → 逆向网络转置卷积层\n\n原始模型池化层 → 逆向网络上采样层\n\n举例：\nclass CIFAR10CNNDecoderConv11(nn.Cell):\n    def __init__(self):\n        super().__init__()\n        self.decoder = nn.SequentialCell([\n            # 输入: [batch, 64, 8, 8]\n            nn.Conv2dTranspose(64, 64, 4, stride=2, padding=1),  # 输出16×16\n            nn.BatchNorm2d(64),\n            nn.ReLU(),\n            nn.Conv2dTranspose(64, 32, 4, stride=2, padding=1),  # 输出32×32\n            nn.BatchNorm2d(32),\n            nn.ReLU(),\n            nn.Conv2d(32, 3, 3, padding=1),  # 输出3通道\n            nn.Sigmoid()  # 约束输出到[0,1]\n        ])\n    \n    def construct(self, x):\n        return self.decoder(x)\n\n\n### 2. 运行攻击\n\n由用户自主定义逆向网络`inv_net`，保证逆向网络输入与原始网络输出一致，逆向网络输出与原始网络输入一致。\n\n```python\nmodel_inversion_attack = ModelInversionAttack(net, inv_net, input_shape=(3, 32, 32), split_layer='conv11')\nmodel_inversion_attack.train_inversion_model(ds, epochs=100)\n```\n\n### 3. 反演图像\n\n```python\n# 反演图像\ninversion_images = model_inversion_attack.inverse(target_features).asnumpy()\ninversion_images = inversion_images.clip(0, 1)\n# 评估反演图像质量\navg_ssim, avg_psnr = model_inversion_attack.evaluate(ds_test) LOGGER.info(TAG, '原始图像与反演图像之间的平均ssim值是：{}'.format(avg_ssim))\nLOGGER.info(TAG, '原始图像与反演图像之间的平均psnr值是：{}'.format(avg_psnr))\n```\n\n## 逆向攻击参数介绍\n\n1.`ModelInversionAttack` 模块介绍\n\n```Python\nclass ModelInversionAttack:\n    def __init__(self, network, inv_network, input_shape, ckpoint_path=None, split_layer='conv1'):\n...\n```\n\n构建模型逆向攻击对象\n输入：\n\n- netword：原始网络\n- inv_network：逆向网络\n- input_shape：输入图像维度\n- ckpoint_path：逆向网络参数\n- split_layer：原始网络输出层\n\n2. 逆向网络训练\n\n```python\ndef train_inversion_model(self, dataset, epochs=50, learningrate=1e-3, eps=1e-3, apply_ams=True):\n```\n\n训练逆向网络\n输入：\n\n- dataset：原始数据集或构造数据集\n- epochs：训练轮次\n- learningrate：训练学习率\n- eps：增加数值计算稳定性\n- apply_ams：启用自适应移动平均\n\n## 攻击效果\n\n![modelinversion](./imgs/modelinversion.png)\n\n# 影子模型攻击\n\n使用MindSpore框架和MindArmour工具包实现的CIFAR-10影子模型攻击的Python脚本。该脚本利用深度学习模型对CIFAR-10数据集中的图像进行反演攻击，以评估模型的隐私保护能力。构造与原始模型输入输出维度一致的影子模型，使得通过对影子模型进行参数逆向攻击达到与原始模型参数逆向攻击一致的效果。\n\n## 脚本说明\n\n### 1. 加载模型参数及数据集\n\n```python\n# 加载训练好的网络参数\nload_dict = load_checkpoint(ckptpath)\nload_param_into_net(net, load_dict)\n# 获取原始数据\nds = generate_dataset_cifar(data_list, 32, repeat_num=1)\nds_test = generate_dataset_cifar(data_list, 32, repeat_num=1)\n```\n\n### 2. 构造影子模型\n\n```python\n# 运行攻击\nshadow_model_attack = ShadowModelAttack(net, shadow_net, split_layer='conv11')\nshadow_model_attack.train_shadow_model(ds, attack_config={'epochs': 100}) shadow_model_attack.evaluate(ds_test, 10)\n```\n\n### 3. 反演影子模型\n\n```python\n# 图像反演\ninversion_attack = ImageInversionAttack(shadow_net, (3, 32, 32), input_bound=(0, 1), loss_weights=(1, 0.1, 5))\ninversion_images = inversion_attack.generate(target_features, iters=150)\n# 评估反演图像质量\navg_l2_dis, avg_ssim, _ = inversion_attack.evaluate(original_images, inversion_images)\nLOGGER.info(TAG, '原始图像与反演图像之间的平均L2距离是：{}'.format(avg_l2_dis))\nLOGGER.info(TAG, '原始图像与反演图像之间的平均ssim值是：{}'.format(avg_ssim))\n```\n\n## 影子模型攻击参数介绍\n\n1. `ShadowModelAttack`\n\n```python\nclass ShadowModelAttack:\n    def __init__(self, network, shadow_network, ckpoint_path='', split_layer='conv1'):\n```\n\n构建影子模型攻击对象\n输入：\n\n- netword：原始网络\n- shadow_network：影子网络\n- ckpoint_path：逆向网络参数\n- split_layer：原始网络输出层\n\n1. 影子网络训练\n\n```python\ndef train_shadow_model(self, dataset, attack_config):\n```\n\n- dataset：原始数据集或构造数据集\n- attack_config ={\"epochs\": 50, \"learningrate\": 1e-3, \"eps\": 1e-3,\"num_classes\": 10, \"apply_ams\": True}\n    - epochs：训练轮次\n    - learningrate：训练学习率\n    - eps：增加数值计算稳定性\n    - num_classes：模型输出类别\n    - apply_ams：启用自适应移动平均\n\n## 影子模型攻击效果\n\n![shadowattack](./imgs/shadownattack.png)\n"
  },
  {
    "path": "examples/privacy/inversion_attack/__init__.py",
    "content": ""
  },
  {
    "path": "examples/privacy/inversion_attack/cifar_black_box.py",
    "content": "# Copyright 2024 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nExamples of model inversion attack\n\"\"\"\nimport numpy as np\nimport matplotlib.pyplot as plt\n\nimport mindspore as ms\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nfrom mindspore import Tensor, context\nfrom mindarmour.privacy.evaluation.model_inversion_attack import ModelInversionAttack\n# from mindarmour.privacy.evaluation.inversion_attack.inversion_net import CIFAR10CNNDecoderConv11\nfrom examples.privacy.inversion_attack.inversion_net import CIFAR10CNNDecoderConv11\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.networks.cifar10cnn.cifar10cnn_net import CIFAR10CNN\nfrom examples.common.dataset.data_processing import generate_dataset_cifar\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'ModelInversionAttack'\n\n\n# pylint: disable=invalid-name\n\n\ndef cifar_inversion_attack(net, inv_net, ckptpath):\n    \"\"\"\n    Image inversion attack based on CNN and CAFIR10 dataset.\n    Args:\n        net(Cell): target model\n        inv_net(Cell): atk model for model inversion\n        ckptpath(str): ckpt file for target model\n    \"\"\"\n    # upload trained network\n\n    load_dict = load_checkpoint(ckptpath)\n    load_param_into_net(net, load_dict)\n\n    # get original data and their inferred fearures\n    data_list = \"../../common/dataset/CIFAR10\" #/train\n    ds = generate_dataset_cifar(data_list, 32, usage=\"train\", repeat_num=1)\n    data_list = \"../../common/dataset/CIFAR10\" #/test\n    ds_test = generate_dataset_cifar(data_list, 32, usage=\"test\", repeat_num=1)\n    i = 0\n    batch_num = 1\n    sample_num = 10\n    for data in ds_test.create_tuple_iterator(output_numpy=True):\n        i += 1\n        images = data[0].astype(np.float32)\n        target_features = net.get_layer_output(Tensor(images), 'conv11')[:sample_num]\n        if i >= batch_num:\n            break\n\n    # run attacking\n    model_inversion_attack = ModelInversionAttack(net, inv_net, input_shape=(3, 32, 32), split_layer='conv11')\n    model_inversion_attack.train_inversion_model(ds, epochs=100)\n\n    inversion_images = model_inversion_attack.inverse(target_features).asnumpy()\n    inversion_images = inversion_images.clip(0, 1)\n    # evaluate the quality of inversion images\n    avg_ssim, avg_psnr = model_inversion_attack.evaluate(ds_test)\n    LOGGER.info(TAG, 'The average ssim value between original images and inverted images is: {}'.format(avg_ssim))\n    LOGGER.info(TAG, 'The average psnr value between original images and inverted images is: {}'.format(avg_psnr))\n\n    # plot 10 images\n    plot_num = min(sample_num, 10)\n    for n in range(1, plot_num+1):\n        plt.subplot(2, plot_num, n)\n        if n == 1:\n            plt.title('Original images', fontsize=16, loc='left')\n        plt.imshow(images[n - 1].transpose(1, 2, 0))\n        plt.subplot(2, plot_num, n + plot_num)\n        if n == 1:\n            plt.title('Inverted images', fontsize=16, loc='left')\n        plt.gray()\n        plt.imshow(inversion_images[n - 1].transpose(1, 2, 0))\n    plt.show()\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=ms.PYNATIVE_MODE, device_target=\"CPU\")\n    ckpt_path = '../../common/networks/cifar10cnn/trained_ckpt_file/checkpoint_cifar-10_1562.ckpt'\n    cifar_inversion_attack(CIFAR10CNN(), CIFAR10CNNDecoderConv11(), ckpt_path)\n"
  },
  {
    "path": "examples/privacy/inversion_attack/cifar_shadow_attack.py",
    "content": "# Copyright 2024 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nExamples of shadow model attack\n\"\"\"\nimport numpy as np\nimport matplotlib.pyplot as plt\n\nimport mindspore as ms\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nfrom mindspore import Tensor, context\nfrom mindarmour.privacy.evaluation.inversion_attack import ImageInversionAttack\nfrom mindarmour.privacy.evaluation.shadow_model_attack import ShadowModelAttack\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.networks.cifar10cnn.cifar10cnn_net import CIFAR10CNN\nfrom examples.privacy.inversion_attack.shadow_net import CIFAR10CNNAlternativeConv11Arch2\nfrom examples.common.dataset.data_processing import generate_dataset_cifar\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'ShadowModelAttack'\n\n\n# pylint: disable=invalid-name\ndef cifar_inversion_attack(net, shadow_net, ckptpath):\n    \"\"\"\n    Image inversion attack based on CNN and CAFIR10 dataset.\n    Args:\n        net(Cell): target model\n        shadow_net(Cell): atk model for model inversion\n        ckptpath(str): ckpt file for target model\n    \"\"\"\n    # upload trained network\n    load_dict = load_checkpoint(ckptpath)\n    load_param_into_net(net, load_dict)\n\n    # get original data and their inferred fearures\n    data_list = \"../../common/dataset/CIFAR10/train\"\n    ds = generate_dataset_cifar(data_list, 32, repeat_num=1)\n    data_list = \"../../common/dataset/CIFAR10/test\"\n    ds_test = generate_dataset_cifar(data_list, 32, repeat_num=1)\n    i = 0\n    batch_num = 1\n    sample_num = 10\n\n    # run attacking\n    shadow_model_attack = ShadowModelAttack(net, shadow_net, split_layer='conv11')\n    shadow_model_attack.train_shadow_model(ds, attack_config={'epochs': 100})\n    shadow_model_attack.evaluate(ds_test, 10)\n    for data in ds_test.create_tuple_iterator(output_numpy=True):\n        i += 1\n        images = data[0].astype(np.float32)\n        target_features = shadow_net.getlayeroutput(Tensor(images), 'conv11').asnumpy()[:sample_num]\n        original_images = images[: sample_num]\n        if i >= batch_num:\n            break\n\n    inversion_attack = ImageInversionAttack(shadow_net, (3, 32, 32), input_bound=(0, 1), loss_weights=(1, 0.1, 5))\n    inversion_images = inversion_attack.generate(target_features, iters=150)\n    # evaluate the quality of inversion images\n    avg_l2_dis, avg_ssim, _ = inversion_attack.evaluate(original_images, inversion_images)\n    LOGGER.info(TAG, 'The average L2 distance between original images and inverted images is: {}'.format(avg_l2_dis))\n    LOGGER.info(TAG, 'The average ssim value between original images and inverted images is: {}'.format(avg_ssim))\n\n    # plot 10 images\n    plot_num = min(sample_num, 10)\n    for n in range(1, plot_num+1):\n        plt.subplot(2, plot_num, n)\n        if n == 1:\n            plt.title('Original images', fontsize=16, loc='left')\n        plt.imshow(images[n - 1].transpose(1, 2, 0))\n        plt.subplot(2, plot_num, n + plot_num)\n        if n == 1:\n            plt.title('Inverted images', fontsize=16, loc='left')\n        plt.imshow(inversion_images[n - 1].transpose(1, 2, 0))\n    plt.show()\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=ms.PYNATIVE_MODE, device_target=\"GPU\")\n    ckpt_path = 'examples/common/networks/cifar10cnn/trained_ckpt_file/checkpoint_cifar-10_1562.ckpt'\n    cifar_inversion_attack(CIFAR10CNN(), CIFAR10CNNAlternativeConv11Arch2(), ckpt_path)\n"
  },
  {
    "path": "examples/privacy/inversion_attack/inversion_net.py",
    "content": "\"\"\"\nInversion Attack Network\n\"\"\"\nfrom mindspore import nn\n\n\nclass LeNetDecoderConv1(nn.Cell):\n    \"\"\"\n    Conv1 -> Input\n    \"\"\"\n    def __init__(self):\n        super(LeNetDecoderConv1, self).__init__()\n        self.conv1 = nn.Conv2d(\n            in_channels=6,\n            out_channels=1,\n            kernel_size=5,\n            pad_mode='pad',\n            padding=4)\n\n    def construct(self, x):\n        return self.conv1(x)\n\n\nclass LeNetDecoderReLU2(nn.Cell):\n    \"\"\"\n    Conv2 -> ReLU -> Conv1 -> Input\n    \"\"\"\n    def __init__(self):\n        super(LeNetDecoderReLU2, self).__init__()\n        self.decoder = []\n\n        self.deconv1 = nn.Conv2dTranspose(\n            in_channels=16,\n            out_channels=6,\n            kernel_size=5,\n        )\n\n        self.relu1 = nn.ReLU()\n\n        self.deconv2 = nn.Conv2dTranspose(\n            in_channels=6,\n            out_channels=1,\n            kernel_size=5,\n            stride=3,\n            pad_mode='pad',\n            output_padding=0\n        )\n\n    def construct(self, x):\n        x = self.deconv1(x)\n        x = self.relu1(x)\n        x = self.deconv2(x)\n        return x\n\n\nclass CIFAR10CNNDecoderConv11(nn.Cell):\n    \"\"\"\n    Conv1 -> Input\n    \"\"\"\n    def __init__(self):\n        super(CIFAR10CNNDecoderConv11, self).__init__()\n        self.deconv1 = nn.Conv2dTranspose(\n            in_channels=64,\n            out_channels=3,\n            kernel_size=3,\n            pad_mode='pad',\n            padding=1\n        )\n\n    def construct(self, x):\n        x = self.deconv1(x)\n        return x\n\n\nclass CIFAR10CNNDecoderReLU22(nn.Cell):\n    \"\"\"\n    Conv22 -> ReLU22 -> Conv11 -> INPUT\n    \"\"\"\n    def __init__(self):\n        super(CIFAR10CNNDecoderReLU22, self).__init__()\n        self.deconv11 = nn.Conv2dTranspose(\n            in_channels=128,\n            out_channels=64,\n            kernel_size=3,\n            stride=2,\n            pad_mode='pad',\n            padding=1,\n            output_padding=1\n        )\n        self.relu1 = nn.ReLU()\n        self.deconv21 = nn.Conv2dTranspose(\n            in_channels=64,\n            out_channels=3,\n            kernel_size=3,\n            pad_mode='pad',\n            padding=1\n        )\n\n    def construct(self, x):\n        x = self.deconv11(x)\n        x = self.relu1(x)\n        x = self.deconv21(x)\n        return x\n\n\nclass CIFAR10CNNDecoderReLU32(nn.Cell):\n    \"\"\"\n    Conv33 -> ReLU22 -> Conv22 -> ReLU11 -> Conv11 -> Input\n    \"\"\"\n    def __init__(self):\n        super(CIFAR10CNNDecoderReLU32, self).__init__()\n        self.deconv11 = nn.Conv2dTranspose(\n            in_channels=128,\n            out_channels=128,\n            kernel_size=3,\n            stride=2,\n            padding=1,\n            pad_mode='pad',\n            output_padding=1\n        )\n        self.relu1 = nn.ReLU()\n        self.deconv21 = nn.Conv2dTranspose(\n            in_channels=128,\n            out_channels=64,\n            kernel_size=3,\n            stride=2,\n            padding=1,\n            pad_mode='pad',\n            output_padding=1\n        )\n        self.relu2 = nn.ReLU()\n\n        self.deconv31 = nn.Conv2dTranspose(\n            in_channels=64,\n            out_channels=3,\n            kernel_size=3,\n            padding=1\n        )\n\n    def construct(self, x):\n        x = self.deconv11(x)\n        x = self.relu1(x)\n        x = self.deconv21(x)\n        x = self.relu2(x)\n        x = self.deconv31(x)\n        return x\n"
  },
  {
    "path": "examples/privacy/inversion_attack/mnist_inversion_attack.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nExamples of image inversion attack\n\"\"\"\nimport numpy as np\nimport matplotlib.pyplot as plt\n\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nfrom mindspore import Tensor, context\nfrom mindspore import nn\nfrom mindarmour.privacy.evaluation.inversion_attack import ImageInversionAttack\nfrom mindarmour.utils.logger import LogUtil\n\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5, conv, fc_with_initialize\nfrom examples.common.dataset.data_processing import generate_mnist_dataset\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'InversionAttack'\n\n\n# pylint: disable=invalid-name\nclass LeNet5_part(nn.Cell):\n    \"\"\"\n    Part of LeNet5 network.\n    \"\"\"\n    def __init__(self):\n        super(LeNet5_part, self).__init__()\n        self.conv1 = conv(1, 6, 5)\n        self.conv2 = conv(6, 16, 5)\n        self.fc1 = fc_with_initialize(16*5*5, 120)\n        self.fc2 = fc_with_initialize(120, 84)\n        self.fc3 = fc_with_initialize(84, 10)\n        self.relu = nn.ReLU()\n        self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.flatten = nn.Flatten()\n\n    def construct(self, x):\n        x = self.conv1(x)\n        x = self.relu(x)\n        x = self.max_pool2d(x)\n        x = self.conv2(x)\n        x = self.relu(x)\n        x = self.max_pool2d(x)\n        return x\n\n\ndef mnist_inversion_attack(net):\n    \"\"\"\n    Image inversion attack based on LeNet5 and MNIST dataset.\n    \"\"\"\n    # upload trained network\n    ckpt_path = '../../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get original data and their inferred fearures\n    data_list = \"../../common/dataset/MNIST/train\"\n    batch_size = 32\n    ds = generate_mnist_dataset(data_list, batch_size)\n    i = 0\n    batch_num = 1\n    sample_num = 30\n    for data in ds.create_tuple_iterator(output_numpy=True):\n        i += 1\n        images = data[0].astype(np.float32)\n        true_labels = data[1][: sample_num]\n        target_features = net(Tensor(images)).asnumpy()[:sample_num]\n        original_images = images[: sample_num]\n        if i >= batch_num:\n            break\n\n    # run attacking\n    inversion_attack = ImageInversionAttack(net, input_shape=(1, 32, 32), input_bound=(0, 1), loss_weights=[1, 0.1, 5])\n    inversion_images = inversion_attack.generate(target_features, iters=100)\n\n    # get the predict results of inversion images on a new trained model\n    net2 = LeNet5()\n    new_ckpt_path = '../../common/networks/lenet5/new_trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    new_load_dict = load_checkpoint(new_ckpt_path)\n    load_param_into_net(net2, new_load_dict)\n    pred_labels = np.argmax(net2(Tensor(inversion_images).astype(np.float32)).asnumpy(), axis=1)\n\n    # evaluate the quality of inversion images\n    avg_l2_dis, avg_ssim, avg_confi = inversion_attack.evaluate(original_images, inversion_images, true_labels, net2)\n    LOGGER.info(TAG, 'The average L2 distance between original images and inverted images is: {}'.format(avg_l2_dis))\n    LOGGER.info(TAG, 'The average ssim value between original images and inverted images is: {}'.format(avg_ssim))\n    LOGGER.info(TAG, 'The average prediction confidence on true labels of inverted images is: {}'.format(avg_confi))\n    LOGGER.info(TAG, 'True labels of original images are:      %s', true_labels)\n    LOGGER.info(TAG, 'Predicted labels of inverted images are: %s', pred_labels)\n\n    # plot 10 images\n    plot_num = min(sample_num, 10)\n    for n in range(1, plot_num+1):\n        plt.subplot(2, plot_num, n)\n        if n == 1:\n            plt.title('Original images', fontsize=16, loc='left')\n        plt.gray()\n        plt.imshow(images[n - 1].reshape(32, 32))\n        plt.subplot(2, plot_num, n + plot_num)\n        if n == 1:\n            plt.title('Inverted images', fontsize=16, loc='left')\n        plt.gray()\n        plt.imshow(inversion_images[n - 1].reshape(32, 32))\n    plt.show()\n\n\nif __name__ == '__main__':\n    # device_target can be \"CPU\", \"GPU\" or \"Ascend\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    # attack based on complete LeNet5\n    mnist_inversion_attack(LeNet5())\n    # attack based on part of LeNet5. The network is more shallower and can lead to a better attack result\n    mnist_inversion_attack(LeNet5_part())\n"
  },
  {
    "path": "examples/privacy/inversion_attack/shadow_net.py",
    "content": "\"\"\"\nShadow Attack Alternative Network\n\"\"\"\nimport collections\nfrom mindspore import nn\n\n\nclass LeNetAlternativeConv1(nn.Cell):\n    \"\"\"\n    LeNet Conv1\n    \"\"\"\n    def __init__(self):\n        super(LeNetAlternativeConv1, self).__init__()\n        self.features = []\n        self.classifier = []\n        self.layerdict = collections.OrderedDict()\n\n        self.conv0 = nn.Conv2d(\n            in_channels=1,\n            out_channels=6,\n            kernel_size=5,\n        )\n        self.features.append(self.conv0)\n        self.layerdict['conv0'] = self.conv0\n\n        self.conv1 = nn.Conv2d(\n            in_channels=6,\n            out_channels=16,\n            kernel_size=5,\n        )\n        self.features.append(self.conv1)\n        self.layerdict['conv1'] = self.conv1\n\n    def construct(self, x):\n        for layer in self.features:\n            x = layer(x)\n        return x\n\n\nclass LeNetAlternativeConv1Arch2(nn.Cell):\n    \"\"\"\n    LeNet Conv1\n    \"\"\"\n    def __init__(self):\n        super(LeNetAlternativeConv1Arch2, self).__init__()\n        self.features = []\n        self.classifier = []\n        self.layerdict = collections.OrderedDict()\n\n        self.conv0 = nn.Conv2d(\n            in_channels=1,\n            out_channels=6,\n            kernel_size=5,\n        )\n        self.features.append(self.conv0)\n        self.layerdict['conv0'] = self.conv0\n\n        self.conv1 = nn.Conv2d(\n            in_channels=6,\n            out_channels=6,\n            kernel_size=5,\n        )\n        self.features.append(self.conv1)\n        self.layerdict['conv1'] = self.conv1\n\n    def construct(self, x):\n        for layer in self.features:\n            x = layer(x)\n        return x\n\n\nclass LeNetAlternativeReLU1(nn.Cell):\n    \"\"\"\n    LeNet ReLU1\n    \"\"\"\n    def __init__(self):\n        super(LeNetAlternativeReLU1, self).__init__()\n        self.features = []\n        self.classifier = []\n        self.layerdict = collections.OrderedDict()\n\n        self.conv1 = nn.Conv2d(\n            in_channels=1,\n            out_channels=6,\n            kernel_size=5,\n        )\n        self.features.append(self.conv1)\n        self.layerdict['conv1'] = self.conv1\n\n        self.relu1 = nn.ReLU()\n        self.features.append(self.relu1)\n        self.layerdict['relu1'] = self.relu1\n\n    def construct(self, x):\n        for layer in self.features:\n            x = layer(x)\n        return x\n\n\nclass LeNetAlternativePool1(nn.Cell):\n    \"\"\"\n    LeNet Pool1\n    \"\"\"\n    def __init__(self):\n        super(LeNetAlternativePool1, self).__init__()\n        self.features = []\n        self.classifier = []\n        self.layerdict = collections.OrderedDict()\n\n        self.conv1 = nn.Conv2d(\n            in_channels=1,\n            out_channels=6,\n            kernel_size=5,\n        )\n        self.features.append(self.conv1)\n        self.layerdict['conv1'] = self.conv1\n\n        self.relu1 = nn.ReLU()\n        self.features.append(self.relu1)\n        self.layerdict['relu1'] = self.relu1\n\n        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.features.append(self.pool1)\n        self.layerdict['pool1'] = self.pool1\n\n    def construct(self, x):\n        for layer in self.features:\n            x = layer(x)\n        return x\n\n\nclass LeNetAlternativeConv2(nn.Cell):\n    \"\"\"\n    LeNet Conv2\n    \"\"\"\n    def __init__(self):\n        super(LeNetAlternativeConv2, self).__init__()\n        self.features = []\n        self.classifier = []\n        self.layerdict = collections.OrderedDict()\n\n        self.conv1 = nn.Conv2d(\n            in_channels=1,\n            out_channels=6,\n            kernel_size=5,\n        )\n        self.features.append(self.conv1)\n        self.layerdict['conv1'] = self.conv1\n\n        self.relu1 = nn.ReLU()\n        self.features.append(self.relu1)\n        self.layerdict['relu1'] = self.relu1\n\n        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.features.append(self.pool1)\n        self.layerdict['pool1'] = self.pool1\n\n        self.conv2 = nn.Conv2d(\n            in_channels=6,\n            out_channels=16,\n            kernel_size=5,\n        )\n        self.features.append(self.conv2)\n        self.layerdict['conv2'] = self.conv2\n\n    def construct(self, x):\n        for layer in self.features:\n            x = layer(x)\n        return x\n\n\nclass LeNetAlternativeReLU2(nn.Cell):\n    \"\"\"\n    LeNet ReLU2\n    \"\"\"\n    def __init__(self):\n        super(LeNetAlternativeReLU2, self).__init__()\n        self.features = []\n        self.classifier = []\n        self.layerdict = collections.OrderedDict()\n\n        self.conv1 = nn.Conv2d(\n            in_channels=1,\n            out_channels=6,\n            kernel_size=5,\n        )\n        self.features.append(self.conv1)\n        self.layerdict['conv1'] = self.conv1\n\n        self.relu1 = nn.ReLU()\n        self.features.append(self.relu1)\n        self.layerdict['relu1'] = self.relu1\n\n        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.features.append(self.pool1)\n        self.layerdict['pool1'] = self.pool1\n\n        self.conv2 = nn.Conv2d(\n            in_channels=6,\n            out_channels=16,\n            kernel_size=5,\n        )\n        self.features.append(self.conv2)\n        self.layerdict['conv2'] = self.conv2\n\n        self.relu2 = nn.ReLU()\n        self.features.append(self.relu2)\n        self.layerdict['relu2'] = self.relu2\n\n    def construct(self, x):\n        for layer in self.features:\n            x = layer(x)\n        return x\n\n\nclass LeNetAlternativePool2(nn.Cell):\n    \"\"\"\n    LeNet Pool2\n    \"\"\"\n    def __init__(self):\n        super(LeNetAlternativePool2, self).__init__()\n        self.features = []\n        self.classifier = []\n        self.layerdict = collections.OrderedDict()\n\n        self.conv1 = nn.Conv2d(\n            in_channels=1,\n            out_channels=6,\n            kernel_size=5,\n        )\n        self.features.append(self.conv1)\n        self.layerdict['conv1'] = self.conv1\n\n        self.relu1 = nn.ReLU()\n        self.features.append(self.relu1)\n        self.layerdict['relu1'] = self.relu1\n\n        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.features.append(self.pool1)\n        self.layerdict['pool1'] = self.pool1\n\n        self.conv2 = nn.Conv2d(\n            in_channels=6,\n            out_channels=16,\n            kernel_size=5,\n        )\n        self.features.append(self.conv2)\n        self.layerdict['conv2'] = self.conv2\n\n        self.relu2 = nn.ReLU()\n        self.features.append(self.relu2)\n        self.layerdict['relu2'] = self.relu22\n\n        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.features.append(self.pool2)\n        self.layerdict['pool2'] = self.pool2\n\n    def construct(self, x):\n        for layer in self.features:\n            x = layer(x)\n        return x\n\n\nclass LeNetAlternativeFc1(nn.Cell):\n    \"\"\"\n    LeNet Fc1\n    \"\"\"\n    def __init__(self):\n        super(LeNetAlternativeFc1, self).__init__()\n        self.features = []\n        self.classifier = []\n        self.layerdict = collections.OrderedDict()\n\n        self.conv1 = nn.Conv2d(\n            in_channels=1,\n            out_channels=6,\n            kernel_size=5,\n        )\n        self.features.append(self.conv1)\n        self.layerdict['conv1'] = self.conv1\n\n        self.relu1 = nn.ReLU()\n        self.features.append(self.relu1)\n        self.layerdict['relu1'] = self.relu1\n\n        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.features.append(self.pool1)\n        self.layerdict['pool1'] = self.pool1\n\n        self.conv2 = nn.Conv2d(\n            in_channels=6,\n            out_channels=16,\n            kernel_size=5,\n        )\n        self.features.append(self.conv2)\n        self.layerdict['conv2'] = self.conv2\n\n        self.relu2 = nn.ReLU()\n        self.features.append(self.relu2)\n        self.layerdict['relu2'] = self.relu2\n\n        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.features.append(self.pool2)\n        self.layerdict['pool2'] = self.pool2\n\n        self.feature_dim = 16 * 5 * 5\n        self.fc1 = nn.Dense(16 * 5 * 5, 120)\n        self.classifier.append(self.fc1)\n        self.layerdict['fc1'] = self.fc1\n\n    def construct(self, x):\n        for layer in self.features:\n            x = layer(x)\n        x = x.view(-1, self.feature_dim)\n        for layer in self.classifier:\n            x = layer(x)\n        return x\n\n\nclass LeNetAlternativeFc1Act(nn.Cell):\n    \"\"\"\n    LeNet Fc1Act\n    \"\"\"\n    def __init__(self):\n        super(LeNetAlternativeFc1Act, self).__init__()\n        self.features = []\n        self.classifier = []\n        self.layerdict = collections.OrderedDict()\n\n        self.conv1 = nn.Conv2d(\n            in_channels=1,\n            out_channels=6,\n            kernel_size=5,\n        )\n        self.features.append(self.conv1)\n        self.layerdict['conv1'] = self.conv1\n\n        self.relu1 = nn.ReLU()\n        self.features.append(self.relu1)\n        self.layerdict['relu1'] = self.relu1\n\n        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.features.append(self.pool1)\n        self.layerdict['pool1'] = self.pool1\n\n        self.conv2 = nn.Conv2d(\n            in_channels=6,\n            out_channels=16,\n            kernel_size=5,\n        )\n        self.features.append(self.conv2)\n        self.layerdict['conv2'] = self.conv2\n\n        self.relu2 = nn.ReLU()\n        self.features.append(self.relu2)\n        self.layerdict['relu2'] = self.relu2\n\n        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.features.append(self.pool2)\n        self.layerdict['pool2'] = self.pool2\n\n        self.feature_dim = 16 * 5 * 5\n        self.fc1 = nn.Dense(16 * 5 * 5, 120)\n        self.classifier.append(self.fc1)\n        self.layerdict['fc1'] = self.fc1\n\n        self.fc1act = nn.ReLU()\n        self.classifier.append(self.fc1act)\n        self.layerdict['fc1act'] = self.fc1act\n\n    def construct(self, x):\n        for layer in self.features:\n            x = layer(x)\n        x = x.view(-1, self.feature_dim)\n        for layer in self.classifier:\n            x = layer(x)\n        return x\n\n\nclass CIFAR10CNNAlternativeConv11(nn.Cell):\n    \"\"\"\n    CIFAR10CNN Alternative Conv11 network\n    \"\"\"\n    def __init__(self):\n        super(CIFAR10CNNAlternativeConv11, self).__init__()\n        self.features = []\n        self.layerdict = collections.OrderedDict()\n\n        self.conv11 = nn.Conv2d(\n            in_channels=3,\n            out_channels=64,\n            kernel_size=3,\n            pad_mode='pad',\n            padding=1,\n        )\n        self.features.append(self.conv11)\n        self.layerdict['conv11'] = self.conv11\n\n    def construct(self, x):\n        for layer in self.features:\n            x = layer(x)\n        return x\n\n    def getlayeroutput(self, x, targetlayer):\n        targetlayer = self.layerdict.get(targetlayer, None)\n        for layer in self.features:\n            x = layer(x)\n            if layer == targetlayer:\n                return x\n        msg = \"Target Layer Error !\"\n        raise ValueError(msg)\n\n\nclass CIFAR10CNNAlternativeConv11Arch2(nn.Cell):\n    \"\"\"\n    CIFAR10CNN Alternative Conv11Arch2 network\n    \"\"\"\n    def __init__(self):\n        super(CIFAR10CNNAlternativeConv11Arch2, self).__init__()\n        self.features = []\n        self.layerdict = collections.OrderedDict()\n\n        self.conv10 = nn.Conv2d(\n            in_channels=3,\n            out_channels=16,\n            kernel_size=3,\n            pad_mode='pad',\n            padding=1,\n        )\n        self.features.append(self.conv10)\n        self.layerdict['conv10'] = self.conv10\n\n        self.conv11 = nn.Conv2d(\n            in_channels=16,\n            out_channels=64,\n            kernel_size=3,\n            pad_mode='pad',\n            padding=1,\n        )\n        self.features.append(self.conv11)\n        self.layerdict['conv11'] = self.conv11\n\n    def construct(self, x):\n        for layer in self.features:\n            x = layer(x)\n        return x\n\n    def getlayeroutput(self, x, targetlayer):\n        targetlayer = self.layerdict.get(targetlayer, None)\n        for layer in self.features:\n            x = layer(x)\n            if layer == targetlayer:\n                return x\n        msg = \"Target Layer Error !\"\n        raise ValueError(msg)\n\n\nclass CIFAR10CNNAlternativeReLU22(nn.Cell):\n    \"\"\"\n    CIFAR10CNN Alternative ReLU22 network\n    \"\"\"\n    def __init__(self):\n        super(CIFAR10CNNAlternativeReLU22, self).__init__()\n        self.features = []\n        self.layerdict = collections.OrderedDict()\n\n        self.conv11 = nn.Conv2d(\n            in_channels=3,\n            out_channels=64,\n            kernel_size=3,\n            pad_mode='pad',\n            padding=1,\n        )\n        self.features.append(self.conv1)\n        self.layerdict['conv1'] = self.conv1\n\n        self.relu11 = nn.ReLU()\n        self.features.append(self.relu1)\n        self.layerdict['relu1'] = self.relu1\n\n        self.conv12 = nn.Conv2d(\n            in_channels=64,\n            out_channels=64,\n            kernel_size=3,\n            pad_mode='pad',\n            padding=1,\n        )\n        self.features.append(self.conv12)\n        self.layerdict['conv12'] = self.conv12\n\n        self.relu12 = nn.ReLU()\n        self.features.append(self.relu12)\n        self.layerdict['relu12'] = self.relu12\n\n        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.features.append(self.pool1)\n        self.layerdict['pool1'] = self.pool1\n\n        self.conv21 = nn.Conv2d(\n            in_channels=64,\n            out_channels=128,\n            kernel_size=3,\n            pad_mode='pad',\n            padding=1,\n        )\n        self.features.append(self.conv21)\n        self.layerdict['conv21'] = self.conv21\n\n        self.relu21 = nn.ReLU()\n        self.features.append(self.relu21)\n        self.layerdict['relu21'] = self.relu21\n\n        self.conv22 = nn.Conv2d(\n            in_channels=128,\n            out_channels=128,\n            kernel_size=3,\n            pad_mode='pad',\n            padding=1,\n        )\n        self.features.append(self.conv22)\n        self.layerdict['conv22'] = self.conv22\n\n        self.relu22 = nn.ReLU()\n        self.features.append(self.relu22)\n        self.layerdict['relu22'] = self.relu22\n\n    def construct(self, x):\n        for layer in self.features:\n            x = layer(x)\n        return x\n\n    def getlayeroutput(self, x, targetlayer):\n        targetlayer = self.layerdict.get(targetlayer, None)\n        for layer in self.features:\n            x = layer(x)\n            if layer == targetlayer:\n                return x\n        msg = \"Target Layer Error !\"\n        raise ValueError(msg)\n\n\nclass CIFAR10CNNAlternativeReLU22Arch2(nn.Cell):\n    \"\"\"\n    CIFAR10CNN Alternative ReLU22Arch2 network structure\n    \"\"\"\n    def __init__(self):\n        super(CIFAR10CNNAlternativeReLU22Arch2, self).__init__()\n        self.features = []\n        self.layerdict = collections.OrderedDict()\n\n        self.conv11 = nn.Conv2d(\n            in_channels=3,\n            out_channels=64,\n            kernel_size=5,\n            pad_mode='pad',\n            padding=2,\n        )\n        self.features.append(self.conv11)\n        self.layerdict['conv11'] = self.conv11\n\n        self.relu11 = nn.ReLU()\n        self.features.append(self.relu11)\n        self.layerdict['relu11'] = self.relu11\n\n        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.features.append(self.pool1)\n        self.layerdict['pool1'] = self.pool1\n\n        self.conv22 = nn.Conv2d(\n            in_channels=64,\n            out_channels=128,\n            kernel_size=5,\n            pad_mode='pad',\n            padding=2,\n        )\n        self.features.append(self.conv22)\n        self.layerdict['conv22'] = self.conv22\n\n    def construct(self, x):\n        for layer in self.features:\n            x = layer(x)\n        return x\n\n    def getlayeroutput(self, x, targetlayer):\n        targetlayer = self.layerdict.get(targetlayer, None)\n        for layer in self.features:\n            x = layer(x)\n            if layer == targetlayer:\n                return x\n        msg = \"Target Layer Error !\"\n        raise ValueError(msg)\n\n\nclass CIFAR10CNNAlternativeReLU32(nn.Cell):\n    \"\"\"\n    CIFAR10CNN Alternative ReLU32 network structure\n    \"\"\"\n    def __init__(self):\n        super(CIFAR10CNNAlternativeReLU32, self).__init__()\n        self.features = []\n        self.layerdict = collections.OrderedDict()\n\n        self.conv11 = nn.Conv2d(\n            in_channels=3,\n            out_channels=64,\n            kernel_size=3,\n            pad_mode='pad',\n            padding=1,\n        )\n        self.features.append(self.conv11)\n        self.layerdict['conv11'] = self.conv11\n\n        self.relu11 = nn.ReLU()\n        self.features.append(self.relu11)\n        self.layerdict['relu11'] = self.relu11\n\n        self.conv12 = nn.Conv2d(\n            in_channels=64,\n            out_channels=64,\n            kernel_size=3,\n            pad_mode='pad',\n            padding=1,\n        )\n        self.features.append(self.conv12)\n        self.layerdict['conv12'] = self.conv12\n\n        self.relu12 = nn.ReLU()\n        self.features.append(self.relu12)\n        self.layerdict['relu12'] = self.relu12\n\n        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.features.append(self.pool1)\n        self.layerdict['pool1'] = self.pool1\n\n        self.conv21 = nn.Conv2d(\n            in_channels=64,\n            out_channels=128,\n            kernel_size=3,\n            pad_mode='pad',\n            padding=1,\n        )\n        self.features.append(self.conv21)\n        self.layerdict['conv21'] = self.conv21\n\n        self.relu21 = nn.ReLU()\n        self.features.append(self.relu21)\n        self.layerdict['relu21'] = self.relu21\n\n        self.conv22 = nn.Conv2d(\n            in_channels=128,\n            out_channels=128,\n            kernel_size=3,\n            pad_mode='pad',\n            padding=1,\n        )\n        self.features.append(self.conv22)\n        self.layerdict['conv22'] = self.conv22\n\n        self.relu22 = nn.ReLU()\n        self.features.append(self.relu22)\n        self.layerdict['relu22'] = self.relu22\n\n        self.conv31 = nn.Conv2d(\n            in_channels=128,\n            out_channels=128,\n            kernel_size=3,\n            pad_mode='pad',\n            padding=1,\n        )\n        self.features.append(self.conv31)\n        self.layerdict['conv31'] = self.conv31\n\n        self.relu31 = nn.ReLU()\n        self.features.append(self.relu31)\n        self.layerdict['relu31'] = self.relu31\n\n        self.conv32 = nn.Conv2d(\n            in_channels=128,\n            out_channels=128,\n            kernel_size=3,\n            pad_mode='pad',\n            padding=1,\n        )\n        self.features.append(self.conv32)\n        self.layerdict['conv32'] = self.conv32\n\n        self.relu32 = nn.ReLU()\n        self.features.append(self.relu32)\n        self.layerdict['relu32'] = self.relu32\n\n    def construct(self, x):\n        for layer in self.features:\n            x = layer(x)\n        return x\n\n    def getlayeroutput(self, x, targetlayer):\n        targetlayer = self.layerdict.get(targetlayer, None)\n        for layer in self.features:\n            x = layer(x)\n            if layer == targetlayer:\n                return x\n        msg = \"Target Layer Error !\"\n        raise ValueError(msg)\n"
  },
  {
    "path": "examples/privacy/membership_inference/__init__.py",
    "content": ""
  },
  {
    "path": "examples/privacy/membership_inference/eval.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"Eval\"\"\"\nimport os\nimport argparse\nimport datetime\nimport mindspore.nn as nn\n\nfrom mindspore import context\nfrom mindspore.nn.optim.momentum import Momentum\nfrom mindspore.train.model import Model\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nfrom mindspore.ops import operations as P\nfrom mindspore.ops import functional as F\nfrom mindspore.common import dtype as mstype\nfrom mindarmour.utils import LogUtil\n\nfrom examples.common.networks.vgg.vgg import vgg16\nfrom examples.common.dataset.data_processing import vgg_create_dataset100\nfrom examples.common.networks.vgg.config import cifar_cfg as cfg\n\n\nclass ParameterReduce(nn.Cell):\n    \"\"\"ParameterReduce\"\"\"\n    def __init__(self):\n        super(ParameterReduce, self).__init__()\n        self.cast = P.Cast()\n        self.reduce = P.AllReduce()\n\n    def construct(self, x):\n        one = self.cast(F.scalar_to_array(1.0), mstype.float32)\n        out = x*one\n        ret = self.reduce(out)\n        return ret\n\n\ndef parse_args(cloud_args=None):\n    \"\"\"parse_args\"\"\"\n    parser = argparse.ArgumentParser('mindspore classification test')\n    parser.add_argument('--device_target', type=str, default='Ascend', choices=['Ascend', 'GPU'],\n                        help='device where the code will be implemented. (Default: Ascend)')\n    # dataset related\n    parser.add_argument('--data_path', type=str, default='', help='eval data dir')\n    parser.add_argument('--per_batch_size', default=32, type=int, help='batch size for per npu')\n    # network related\n    parser.add_argument('--graph_ckpt', type=int, default=1, help='graph ckpt or feed ckpt')\n    parser.add_argument('--pre_trained', default='', type=str, help='fully path of pretrained model to load. '\n                        'If it is a direction, it will test all ckpt')\n\n    # logging related\n    parser.add_argument('--log_path', type=str, default='outputs/', help='path to save log')\n    parser.add_argument('--rank', type=int, default=0, help='local rank of distributed')\n    parser.add_argument('--group_size', type=int, default=1, help='world size of distributed')\n\n    args_opt = parser.parse_args()\n    args_opt = merge_args(args_opt, cloud_args)\n\n    args_opt.image_size = cfg.image_size\n    args_opt.num_classes = cfg.num_classes\n    args_opt.per_batch_size = cfg.batch_size\n    args_opt.momentum = cfg.momentum\n    args_opt.weight_decay = cfg.weight_decay\n    args_opt.buffer_size = cfg.buffer_size\n    args_opt.pad_mode = cfg.pad_mode\n    args_opt.padding = cfg.padding\n    args_opt.has_bias = cfg.has_bias\n    args_opt.batch_norm = cfg.batch_norm\n    args_opt.initialize_mode = cfg.initialize_mode\n    args_opt.has_dropout = cfg.has_dropout\n\n    args_opt.image_size = list(map(int, args_opt.image_size.split(',')))\n\n    return args_opt\n\n\ndef merge_args(args, cloud_args):\n    \"\"\"merge_args\"\"\"\n    args_dict = vars(args)\n    if isinstance(cloud_args, dict):\n        for key in cloud_args.keys():\n            val = cloud_args[key]\n            if key in args_dict and val:\n                arg_type = type(args_dict[key])\n                if arg_type is not type(None):\n                    val = arg_type(val)\n                args_dict[key] = val\n    return args\n\n\ndef test(cloud_args=None):\n    \"\"\"test\"\"\"\n    args = parse_args(cloud_args)\n    context.set_context(mode=context.GRAPH_MODE, enable_auto_mixed_precision=True,\n                        device_target=args.device_target, save_graphs=False)\n    if os.getenv('DEVICE_ID', \"not_set\").isdigit():\n        context.set_context(device_id=int(os.getenv('DEVICE_ID')))\n\n    args.outputs_dir = os.path.join(args.log_path,\n                                    datetime.datetime.now().strftime('%Y-%m-%d_time_%H_%M_%S'))\n\n    args.logger = LogUtil.get_instance()\n    args.logger.set_level(20)\n\n    net = vgg16(num_classes=args.num_classes, args=args)\n    opt = Momentum(filter(lambda x: x.requires_grad, net.get_parameters()), 0.01, args.momentum,\n                   weight_decay=args.weight_decay)\n    loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')\n    model = Model(net, loss_fn=loss, optimizer=opt, metrics={'acc'})\n\n    param_dict = load_checkpoint(args.pre_trained)\n    load_param_into_net(net, param_dict)\n    net.set_train(False)\n\n    dataset_test = vgg_create_dataset100(args.data_path, args.image_size, args.per_batch_size, training=False)\n    res = model.eval(dataset_test)\n    print(\"result: \", res)\n\n\nif __name__ == \"__main__\":\n    test()\n"
  },
  {
    "path": "examples/privacy/membership_inference/example_vgg_cifar.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nExamples of membership inference\n\"\"\"\nimport argparse\nimport sys\nimport numpy as np\n\nfrom mindspore.train import Model\nfrom mindspore.train.serialization import load_param_into_net, load_checkpoint\nimport mindspore.nn as nn\nfrom mindarmour.privacy.evaluation import MembershipInference\nfrom mindarmour.utils import LogUtil\n\nfrom examples.common.networks.vgg.vgg import vgg16\nfrom examples.common.networks.vgg.config import cifar_cfg as cfg\nfrom examples.common.networks.vgg.utils.util import get_param_groups\nfrom examples.common.dataset.data_processing import vgg_create_dataset100\n\nlogging = LogUtil.get_instance()\nlogging.set_level(20)\n\nsys.path.append(\"../../../\")\n\nTAG = \"membership inference example\"\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(\"main case arg parser.\")\n    parser.add_argument(\"--device_target\", type=str, default=\"Ascend\",\n                        choices=[\"Ascend\"])\n    parser.add_argument(\"--data_path\", type=str, required=True,\n                        help=\"Data home path for Cifar100.\")\n    parser.add_argument(\"--pre_trained\", type=str, required=True,\n                        help=\"Checkpoint path.\")\n    args = parser.parse_args()\n    args.num_classes = cfg.num_classes\n    args.batch_norm = cfg.batch_norm\n    args.has_dropout = cfg.has_dropout\n    args.has_bias = cfg.has_bias\n    args.initialize_mode = cfg.initialize_mode\n    args.padding = cfg.padding\n    args.pad_mode = cfg.pad_mode\n    args.weight_decay = cfg.weight_decay\n    args.loss_scale = cfg.loss_scale\n\n    # load the pretrained model\n    net = vgg16(args.num_classes, args)\n    loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True)\n    opt = nn.Momentum(params=get_param_groups(net), learning_rate=0.1, momentum=0.9,\n                      weight_decay=args.weight_decay, loss_scale=args.loss_scale)\n    load_param_into_net(net, load_checkpoint(args.pre_trained))\n    model = Model(network=net, loss_fn=loss, optimizer=opt)\n    logging.info(TAG, \"The model is loaded.\")\n    attacker = MembershipInference(model)\n    config = [\n        {\n            \"method\": \"knn\",\n            \"params\": {\n                \"n_neighbors\": [3, 5, 7]\n            }\n        },\n        {\n            \"method\": \"lr\",\n            \"params\": {\n                \"C\": np.logspace(-4, 2, 10)\n            }\n        },\n        {\n            \"method\": \"mlp\",\n            \"params\": {\n                \"hidden_layer_sizes\": [(64,), (32, 32)],\n                \"solver\": [\"adam\"],\n                \"alpha\": [0.0001, 0.001, 0.01]\n            }\n        },\n        {\n            \"method\": \"rf\",\n            \"params\": {\n                \"n_estimators\": [100],\n                \"max_features\": [\"auto\", \"sqrt\"],\n                \"max_depth\": [5, 10, 20, None],\n                \"min_samples_split\": [2, 5, 10],\n                \"min_samples_leaf\": [1, 2, 4]\n            }\n        }\n    ]\n\n    # load and split dataset\n    train_dataset = vgg_create_dataset100(data_home=args.data_path, image_size=(224, 224),\n                                          batch_size=64, num_samples=10000, shuffle=False)\n    test_dataset = vgg_create_dataset100(data_home=args.data_path, image_size=(224, 224),\n                                         batch_size=64, num_samples=10000, shuffle=False, training=False)\n    train_train, eval_train = train_dataset.split([0.8, 0.2])\n    train_test, eval_test = test_dataset.split([0.8, 0.2])\n    logging.info(TAG, \"Data loading is complete.\")\n\n    logging.info(TAG, \"Start training the inference model.\")\n    attacker.train(train_train, train_test, config)\n    logging.info(TAG, \"The inference model is training complete.\")\n\n    logging.info(TAG, \"Start the evaluation phase\")\n    metrics = [\"precision\", \"accuracy\", \"recall\"]\n    result = attacker.eval(eval_train, eval_test, metrics)\n\n    # Show the metrics for each attack method.\n    count = len(config)\n    for i in range(count):\n        print(\"Method: {}, {}\".format(config[i][\"method\"], result[i]))\n"
  },
  {
    "path": "examples/privacy/membership_inference/train.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\n#################train vgg16 example on cifar10########################\npython train.py --data_path=$DATA_HOME --device_id=$DEVICE_ID\n\"\"\"\nimport argparse\nimport datetime\nimport os\nimport random\n\nimport numpy as np\n\nimport mindspore.nn as nn\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.nn.optim.momentum import Momentum\nfrom mindspore.train.callback import ModelCheckpoint, CheckpointConfig, LossMonitor\nfrom mindspore.train.model import Model\nfrom mindspore.train.serialization import load_param_into_net, load_checkpoint\nfrom mindarmour.utils import LogUtil\n\nfrom examples.common.dataset.data_processing import vgg_create_dataset100\nfrom examples.common.networks.vgg.warmup_step_lr import warmup_step_lr\nfrom examples.common.networks.vgg.warmup_cosine_annealing_lr import warmup_cosine_annealing_lr\nfrom examples.common.networks.vgg.warmup_step_lr import lr_steps\nfrom examples.common.networks.vgg.utils.util import get_param_groups\nfrom examples.common.networks.vgg.vgg import vgg16\nfrom examples.common.networks.vgg.config import cifar_cfg as cfg\n\nTAG = \"train\"\n\nrandom.seed(1)\nnp.random.seed(1)\n\n\ndef parse_args(cloud_args=None):\n    \"\"\"parameters\"\"\"\n    parser = argparse.ArgumentParser('mindspore classification training')\n    parser.add_argument('--device_target', type=str, default='Ascend', choices=['Ascend', 'GPU'],\n                        help='device where the code will be implemented. (Default: Ascend)')\n    parser.add_argument('--device_id', type=int, default=1, help='device id of GPU or Ascend. (Default: None)')\n\n    # dataset related\n    parser.add_argument('--data_path', type=str, default='', help='train data dir')\n\n    # network related\n    parser.add_argument('--pre_trained', default='', type=str, help='model_path, local pretrained model to load')\n    parser.add_argument('--lr_gamma', type=float, default=0.1,\n                        help='decrease lr by a factor of exponential lr_scheduler')\n    parser.add_argument('--eta_min', type=float, default=0., help='eta_min in cosine_annealing scheduler')\n    parser.add_argument('--T_max', type=int, default=150, help='T-max in cosine_annealing scheduler')\n\n    # logging and checkpoint related\n    parser.add_argument('--log_interval', type=int, default=100, help='logging interval')\n    parser.add_argument('--ckpt_path', type=str, default='outputs/', help='checkpoint save location')\n    parser.add_argument('--ckpt_interval', type=int, default=2, help='ckpt_interval')\n    parser.add_argument('--is_save_on_master', type=int, default=1, help='save ckpt on master or all rank')\n\n    args_opt = parser.parse_args()\n    args_opt = merge_args(args_opt, cloud_args)\n\n    args_opt.rank = 0\n    args_opt.group_size = 1\n    args_opt.label_smooth = cfg.label_smooth\n    args_opt.label_smooth_factor = cfg.label_smooth_factor\n    args_opt.lr_scheduler = cfg.lr_scheduler\n    args_opt.loss_scale = cfg.loss_scale\n    args_opt.max_epoch = cfg.max_epoch\n    args_opt.warmup_epochs = cfg.warmup_epochs\n    args_opt.lr = cfg.lr\n    args_opt.lr_init = cfg.lr_init\n    args_opt.lr_max = cfg.lr_max\n    args_opt.momentum = cfg.momentum\n    args_opt.weight_decay = cfg.weight_decay\n    args_opt.per_batch_size = cfg.batch_size\n    args_opt.num_classes = cfg.num_classes\n    args_opt.buffer_size = cfg.buffer_size\n    args_opt.ckpt_save_max = cfg.keep_checkpoint_max\n    args_opt.pad_mode = cfg.pad_mode\n    args_opt.padding = cfg.padding\n    args_opt.has_bias = cfg.has_bias\n    args_opt.batch_norm = cfg.batch_norm\n    args_opt.initialize_mode = cfg.initialize_mode\n    args_opt.has_dropout = cfg.has_dropout\n\n    args_opt.lr_epochs = list(map(int, cfg.lr_epochs.split(',')))\n    args_opt.image_size = list(map(int, cfg.image_size.split(',')))\n\n    return args_opt\n\n\ndef merge_args(args_opt, cloud_args):\n    \"\"\"dictionary\"\"\"\n    args_dict = vars(args_opt)\n    if isinstance(cloud_args, dict):\n        for key_arg in cloud_args.keys():\n            val = cloud_args[key_arg]\n            if key_arg in args_dict and val:\n                arg_type = type(args_dict[key_arg])\n                if arg_type is not None:\n                    val = arg_type(val)\n                args_dict[key_arg] = val\n    return args_opt\n\n\nif __name__ == '__main__':\n    args = parse_args()\n\n    device_num = int(os.environ.get(\"DEVICE_NUM\", 1))\n\n    context.set_context(device_id=args.device_id)\n    context.set_context(mode=context.GRAPH_MODE, device_target=args.device_target)\n\n    # select for master rank save ckpt or all rank save, compatiable for model parallel\n    args.rank_save_ckpt_flag = 0\n    if args.is_save_on_master:\n        if args.rank == 0:\n            args.rank_save_ckpt_flag = 1\n    else:\n        args.rank_save_ckpt_flag = 1\n\n    # logger\n    args.outputs_dir = os.path.join(args.ckpt_path,\n                                    datetime.datetime.now().strftime('%Y-%m-%d_time_%H_%M_%S'))\n    args.logger = LogUtil.get_instance()\n    args.logger.set_level(20)\n\n    # load train data set\n    dataset = vgg_create_dataset100(args.data_path, args.image_size, args.per_batch_size, args.rank, args.group_size)\n    batch_num = dataset.get_dataset_size()\n    args.steps_per_epoch = dataset.get_dataset_size()\n\n    # network\n    args.logger.info(TAG, 'start create network')\n\n    # get network and init\n    network = vgg16(args.num_classes, args)\n\n    # pre_trained\n    if args.pre_trained:\n        load_param_into_net(network, load_checkpoint(args.pre_trained))\n\n    # lr scheduler\n    if args.lr_scheduler == 'exponential':\n        lr = warmup_step_lr(args.lr,\n                            args.lr_epochs,\n                            args.steps_per_epoch,\n                            args.warmup_epochs,\n                            args.max_epoch,\n                            gamma=args.lr_gamma,\n                            )\n    elif args.lr_scheduler == 'cosine_annealing':\n        lr = warmup_cosine_annealing_lr(args.lr,\n                                        args.steps_per_epoch,\n                                        args.warmup_epochs,\n                                        args.max_epoch,\n                                        args.T_max,\n                                        args.eta_min)\n    elif args.lr_scheduler == 'step':\n        lr = lr_steps(0, lr_init=args.lr_init, lr_max=args.lr_max, warmup_epochs=args.warmup_epochs,\n                      total_epochs=args.max_epoch, steps_per_epoch=batch_num)\n    else:\n        raise NotImplementedError(args.lr_scheduler)\n\n    # optimizer\n    opt = Momentum(params=get_param_groups(network),\n                   learning_rate=Tensor(lr),\n                   momentum=args.momentum,\n                   weight_decay=args.weight_decay,\n                   loss_scale=args.loss_scale)\n\n    loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')\n    model = Model(network, loss_fn=loss, optimizer=opt, metrics={'acc'},\n                  amp_level=\"O2\", keep_batchnorm_fp32=False, loss_scale_manager=None)\n\n    # checkpoint save\n    callbacks = [LossMonitor()]\n    if args.rank_save_ckpt_flag:\n        ckpt_config = CheckpointConfig(save_checkpoint_steps=args.ckpt_interval*args.steps_per_epoch,\n                                       keep_checkpoint_max=args.ckpt_save_max)\n        ckpt_cb = ModelCheckpoint(config=ckpt_config,\n                                  directory=args.outputs_dir,\n                                  prefix='{}'.format(args.rank))\n        callbacks.append(ckpt_cb)\n\n    model.train(args.max_epoch, dataset, callbacks=callbacks)\n"
  },
  {
    "path": "examples/privacy/sup_privacy/__init__.py",
    "content": ""
  },
  {
    "path": "examples/privacy/sup_privacy/sup_privacy.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nTraining example of suppress-based privacy.\n\"\"\"\nimport os\n\nimport mindspore.nn as nn\nfrom mindspore import context\nfrom mindspore.train.callback import ModelCheckpoint\nfrom mindspore.train.callback import CheckpointConfig\nfrom mindspore.train.callback import LossMonitor\nfrom mindspore.nn import Accuracy\nimport mindspore.dataset as ds\nimport mindspore.dataset.vision as CV\nimport mindspore.dataset.transforms as C\nfrom mindspore.dataset.vision import Inter\nfrom mindspore import dtype as mstype\n\nfrom mindarmour.privacy.sup_privacy import SuppressModel\nfrom mindarmour.privacy.sup_privacy import SuppressMasker\nfrom mindarmour.privacy.sup_privacy import SuppressPrivacyFactory\nfrom mindarmour.privacy.sup_privacy import MaskLayerDes\nfrom mindarmour.utils import LogUtil\n\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\nfrom sup_privacy_config import mnist_cfg as cfg\n\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'Lenet5_Suppress_train'\n\n\ndef generate_mnist_dataset(data_path, batch_size=32, repeat_size=1, samples=None, num_parallel_workers=1, sparse=True):\n    \"\"\"\n    create dataset for training or testing\n    \"\"\"\n    # define dataset\n    ds1 = ds.MnistDataset(data_path, num_samples=samples)\n\n    # define operation parameters\n    resize_height, resize_width = 32, 32\n    rescale = 1.0 / 255.0\n    shift = 0.0\n\n    # define map operations\n    resize_op = CV.Resize((resize_height, resize_width),\n                          interpolation=Inter.LINEAR)\n    rescale_op = CV.Rescale(rescale, shift)\n    hwc2chw_op = CV.HWC2CHW()\n    type_cast_op = C.TypeCast(mstype.int32)\n\n    # apply map operations on images\n    if not sparse:\n        one_hot_enco = C.OneHot(10)\n        ds1 = ds1.map(input_columns=\"label\", operations=one_hot_enco, num_parallel_workers=num_parallel_workers)\n        type_cast_op = C.TypeCast(mstype.float32)\n    ds1 = ds1.map(input_columns=\"label\", operations=type_cast_op,\n                  num_parallel_workers=num_parallel_workers)\n    ds1 = ds1.map(input_columns=\"image\", operations=resize_op,\n                  num_parallel_workers=num_parallel_workers)\n    ds1 = ds1.map(input_columns=\"image\", operations=rescale_op,\n                  num_parallel_workers=num_parallel_workers)\n    ds1 = ds1.map(input_columns=\"image\", operations=hwc2chw_op,\n                  num_parallel_workers=num_parallel_workers)\n\n    # apply DatasetOps\n    buffer_size = 10000\n    ds1 = ds1.shuffle(buffer_size=buffer_size)\n    ds1 = ds1.batch(batch_size, drop_remainder=True)\n    ds1 = ds1.repeat(repeat_size)\n\n    return ds1\n\ndef mnist_suppress_train(epoch_size=10, start_epoch=3, lr=0.05, samples=10000, mask_times=1000,\n                         sparse_thd=0.90, sparse_start=0.0, masklayers=None):\n    \"\"\"\n    local train by suppress-based privacy\n    \"\"\"\n\n    networks_l5 = LeNet5()\n    suppress_ctrl_instance = SuppressPrivacyFactory().create(networks_l5,\n                                                             masklayers,\n                                                             policy=\"local_train\",\n                                                             end_epoch=epoch_size,\n                                                             batch_num=(int)(samples/cfg.batch_size),\n                                                             start_epoch=start_epoch,\n                                                             mask_times=mask_times,\n                                                             lr=lr,\n                                                             sparse_end=sparse_thd,\n                                                             sparse_start=sparse_start)\n    net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction=\"mean\")\n    net_opt = nn.SGD(networks_l5.trainable_params(), lr)\n    config_ck = CheckpointConfig(save_checkpoint_steps=(int)(samples/cfg.batch_size),\n                                 keep_checkpoint_max=10)\n\n    # Create the SuppressModel model for training.\n    model_instance = SuppressModel(network=networks_l5,\n                                   loss_fn=net_loss,\n                                   optimizer=net_opt,\n                                   metrics={\"Accuracy\": Accuracy()})\n    model_instance.link_suppress_ctrl(suppress_ctrl_instance)\n\n    # Create a Masker for Suppress training. The function of the Masker is to\n    # enforce suppress operation while training.\n    suppress_masker = SuppressMasker(model=model_instance, suppress_ctrl=suppress_ctrl_instance)\n\n    mnist_path = \"./MNIST_unzip/\"  #\"../../MNIST_unzip/\"\n    ds_train = generate_mnist_dataset(os.path.join(mnist_path, \"train\"),\n                                      batch_size=cfg.batch_size, repeat_size=1, samples=samples)\n\n    ckpoint_cb = ModelCheckpoint(prefix=\"checkpoint_lenet\",\n                                 directory=\"./trained_ckpt_file/\",\n                                 config=config_ck)\n\n    print(\"============== Starting SUPP Training ==============\")\n    model_instance.train(epoch_size, ds_train, callbacks=[ckpoint_cb, LossMonitor(), suppress_masker],\n                         dataset_sink_mode=False)\n\n    print(\"============== Starting SUPP Testing ==============\")\n    ds_eval = generate_mnist_dataset(os.path.join(mnist_path, 'test'),\n                                     batch_size=cfg.batch_size)\n    acc = model_instance.eval(ds_eval, dataset_sink_mode=False)\n    print(\"============== SUPP Accuracy: %s  ==============\", acc)\n\n    suppress_ctrl_instance.print_paras()\nif __name__ == \"__main__\":\n    # This configure can run in pynative mode\n    context.set_context(mode=context.PYNATIVE_MODE, device_target=cfg.device_target)\n\n    masklayers_lenet5 = []  # determine which layer should be masked\n\n    masklayers_lenet5.append(MaskLayerDes(\"conv1.weight\", 0, False, True, 10))\n    masklayers_lenet5.append(MaskLayerDes(\"conv2.weight\", 1, False, True, 150))\n    masklayers_lenet5.append(MaskLayerDes(\"fc1.weight\", 2, True, False, -1))\n    masklayers_lenet5.append(MaskLayerDes(\"fc2.weight\", 4, True, False, -1))\n    masklayers_lenet5.append(MaskLayerDes(\"fc3.weight\", 6, True, False, 50))\n\n    # do suppreess privacy train, with stronger privacy protection and better performance than Differential Privacy\n    mnist_suppress_train(10, 3, 0.10, 60000, 1000, 0.95, 0.0, masklayers=masklayers_lenet5)  # used\n"
  },
  {
    "path": "examples/privacy/sup_privacy/sup_privacy_config.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nnetwork config setting, will be used in sup_privacy.py\n\"\"\"\n\nfrom easydict import EasyDict as edict\n\nmnist_cfg = edict({\n    'num_classes': 10,  # the number of classes of model's output\n    'batch_size': 32,  # batch size for training\n    'image_height': 32,  # the height of training samples\n    'image_width': 32,  # the width of training samples\n    'keep_checkpoint_max': 10,  # the maximum number of checkpoint files would be saved\n    'device_target': 'Ascend',  # device used\n})\n"
  },
  {
    "path": "examples/reliability/concept_drift_check_images_lenet.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport numpy as np\nfrom mindspore import Tensor\nfrom mindspore.train.model import Model\nfrom mindspore import Model, nn, context\nfrom examples.common.networks.lenet5.lenet5_net_for_fuzzing import LeNet5\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nfrom mindarmour.reliability.concept_drift.concept_drift_check_images import OodDetectorFeatureCluster\n\n\n\"\"\"\nExamples for Lenet.\n\"\"\"\n\n\nif __name__ == '__main__':\n    # load model\n    ckpt_path = '../../tests/ut/python/dataset/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n    model = Model(net)\n    # load data\n    ds_train = np.load('../../tests/ut/python/dataset/concept_train_lenet.npy')\n    ds_eval = np.load('../../tests/ut/python/dataset/concept_test_lenet1.npy')\n    ds_test = np.load('../../tests/ut/python/dataset/concept_test_lenet2.npy')\n    # ood detector initialization\n    detector = OodDetectorFeatureCluster(model, ds_train, n_cluster=10, layer='output[:Tensor]')\n    # get optimal threshold with ds_eval\n    num = int(len(ds_eval) / 2)\n    label = np.concatenate((np.zeros(num), np.ones(num)), axis=0)  # ID data = 0, OOD data = 1\n    optimal_threshold = detector.get_optimal_threshold(label, ds_eval)\n    # get result of ds_test2. We can also set threshold by ourselves.\n    result = detector.ood_predict(optimal_threshold, ds_test)\n"
  },
  {
    "path": "examples/reliability/concept_drift_check_images_resnet.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport numpy as np\nfrom mindspore import Tensor\nfrom mindspore.train.model import Model\nfrom mindspore import Model, nn, context\nfrom examples.common.networks.resnet.resnet import resnet50\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nfrom mindarmour.reliability.concept_drift.concept_drift_check_images import OodDetectorFeatureCluster\n\n\n\"\"\"\nExamples for Resnet.\n\"\"\"\n\n\nif __name__ == '__main__':\n    # load model\n    ckpt_path = '../../tests/ut/python/dataset/trained_ckpt_file/resnet_1-20_1875.ckpt'\n    net = resnet50()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n    model = Model(net)\n    # load data\n    ds_train = np.load('train.npy')\n    ds_eval = np.load('test1.npy')\n    ds_test = np.load('test2.npy')\n    # ood detector initialization\n    detector = OodDetectorFeatureCluster(model, ds_train, n_cluster=10, layer='output[:Tensor]')\n    # get optimal threshold with ds_eval\n    num = int(len(ds_eval) / 2)\n    label = np.concatenate((np.zeros(num), np.ones(num)), axis=0)  # ID data = 0, OOD data = 1\n    optimal_threshold = detector.get_optimal_threshold(label, ds_eval)\n    # get result of ds_test2. We can also set threshold by ourselves.\n    result = detector.ood_predict(optimal_threshold, ds_test)\n"
  },
  {
    "path": "examples/reliability/concept_drift_time_series.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\n\"\"\"\nConcept drift example.\nDownload dataset from: https://www.kaggle.com/camnugent/sandp500.\nFile structure:\n    --archive\n        --individual_stocks_5yr\n            --__MACOSX\n            --individual_stocks_5yr\n        --all_stocks_5yr.csv\n        --getSandP.py\n        --merge.sh\nPlease use the data in archive/individual_stocks_5yr/individual_stocks_5yr/XX.csv.\nIn each csv file, there are 'date','open','high','low','close','volume','Name' columns.\nPlease choose one column or multiple columns.\n'date' and 'Name' are non-data column, please do not use.\n\"\"\"\n\nimport numpy as np\nfrom mindarmour import ConceptDriftCheckTimeSeries\n\n# input data\nDATA_FILE = r'archive/individual_stocks_5yr/individual_stocks_5yr/AEE_data.csv'\ndata = np.loadtxt(DATA_FILE, str, delimiter=\",\")\ndata = data[1:, 2].astype('float64')  # choose one column or multiple columns data[1:, 2:5]\n# Initialization\nconcept = ConceptDriftCheckTimeSeries(window_size=100, rolling_window=10,\n                                      step=10, threshold_index=1.5, need_label=False)\n# drift check\ndrift_score, threshold, concept_drift_location = concept.concept_check(data)\n"
  },
  {
    "path": "examples/reliability/model_fault_injection.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\n\"\"\"\nFault injection example.\nDownload checkpoint from: https://www.mindspore.cn/resources/hub or just trained your own checkpoint.\nDownload dataset from: http://www.cs.toronto.edu/~kriz/cifar-10-binary.tar.gz.\nFile structure:\n    --cifar10-batches-bin\n        --train\n            --data_batch_1.bin\n            --data_batch_2.bin\n            --data_batch_3.bin\n            --data_batch_4.bin\n            --data_batch_5.bin\n        --test\n            --test_batch.bin\n\nPlease extract and restructure the file as shown above.\n\"\"\"\nimport argparse\n\nimport numpy as np\nfrom mindspore import Model, context\nfrom mindspore.train.serialization import load_checkpoint\n\nfrom mindarmour.reliability.model_fault_injection.fault_injection import FaultInjector\nfrom examples.common.networks.lenet5.lenet5_net import LeNet5\nfrom examples.common.networks.vgg.vgg import vgg16\nfrom examples.common.networks.resnet.resnet import resnet50\nfrom examples.common.dataset.data_processing import create_dataset_cifar, generate_mnist_dataset\n\n\nparser = argparse.ArgumentParser(description='layer_states')\nparser.add_argument('--device_target', type=str, default=\"CPU\", choices=['Ascend', 'GPU', 'CPU'])\nparser.add_argument('--model', type=str, default='lenet', choices=['lenet', 'resnet50', 'vgg16'])\nparser.add_argument('--device_id', type=int, default=0)\nargs = parser.parse_args()\ncontext.set_context(mode=context.GRAPH_MODE, device_target=args.device_target, device_id=args.device_id)\n\n\ntest_flag = args.model\nif test_flag == 'lenet':\n    # load data\n    DATA_FILE = '../common/dataset/MNIST_Data/test'\n    ckpt_path = '../common/networks/lenet5/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    ds_eval = generate_mnist_dataset(DATA_FILE, batch_size=64)\n    net = LeNet5()\nelif test_flag == 'vgg16':\n    from examples.common.networks.vgg.config import cifar_cfg as cfg\n    DATA_FILE = '../common/dataset/cifar10-batches-bin'\n    ckpt_path = '../common/networks/vgg16_ascend_v111_cifar10_offical_cv_bs64_acc93.ckpt'\n    ds_eval = create_dataset_cifar(DATA_FILE, 224, 224, training=False)\n    net = vgg16(10, cfg, 'test')\nelif test_flag == 'resnet50':\n    DATA_FILE = '../common/dataset/cifar10-batches-bin'\n    ckpt_path = '../common/networks/resnet50_ascend_v111_cifar10_offical_cv_bs32_acc92.ckpt'\n    ds_eval = create_dataset_cifar(DATA_FILE, 224, 224, training=False)\n    net = resnet50(10)\nelse:\n    exit()\n\ntest_images = []\ntest_labels = []\nfor data in ds_eval.create_tuple_iterator(output_numpy=True):\n    images = data[0].astype(np.float32)\n    labels = data[1]\n    test_images.append(images)\n    test_labels.append(labels)\nds_data = np.concatenate(test_images, axis=0)\nds_label = np.concatenate(test_labels, axis=0)\n\nparam_dict = load_checkpoint(ckpt_path, net=net)\nmodel = Model(net)\n\n# Initialization\nfi_type = ['bitflips_random', 'bitflips_designated', 'random', 'zeros',\n           'nan', 'inf', 'anti_activation', 'precision_loss']\nfi_mode = ['single_layer', 'all_layer']\nfi_size = [1, 2, 3]\n\n# Fault injection\nfi = FaultInjector(model, fi_type, fi_mode, fi_size)\nresults = fi.kick_off(ds_data, ds_label, iter_times=100)\nresult_summary = fi.metrics()\n\n# print result\nfor result in results:\n    print(result)\nfor result in result_summary:\n    print(result)\n"
  },
  {
    "path": "mindarmour/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nMindArmour, a tool box of MindSpore to enhance model trustworthiness and achieve\nprivacy-preserving machine learning.\n\"\"\"\nimport logging\nimport time\n\nfrom .adv_robustness.attacks.attack import Attack\nfrom .adv_robustness.attacks.black.black_model import BlackModel\nfrom .adv_robustness.defenses.defense import Defense\nfrom .adv_robustness.detectors.detector import Detector\nfrom .fuzz_testing.fuzzing import Fuzzer\nfrom .privacy.diff_privacy import DPModel\nfrom .privacy.evaluation.membership_inference import MembershipInference\nfrom .privacy.sup_privacy.sup_ctrl.conctrl import SuppressCtrl\nfrom .privacy.sup_privacy.train.model import SuppressModel\nfrom .privacy.sup_privacy.mask_monitor.masker import SuppressMasker\nfrom .privacy.evaluation.inversion_attack import ImageInversionAttack\nfrom .privacy.evaluation.model_inversion_attack import ModelInversionAttack\nfrom .privacy.evaluation.shadow_model_attack import ShadowModelAttack\nfrom .reliability.concept_drift.concept_drift_check_time_series import ConceptDriftCheckTimeSeries\nfrom .model_protection import ModelObfuscator\n\n__all__ = ['Attack',\n           'BlackModel',\n           'Detector',\n           'Defense',\n           'Fuzzer',\n           'DPModel',\n           'MembershipInference',\n           'SuppressModel',\n           'SuppressCtrl',\n           'SuppressMasker',\n           'ImageInversionAttack',\n           'ModelInversionAttack',\n           'ShadowModelAttack',\n           'ConceptDriftCheckTimeSeries']\n__all__.extend(model_protection.__all__)\n\ndef _mindspore_version_check():\n    \"\"\"\n    Do the MindSpore version check for MindArmour. If the\n    MindSpore can not be imported, it will raise ImportError. If its\n    version is not compatible with current MindArmour version,\n    it will print a warning.\n\n    Raise:\n        ImportError: If the MindSpore can not be imported.\n    \"\"\"\n    try:\n        from mindarmour.version import __version__\n        ma_version = __version__[:3]\n    except (ImportError, ModuleNotFoundError):\n        raise ImportError(f\"Get MindArmour version failed\")\n\n    try:\n        import mindspore as ms\n    except (ImportError, ModuleNotFoundError):\n        raise ImportError(\"Can not find MindSpore in current environment. Please install MindSpore before \" \\\n                          \"using MindArmour, by following  the instruction at https://www.mindspore.cn/install\")\n\n    ms_ma_version_match = {'1.7': ['1.7'],\n                           '1.8': ['1.7', '1.8', '1.9', '2.0', '2.1'],\n                           '1.9': ['1.7', '1.8', '1.9', '2.0', '2.1'],\n                           '2.0': ['1.7', '1.8', '1.9', '2.0', '2.1'],\n                           '2.1': ['2.1', '2.2', '2.3', '2.4', '2.5', '2.6']}\n\n    ms_version = ms.__version__[:3]\n    required_mindspore_verision = ms_ma_version_match.get(ma_version[:3])\n\n    if ms_version not in required_mindspore_verision:\n        logging.warning(\"Current version of MindSpore is not compatible with MindArmour. \" \\\n                        \"Some functions might not work or even raise error. Please install MindSpore \" \\\n                        \"version in %s. For more details about dependency setting, please check \" \\\n                        \"the instructions at MindSpore official website https://www.mindspore.cn/install \" \\\n                        \"or check the README.md at https://gitee.com/mindspore/mindarmour\", required_mindspore_verision)\n        warning_countdown = 3\n        for i in range(warning_countdown, 0, -1):\n            logging.warning(\"Please pay attention to the above warning, countdown: %d .\", i)\n            time.sleep(1)\n\n\n_mindspore_version_check()\n"
  },
  {
    "path": "mindarmour/adv_robustness/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nAdversarial Robustness.\n\nThis module is a tool box to enhance model security and against adversarial\nexamples.\n\"\"\"\n"
  },
  {
    "path": "mindarmour/adv_robustness/attacks/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis module includes classical black-box and white-box attack algorithms\nin making adversarial examples.\n\"\"\"\nfrom .gradient_method import FastGradientMethod, FastGradientSignMethod, RandomFastGradientMethod, \\\n    RandomFastGradientSignMethod, LeastLikelyClassMethod, RandomLeastLikelyClassMethod\nfrom .iterative_gradient_method import IterativeGradientMethod, BasicIterativeMethod, MomentumIterativeMethod, \\\n    ProjectedGradientDescent, AutoProjectedGradientDescent, DiverseInputIterativeMethod, \\\n    MomentumDiverseInputIterativeMethod, VarianceTuningMomentumIterativeMethod, VarianceTuningNesterovIterativeMethod\nfrom .deep_fool import DeepFool\nfrom .jsma import JSMAAttack\nfrom .carlini_wagner import CarliniWagnerL2Attack\nfrom .lbfgs import LBFGS\nfrom . import black\nfrom .black.hop_skip_jump_attack import HopSkipJumpAttack\nfrom .black.genetic_attack import GeneticAttack\nfrom .black.natural_evolutionary_strategy import NES\nfrom .black.pointwise_attack import PointWiseAttack\nfrom .black.pso_attack import PSOAttack\nfrom .black.salt_and_pepper_attack import SaltAndPepperNoiseAttack\n\n__all__ = ['FastGradientMethod',\n           'RandomFastGradientMethod',\n           'FastGradientSignMethod',\n           'RandomFastGradientSignMethod',\n           'LeastLikelyClassMethod',\n           'RandomLeastLikelyClassMethod',\n           'IterativeGradientMethod',\n           'BasicIterativeMethod',\n           'MomentumIterativeMethod',\n           'VarianceTuningMomentumIterativeMethod',\n           'VarianceTuningNesterovIterativeMethod',\n           'ProjectedGradientDescent',\n           'AutoProjectedGradientDescent',\n           'DiverseInputIterativeMethod',\n           'MomentumDiverseInputIterativeMethod',\n           'DeepFool',\n           'CarliniWagnerL2Attack',\n           'JSMAAttack',\n           'LBFGS',\n           'GeneticAttack',\n           'HopSkipJumpAttack',\n           'NES',\n           'PointWiseAttack',\n           'PSOAttack',\n           'SaltAndPepperNoiseAttack'\n           ]\n"
  },
  {
    "path": "mindarmour/adv_robustness/attacks/attack.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nBase Class of Attack.\n\"\"\"\nfrom abc import abstractmethod\n\nimport numpy as np\n\nfrom mindarmour.utils._check_param import check_inputs_labels, \\\n    check_int_positive, check_equal_shape, check_numpy_param, check_model\nfrom mindarmour.utils.util import calculate_iou\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.adv_robustness.attacks.black.black_model import BlackModel\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Attack'\n\n\nclass Attack:\n    \"\"\"\n    The abstract base class for all attack classes creating adversarial examples.\n    The adversarial examples are generated by adding adversarial noises to the original sample.\n    \"\"\"\n    def __init__(self):\n        pass\n\n    def batch_generate(self, inputs, labels, batch_size=64):\n        \"\"\"\n        Generate adversarial examples in batch, based on input samples and\n        their labels.\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Samples based on which adversarial\n                examples are generated.\n            labels (Union[numpy.ndarray, tuple]): Original/target labels. \\\n                For each input if it has more than one label, it is wrapped in a tuple.\n            batch_size (int): The number of samples in one batch. Default: ``64``.\n\n        Returns:\n            numpy.ndarray, generated adversarial examples.\n        \"\"\"\n        inputs_image, inputs, labels = check_inputs_labels(inputs, labels)\n        arr_x = inputs\n        arr_y = labels\n        len_x = inputs_image.shape[0]\n        batch_size = check_int_positive('batch_size', batch_size)\n        batches = int(len_x / batch_size)\n        rest = len_x - batches*batch_size\n        res = []\n        for i in range(batches):\n            if isinstance(arr_x, tuple):\n                x_batch = tuple([sub_items[i*batch_size: (i + 1)*batch_size] for sub_items in arr_x])\n            else:\n                x_batch = arr_x[i*batch_size: (i + 1)*batch_size]\n            if isinstance(arr_y, tuple):\n                y_batch = tuple([sub_labels[i*batch_size: (i + 1)*batch_size] for sub_labels in arr_y])\n            else:\n                y_batch = arr_y[i*batch_size: (i + 1)*batch_size]\n            adv_x = self.generate(x_batch, y_batch)\n            # Black-attack methods will return 3 values, just get the second.\n            res.append(adv_x[1] if isinstance(adv_x, tuple) else adv_x)\n\n        if rest != 0:\n            if isinstance(arr_x, tuple):\n                x_batch = tuple([sub_items[batches*batch_size:] for sub_items in arr_x])\n            else:\n                x_batch = arr_x[batches*batch_size:]\n            if isinstance(arr_y, tuple):\n                y_batch = tuple([sub_labels[batches*batch_size:] for sub_labels in arr_y])\n            else:\n                y_batch = arr_y[batches*batch_size:]\n            adv_x = self.generate(x_batch, y_batch)\n            # Black-attack methods will return 3 values, just get the second.\n            res.append(adv_x[1] if isinstance(adv_x, tuple) else adv_x)\n\n        adv_x = np.concatenate(res, axis=0)\n        return adv_x\n\n    @abstractmethod\n    def generate(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples based on normal samples and their labels.\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Samples based on which adversarial\n                examples are generated.\n            labels (Union[numpy.ndarray, tuple]): Original/target labels. \\\n                For each input if it has more than one label, it is wrapped in a tuple.\n\n        Raises:\n            NotImplementedError: It is an abstract method.\n        \"\"\"\n        msg = 'The function generate() is an abstract function in class ' \\\n              '`Attack` and should be implemented in child class.'\n        LOGGER.error(TAG, msg)\n        raise NotImplementedError(msg)\n\n    @staticmethod\n    def _reduction(x_ori, q_times, label, best_position, model, targeted_attack):\n        \"\"\"\n        Decrease the differences between the original samples and adversarial samples.\n\n        Args:\n            x_ori (numpy.ndarray): Original samples.\n            q_times (int): Query times.\n            label (int): Target label ot ground-truth label.\n            best_position (numpy.ndarray): Adversarial examples.\n            model (BlackModel): Target model.\n            targeted_attack (bool): If True, it means this is a targeted attack. If False,\n                it means this is an untargeted attack.\n\n        Returns:\n            numpy.ndarray, adversarial examples after reduction.\n\n        Examples:\n            >>> adv_reduction = self._reduction(self, [0.1, 0.2, 0.3], 20, 1,\n            >>> [0.12, 0.15, 0.25])\n        \"\"\"\n        LOGGER.info(TAG, 'Reduction begins...')\n        model = check_model('model', model, BlackModel)\n        x_ori = check_numpy_param('x_ori', x_ori)\n        best_position = check_numpy_param('best_position', best_position)\n        x_ori, best_position = check_equal_shape('x_ori', x_ori,\n                                                 'best_position', best_position)\n        x_ori_fla = x_ori.flatten()\n        best_position_fla = best_position.flatten()\n        pixel_deep = np.max(x_ori) - np.min(x_ori)\n        nums_pixel = len(x_ori_fla)\n        for i in range(nums_pixel):\n            diff = x_ori_fla[i] - best_position_fla[i]\n            if abs(diff) > pixel_deep*0.1:\n                best_position_fla[i] += diff*0.5\n                cur_label = np.argmax(\n                    model.predict(best_position_fla.reshape(x_ori.shape)))\n                q_times += 1\n                if targeted_attack:\n                    if cur_label != label:\n                        best_position_fla[i] -= diff * 0.5\n\n                else:\n                    if cur_label == label:\n                        best_position_fla -= diff*0.5\n        return best_position_fla.reshape(x_ori.shape), q_times\n\n    def _fast_reduction(self, x_ori, best_position, q_times, auxiliary_inputs, gt_boxes, gt_labels, model):\n        \"\"\"\n        Decrease the differences between the original samples and adversarial samples in a fast way.\n\n        Args:\n            x_ori (numpy.ndarray): Original samples.\n            best_position (numpy.ndarray): Adversarial examples.\n            q_times (int): Query times.\n            auxiliary_inputs (tuple): Auxiliary inputs mathced with x_ori.\n            gt_boxes (numpy.ndarray): Ground-truth boxes of x_ori.\n            gt_labels (numpy.ndarray): Ground-truth labels of x_ori.\n            model (BlackModel): Target model.\n\n        Returns:\n            - numpy.ndarray, adversarial examples after reduction.\n\n            - int, total query times after reduction.\n        \"\"\"\n        LOGGER.info(TAG, 'Reduction begins...')\n        model = check_model('model', model, BlackModel)\n        x_ori = check_numpy_param('x_ori', x_ori)\n        _, gt_num = self._detection_scores((x_ori,) + auxiliary_inputs, gt_boxes, gt_labels, model)\n        best_position = check_numpy_param('best_position', best_position)\n        x_ori, best_position = check_equal_shape('x_ori', x_ori, 'best_position', best_position)\n        _, original_num = self._detection_scores((best_position,) + auxiliary_inputs, gt_boxes, gt_labels, model)\n        reduction_iters = 6  # recover 10% difference each time and recover 60% totally.\n        for _ in range(reduction_iters):\n            block_num = 30  # divide the image into 30 segments\n            block_width = best_position.shape[0] // block_num\n            if block_width > 0:\n                for i in range(block_num):\n                    diff = x_ori[i*block_width: (i+1)*block_width, :, :]\\\n                           - best_position[i*block_width:(i+1)*block_width, :, :]\n                    if np.max(np.abs(diff)) >= 0.1*(self._bounds[1] - self._bounds[0]):\n                        res = diff*0.1\n                        best_position[i*block_width: (i+1)*block_width, :, :] += res\n                        _, correct_num = self._detection_scores((best_position,) + auxiliary_inputs, gt_boxes,\n                                                                gt_labels, model)\n                        q_times += 1\n                        if correct_num[0] > max(original_num[0], gt_num[0]*self._reserve_ratio):\n                            best_position[i*block_width:(i+1)*block_width, :, :] -= res\n        return best_position, q_times\n\n    @staticmethod\n    def _detection_scores(inputs, gt_boxes, gt_labels, model):\n        \"\"\"\n        Evaluate the detection result of inputs, specially for object detection models.\n\n        Args:\n            inputs (numpy.ndarray): Input samples.\n            gt_boxes (numpy.ndarray): Ground-truth boxes of inputs.\n            gt_labels (numpy.ndarray): Ground-truth labels of inputs.\n            model (BlackModel): Target model.\n\n        Returns:\n            - numpy.ndarray, detection scores of inputs.\n\n            - numpy.ndarray, the number of objects that are correctly detected.\n        \"\"\"\n        model = check_model('model', model, BlackModel)\n        boxes_and_confi, pred_labels = model.predict(*inputs)\n        det_scores = []\n        correct_labels_num = []\n        # repeat gt_boxes and gt_labels for all particles cloned from the same sample in PSOAttack/GeneticAttack\n        if gt_boxes.shape[0] == 1 and boxes_and_confi.shape[0] > 1:\n            gt_boxes = np.repeat(gt_boxes, boxes_and_confi.shape[0], axis=0)\n            gt_labels = np.repeat(gt_labels, boxes_and_confi.shape[0], axis=0)\n        iou_thres = 0.5\n        for boxes, labels, gt_box, gt_label in zip(boxes_and_confi, pred_labels, gt_boxes, gt_labels):\n            gt_box_num = gt_box.shape[0]\n            score = 0\n            box_num = boxes.shape[0]\n            correct_label_flag = np.zeros(gt_label.shape)\n            for i in range(box_num):\n                pred_box = boxes[i]\n                max_iou_confi = 0\n                for j in range(gt_box_num):\n                    iou = calculate_iou(pred_box[:4], gt_box[j][:4])\n                    if labels[i] == gt_label[j] and iou > iou_thres and correct_label_flag[j] == 0:\n                        max_iou_confi = max(max_iou_confi, pred_box[-1] + iou)\n                        correct_label_flag[j] = 1\n                score += max_iou_confi\n            det_scores.append(score)\n            correct_labels_num.append(np.sum(correct_label_flag))\n        return np.array(det_scores), np.array(correct_labels_num)\n"
  },
  {
    "path": "mindarmour/adv_robustness/attacks/black/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis module is a submodule, which provides some black-box based adversarial method.\n\"\"\"\n"
  },
  {
    "path": "mindarmour/adv_robustness/attacks/black/black_model.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n\"\"\"\r\nBlack model.\r\n\"\"\"\r\nfrom abc import abstractmethod\r\n\r\nimport numpy as np\r\n\r\nfrom mindarmour.utils.logger import LogUtil\r\n\r\nLOGGER = LogUtil.get_instance()\r\nTAG = 'BlackModel'\r\n\r\n\r\nclass BlackModel:\r\n    \"\"\"\r\n    The abstract class which treats the target model as a black box. The model\r\n    should be defined by users.\r\n    \"\"\"\r\n    def __init__(self):\r\n        pass\r\n\r\n    @abstractmethod\r\n    def predict(self, inputs):\r\n        \"\"\"\r\n        Predict using the user specified model. The shape of predict results\r\n        should be :math:`(m, n)`, where n represents the number of classes this model\r\n        classifies.\r\n\r\n        Args:\r\n            inputs (numpy.ndarray): The input samples to be predicted.\r\n\r\n        Raises:\r\n            NotImplementedError: It is an abstract method.\r\n        \"\"\"\r\n        msg = 'The function predict() is an abstract function in class ' \\\r\n              '`BlackModel` and should be implemented in child class by user.'\r\n        LOGGER.error(TAG, msg)\r\n        raise NotImplementedError(msg)\r\n\r\n    def is_adversarial(self, data, label, is_targeted):\r\n        \"\"\"\r\n        Check if input sample is adversarial example or not.\r\n\r\n        Args:\r\n            data (numpy.ndarray): The input sample to be check, typically some\r\n                maliciously perturbed examples.\r\n            label (numpy.ndarray): For targeted attacks, label is intended\r\n                label of perturbed example. For untargeted attacks, label is\r\n                original label of corresponding unperturbed sample.\r\n            is_targeted (bool): For targeted/untargeted attacks, select ``True`` / ``False``.\r\n\r\n        Returns:\r\n            bool.\r\n\r\n            - If ``True``, the input sample is adversarial.\r\n\r\n            - If ``False``, the input sample is not adversarial.\r\n        \"\"\"\r\n        logits = self.predict(np.expand_dims(data, axis=0))[0]\r\n        predicts = np.argmax(logits)\r\n        if is_targeted:\r\n            return predicts == label\r\n        return predicts != label\r\n"
  },
  {
    "path": "mindarmour/adv_robustness/attacks/black/genetic_attack.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nGenetic-Attack.\n\"\"\"\nimport numpy as np\nfrom scipy.special import softmax\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_numpy_param, check_model, \\\n    check_pair_numpy_param, check_param_type, check_value_positive, \\\n    check_int_positive, check_detection_inputs, check_value_non_negative, check_param_multi_types\nfrom mindarmour.adv_robustness.attacks.attack import Attack\nfrom .black_model import BlackModel\n\nLOGGER = LogUtil.get_instance()\nTAG = 'GeneticAttack'\n\n\nclass GeneticAttack(Attack):\n    \"\"\"\n    The Genetic Attack represents the black-box attack based on the genetic algorithm,\n    which belongs to differential evolution algorithms.\n\n    This attack was proposed by Moustafa Alzantot et al. (2018).\n\n    References: `Moustafa Alzantot, Yash Sharma, Supriyo Chakraborty,\n    \"GeneticAttack: Practical Black-box Attacks with\n    Gradient-FreeOptimization\" <https://arxiv.org/abs/1805.11090>`_\n\n    Args:\n        model (BlackModel): Target model.\n        model_type (str): The type of targeted model. ``'classification'`` and ``'detection'`` are supported now.\n            Default: ``'classification'``.\n        targeted (bool): If ``True``, turns on the targeted attack. If ``False``,\n            turns on untargeted attack. It should be noted that only untargeted attack\n            is supported for `model_type` is ``'detection'``, Default: ``True``.\n        reserve_ratio (Union[int, float]): The percentage of objects that can be detected after attacks,\n            specifically for `model_type` is ``'detection'``. Reserve_ratio should be in the range of (0, 1).\n            Default: ``0.3``.\n        pop_size (int): The number of particles, which should be greater than\n            zero. Default: ``6``.\n        mutation_rate (Union[int, float]): The probability of mutations, which should be in the range of (0, 1).\n            Default: ``0.005``.\n        per_bounds (Union[int, float]): Maximum L_inf distance.\n        max_steps (int): The maximum round of iteration for each adversarial\n            example. Default: ``1000``.\n        step_size (Union[int, float]): Attack step size. Default: ``0.2``.\n        temp (Union[int, float]): Sampling temperature for selection. Default: ``0.3``.\n            The greater the temp, the greater the differences between individuals'\n            selecting probabilities.\n        bounds (Union[tuple, list, None]): Upper and lower bounds of data. In form\n            of (clip_min, clip_max). Default: ``(0, 1.0)``.\n        adaptive (bool): If ``True``, turns on dynamic scaling of mutation\n            parameters. If ``False``, turns on static mutation parameters.\n            Default: ``False``.\n        sparse (bool): If ``True``, input labels are sparse-encoded. If ``False``,\n            input labels are one-hot-encoded. Default: ``True``.\n        c (Union[int, float]): Weight of perturbation loss. Default: ``0.1``.\n\n    Examples:\n        >>> import mindspore.ops.operations as M\n        >>> from mindspore import Tensor\n        >>> from mindspore.nn import Cell\n        >>> from mindarmour import BlackModel\n        >>> from mindarmour.adv_robustness.attacks import GeneticAttack\n        >>> class ModelToBeAttacked(BlackModel):\n        ...     def __init__(self, network):\n        ...         super(ModelToBeAttacked, self).__init__()\n        ...         self._network = network\n        ...     def predict(self, inputs):\n        ...         result = self._network(Tensor(inputs.astype(np.float32)))\n        ...         return result.asnumpy()\n        >>> class Net(Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = M.Softmax()\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         return out\n        >>> net = Net()\n        >>> model = ModelToBeAttacked(net)\n        >>> attack = GeneticAttack(model, sparse=False)\n        >>> batch_size = 6\n        >>> x_test = np.random.rand(batch_size, 10)\n        >>> y_test = np.random.randint(low=0, high=10, size=batch_size)\n        >>> y_test = np.eye(10)[y_test]\n        >>> y_test = y_test.astype(np.float32)\n        >>> _, adv_data, _ = attack.generate(x_test, y_test)\n    \"\"\"\n    def __init__(self, model, model_type='classification', targeted=True, reserve_ratio=0.3, sparse=True,\n                 pop_size=6, mutation_rate=0.005, per_bounds=0.15, max_steps=1000, step_size=0.20, temp=0.3,\n                 bounds=(0, 1.0), adaptive=False, c=0.1):\n        super(GeneticAttack, self).__init__()\n        self._model = check_model('model', model, BlackModel)\n        self._model_type = check_param_type('model_type', model_type, str)\n        if self._model_type not in ('classification', 'detection'):\n            msg = \"Only 'classification' or 'detection' is supported now, but got {}.\".format(self._model_type)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        self._targeted = check_param_type('targeted', targeted, bool)\n        self._reserve_ratio = check_value_non_negative('reserve_ratio', reserve_ratio)\n        if self._reserve_ratio > 1:\n            msg = \"reserve_ratio should not be greater than 1.0, but got {}.\".format(self._reserve_ratio)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        self._sparse = check_param_type('sparse', sparse, bool)\n        self._per_bounds = check_value_positive('per_bounds', per_bounds)\n        self._pop_size = check_int_positive('pop_size', pop_size)\n        self._step_size = check_value_positive('step_size', step_size)\n        self._temp = check_value_positive('temp', temp)\n        self._max_steps = check_int_positive('max_steps', max_steps)\n        self._mutation_rate = check_value_non_negative('mutation_rate', mutation_rate)\n        if self._mutation_rate > 1:\n            msg = \"mutation_rate should not be greater than 1.0, but got {}.\".format(self._mutation_rate)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        self._adaptive = check_param_type('adaptive', adaptive, bool)\n        # initial global optimum fitness value\n        self._best_fit = -np.inf\n        # count times of no progress\n        self._plateau_times = 0\n        # count times of changing attack step_size\n        self._adap_times = 0\n        self._bounds = bounds\n        if self._bounds is not None:\n            self._bounds = check_param_multi_types('bounds', bounds, [list, tuple])\n            for b in self._bounds:\n                _ = check_param_multi_types('bound', b, [int, float])\n        self._c = check_value_positive('c', c)\n\n    def _mutation(self, cur_pop, step_noise=0.01, prob=0.005):\n        \"\"\"\n        Generate mutation samples in genetic_attack.\n\n        Args:\n            cur_pop (numpy.ndarray): Samples before mutation.\n            step_noise (float): Noise range. Default: ``0.01``.\n            prob (float): Mutation probability. Default: ``0.005``.\n\n        Returns:\n            numpy.ndarray, samples after mutation operation in genetic_attack.\n\n        Examples:\n            >>> mul_pop = self._mutation_op([0.2, 0.3, 0.4], step_noise=0.03,\n            >>> prob=0.01)\n        \"\"\"\n        cur_pop = check_numpy_param('cur_pop', cur_pop)\n        perturb_noise = np.clip(np.random.random(cur_pop.shape) - 0.5,\n                                -step_noise, step_noise)*(self._bounds[1] - self._bounds[0])\n        mutated_pop = perturb_noise*(\n            np.random.random(cur_pop.shape) < prob) + cur_pop\n        return mutated_pop\n\n\n    def _compute_next_generation(self, cur_pop, fit_vals, x_ori):\n        \"\"\"\n        Compute pop for next generation\n\n        Args:\n            cur_pop (numpy.ndarray): Samples before mutation.\n            fit_vals (numpy.ndarray): fitness values\n            x_ori (numpy.ndarray): original input x\n\n        Returns:\n            numpy.ndarray, pop after generation\n\n        Examples:\n            >>> cur_pop, elite = self._compute_next_generation(cur_pop, fit_vals, x_ori)\n        \"\"\"\n        best_fit = max(fit_vals)\n\n        if best_fit > self._best_fit:\n            self._best_fit = best_fit\n            self._plateau_times = 0\n        else:\n            self._plateau_times += 1\n        adap_threshold = (lambda z: 100 if z > -0.4 else 300)(best_fit)\n        if self._plateau_times > adap_threshold:\n            self._adap_times += 1\n            self._plateau_times = 0\n        if self._adaptive:\n            step_noise = max(self._step_size, 0.4*(0.9**self._adap_times))\n            step_p = max(self._mutation_rate, 0.5*(0.9**self._adap_times))\n        else:\n            step_noise = self._step_size\n            step_p = self._mutation_rate\n        step_temp = self._temp\n        elite = cur_pop[np.argmax(fit_vals)]\n        select_probs = softmax(fit_vals/step_temp)\n        select_args = np.arange(self._pop_size)\n        parents_arg = np.random.choice(\n            a=select_args, size=2*(self._pop_size - 1),\n            replace=True, p=select_probs)\n        parent1 = cur_pop[parents_arg[:self._pop_size - 1]]\n        parent2 = cur_pop[parents_arg[self._pop_size - 1:]]\n        parent1_probs = select_probs[parents_arg[:self._pop_size - 1]]\n        parent2_probs = select_probs[parents_arg[self._pop_size - 1:]]\n        parent2_probs = parent2_probs / (parent1_probs + parent2_probs)\n        # duplicate the probabilities to all features of each particle.\n        dims = len(x_ori.shape)\n        for _ in range(dims):\n            parent2_probs = parent2_probs[:, np.newaxis]\n        parent2_probs = np.tile(parent2_probs, ((1,) + x_ori.shape))\n        cross_probs = (np.random.random(parent1.shape) >\n                       parent2_probs).astype(np.int32)\n        children = parent1*cross_probs + parent2*(1 - cross_probs)\n        mutated_children = self._mutation(\n            children, step_noise=self._per_bounds*step_noise,\n            prob=step_p)\n        cur_pop = np.concatenate((mutated_children, elite[np.newaxis, :]))\n\n        return cur_pop, elite\n\n\n\n    def _generate_classification(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples based on input data and\n        targeted labels (or ground_truth labels) for classification model.\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Input samples. The format of inputs should be numpy.ndarray.\n            labels (Union[numpy.ndarray, tuple]): Targeted labels or ground-truth labels.\n                                                  The format of labels should be numpy.ndarray.\n\n        Returns:\n            - numpy.ndarray, bool values for each attack result.\n\n            - numpy.ndarray, generated adversarial examples.\n\n            - numpy.ndarray, query times for each sample.\n        \"\"\"\n        inputs, labels = check_pair_numpy_param('inputs', inputs, 'labels', labels)\n        if self._sparse:\n            if labels.size > 1:\n                label_squ = np.squeeze(labels)\n            else:\n                label_squ = labels\n            if len(label_squ.shape) >= 2 or label_squ.shape[0] != inputs.shape[0]:\n                msg = \"The parameter 'sparse' of GeneticAttack is True, but the input labels is not sparse style \" \\\n                      \"and got its shape as {}.\".format(labels.shape)\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n        else:\n            labels = np.argmax(labels, axis=1)\n        images = inputs\n\n        adv_list = []\n        success_list = []\n        query_times_list = []\n        for i in range(images.shape[0]):\n            is_success = False\n            x_ori = images[i]\n            if not self._bounds:\n                self._bounds = [np.min(x_ori), np.max(x_ori)]\n            pixel_deep = self._bounds[1] - self._bounds[0]\n            label_i = labels[i]\n\n            # generate particles\n            ori_copies = np.repeat(x_ori[np.newaxis, :], self._pop_size, axis=0)\n            # initial perturbations\n            cur_pert = np.random.uniform(self._bounds[0], self._bounds[1], ori_copies.shape)\n            cur_pop = ori_copies + cur_pert\n            query_times = 0\n            iters = 0\n\n            while iters < self._max_steps:\n                iters += 1\n                cur_pop = np.clip(np.clip(cur_pop,\n                                          ori_copies - pixel_deep*self._per_bounds,\n                                          ori_copies + pixel_deep*self._per_bounds),\n                                  self._bounds[0], self._bounds[1])\n\n                pop_preds = self._model.predict(cur_pop)\n                query_times += cur_pop.shape[0]\n                all_preds = np.argmax(pop_preds, axis=1)\n                if self._targeted:\n                    success_pop = np.equal(label_i, all_preds).astype(np.int32)\n                else:\n                    success_pop = np.not_equal(label_i, all_preds).astype(np.int32)\n                is_success = max(success_pop)\n                best_idx = np.argmax(success_pop)\n                target_preds = pop_preds[:, label_i]\n                others_preds_sum = np.sum(pop_preds, axis=1) - target_preds\n                if self._targeted:\n                    fit_vals = target_preds - others_preds_sum\n                else:\n                    fit_vals = others_preds_sum - target_preds\n\n                if is_success:\n                    LOGGER.debug(TAG, 'successfully find one adversarial sample '\n                                      'and start Reduction process.')\n                    final_adv = cur_pop[best_idx]\n\n                    final_adv, query_times = self._reduction(x_ori, query_times, label_i, final_adv,\n                                                             model=self._model, targeted_attack=self._targeted)\n                    break\n\n                cur_pop, elite = self._compute_next_generation(cur_pop, fit_vals, x_ori)\n\n            if not is_success:\n                LOGGER.debug(TAG, 'fail to find adversarial sample.')\n                final_adv = elite\n            adv_list.append(final_adv)\n\n            LOGGER.debug(TAG,\n                         'iteration times is: %d and query times is: %d',\n                         iters,\n                         query_times)\n            success_list.append(is_success)\n            query_times_list.append(query_times)\n            del ori_copies, cur_pert, cur_pop\n        return np.asarray(success_list), \\\n               np.asarray(adv_list), \\\n               np.asarray(query_times_list)\n\n\n\n    def _generate_detection(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples based on input data and\n        targeted labels (or ground_truth labels) for detection model.\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Input samples. The format of inputs should be only one array.\n            labels (Union[numpy.ndarray, tuple]): Targeted labels or ground-truth labels. The format of labels should\n                be (gt_boxes, gt_labels).\n\n        Returns:\n            - numpy.ndarray, bool values for each attack result.\n\n            - numpy.ndarray, generated adversarial examples.\n\n            - numpy.ndarray, query times for each sample.\n        \"\"\"\n        images, auxiliary_inputs, gt_boxes, gt_labels = check_detection_inputs(inputs, labels)\n        adv_list = []\n        success_list = []\n        query_times_list = []\n        for i in range(images.shape[0]):\n            is_success = False\n            x_ori = images[i]\n            if not self._bounds:\n                self._bounds = [np.min(x_ori), np.max(x_ori)]\n            pixel_deep = self._bounds[1] - self._bounds[0]\n            auxiliary_input_i = tuple()\n            for item in auxiliary_inputs:\n                auxiliary_input_i += (np.expand_dims(item[i], axis=0),)\n            gt_boxes_i, gt_labels_i = np.expand_dims(gt_boxes[i], axis=0), np.expand_dims(gt_labels[i], axis=0)\n            inputs_i = (images[i],) + auxiliary_input_i\n            confi_ori, gt_object_num = self._detection_scores(inputs_i, gt_boxes_i, gt_labels_i, model=self._model)\n            LOGGER.info(TAG, 'The number of ground-truth objects is %s', gt_object_num[0])\n\n            # generate particles\n            ori_copies = np.repeat(x_ori[np.newaxis, :], self._pop_size, axis=0)\n            # initial perturbations\n            cur_pert = np.random.uniform(self._bounds[0], self._bounds[1], ori_copies.shape)\n            cur_pop = ori_copies + cur_pert\n            query_times = 0\n            iters = 0\n\n            while iters < self._max_steps:\n                iters += 1\n                cur_pop = np.clip(np.clip(cur_pop,\n                                          ori_copies - pixel_deep*self._per_bounds,\n                                          ori_copies + pixel_deep*self._per_bounds),\n                                  self._bounds[0], self._bounds[1])\n\n                confi_adv, correct_nums_adv = self._detection_scores(\n                    (cur_pop,) + auxiliary_input_i, gt_boxes_i, gt_labels_i, model=self._model)\n                LOGGER.info(TAG, 'The number of correctly detected objects in adversarial image is %s',\n                            np.min(correct_nums_adv))\n                query_times += self._pop_size\n                fit_vals = abs(\n                    confi_ori - confi_adv) - self._c / self._pop_size * np.linalg.norm(\n                        (cur_pop - x_ori).reshape(cur_pop.shape[0], -1), axis=1)\n\n                if np.max(fit_vals) < 0:\n                    self._c /= 2\n\n                if np.max(fit_vals) < -2:\n                    LOGGER.debug(TAG,\n                                 'best fitness value is %s, which is too small. We recommend that you decrease '\n                                 'the value of the initialization parameter c.', np.max(fit_vals))\n                if iters < 3 and np.max(fit_vals) > 100:\n                    LOGGER.debug(TAG,\n                                 'best fitness value is %s, which is too large. We recommend that you increase '\n                                 'the value of the initialization parameter c.', np.max(fit_vals))\n\n                if np.min(correct_nums_adv) <= int(gt_object_num*self._reserve_ratio):\n                    is_success = True\n                    best_idx = np.argmin(correct_nums_adv)\n\n                if is_success:\n                    LOGGER.debug(TAG, 'successfully find one adversarial sample '\n                                      'and start Reduction process.')\n                    final_adv = cur_pop[best_idx]\n                    break\n\n                cur_pop, elite = self._compute_next_generation(cur_pop, fit_vals, x_ori)\n\n            if not is_success:\n                LOGGER.debug(TAG, 'fail to find adversarial sample.')\n                final_adv = elite\n\n            final_adv, query_times = self._fast_reduction(\n                x_ori, final_adv, query_times, auxiliary_input_i, gt_boxes_i, gt_labels_i, model=self._model)\n            adv_list.append(final_adv)\n\n            LOGGER.debug(TAG,\n                         'iteration times is: %d and query times is: %d',\n                         iters,\n                         query_times)\n            success_list.append(is_success)\n            query_times_list.append(query_times)\n            del ori_copies, cur_pert, cur_pop\n        return np.asarray(success_list), \\\n               np.asarray(adv_list), \\\n               np.asarray(query_times_list)\n\n    def generate(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples based on input data and targeted labels (or ground_truth labels).\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Input samples. The format of inputs should be numpy.ndarray if\n                `model_type` is ``'classification'``. The format of inputs can be (input1, input2, ...) or only\n                one array if `model_type` is ``'detection'``.\n            labels (Union[numpy.ndarray, tuple]): Targeted labels or ground-truth labels. The format of labels should\n                be numpy.ndarray if `model_type` is ``'classification'``. The format of labels should be\n                (gt_boxes, gt_labels) if `model_type` is ``'detection'``.\n\n        Returns:\n            - numpy.ndarray, bool values for each attack result.\n\n            - numpy.ndarray, generated adversarial examples.\n\n            - numpy.ndarray, query times for each sample.\n        \"\"\"\n        if self._model_type == 'classification':\n            success_list, adv_data, query_time_list = self._generate_classification(inputs, labels)\n\n        elif self._model_type == 'detection':\n            success_list, adv_data, query_time_list = self._generate_detection(inputs, labels)\n\n        return success_list, adv_data, query_time_list\n"
  },
  {
    "path": "mindarmour/adv_robustness/attacks/black/hop_skip_jump_attack.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nHop-skip-jump attack.\n\"\"\"\nimport numpy as np\n\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_pair_numpy_param, check_model, \\\n    check_numpy_param, check_int_positive, check_value_positive, \\\n    check_value_non_negative, check_param_type\nfrom ..attack import Attack\nfrom .black_model import BlackModel\n\nLOGGER = LogUtil.get_instance()\nTAG = 'HopSkipJumpAttack'\n\n\ndef _clip_image(image, clip_min, clip_max):\n    \"\"\"\n    Clip an image, or an image batch, with upper and lower threshold.\n    \"\"\"\n    return np.clip(image, clip_min, clip_max)\n\n\nclass HopSkipJumpAttack(Attack):\n    \"\"\"\n    HopSkipJumpAttack proposed by Chen, Jordan and Wainwright is a\n    decision-based attack. The attack requires access to output labels of\n    target model.\n\n    References: `Chen J, Michael I. Jordan, Martin J. Wainwright.\n    HopSkipJumpAttack: A Query-Efficient Decision-Based Attack. 2019.\n    arXiv:1904.02144 <https://arxiv.org/abs/1904.02144>`_\n\n    Args:\n        model (BlackModel): Target model.\n        init_num_evals (int): The initial number of evaluations for gradient\n            estimation. Default: ``100``.\n        max_num_evals (int): The maximum number of evaluations for gradient\n            estimation. Default: ``1000``.\n        stepsize_search (str): Indicating how to search for stepsize; Possible\n            values are ``'geometric_progression'``, ``'grid_search'``.\n            Default: ``'geometric_progression'``.\n        num_iterations (int): The number of iterations. Default: ``20``.\n        gamma (float): Used to set binary search threshold theta. Default: ``1.0``.\n            For l2 attack the binary search threshold `theta` is\n            :math:`gamma / d^{3/2}`. For linf attack is :math:`gamma / d^2`.\n            Default: ``1.0``.\n        constraint (str): The norm distance to optimize. Possible values are ``'l2'``,\n            ``'linf'``. Default: ``'l2'``.\n        batch_size (int): Batch size. Default: ``32``.\n        clip_min (float, optional): The minimum image component value.\n            Default: ``0``.\n        clip_max (float, optional): The maximum image component value.\n            Default: ``1``.\n        sparse (bool): If ``True``, input labels are sparse-encoded. If ``False``,\n            input labels are one-hot-encoded. Default: ``True``.\n\n    Raises:\n        ValueError: If `stepsize_search` is not ``'geometric_progression'`` or\n            ``'grid_search'``.\n        ValueError: If `constraint` is not ``'l2'`` or ``'linf'``.\n\n    Examples:\n        >>> from mindspore import Tensor\n        >>> from mindarmour import BlackModel\n        >>> import mindspore.ops.operations as P\n        >>> from mindarmour.adv_robustness.attacks import HopSkipJumpAttack\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...         self._reduce = P.ReduceSum()\n        ...         self._squeeze = P.Squeeze(1)\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         out = self._reduce(out, 2)\n        ...         out = self._squeeze(out)\n        ...         return out\n        >>> class ModelToBeAttacked(BlackModel):\n        ...     def __init__(self, network):\n        ...         super(ModelToBeAttacked, self).__init__()\n        ...         self._network = network\n        ...     def predict(self, inputs):\n        ...         if len(inputs.shape) == 3:\n        ...             inputs = inputs[np.newaxis, :]\n        ...         result = self._network(Tensor(inputs.astype(np.float32)))\n        ...         return result.asnumpy()\n        >>> net = Net()\n        >>> model = ModelToBeAttacked(net)\n        >>> attack = HopSkipJumpAttack(model)\n        >>> n, c, h, w = 1, 1, 32, 32\n        >>> class_num = 3\n        >>> x_test = np.asarray(np.random.random((n,c,h,w)), np.float32)\n        >>> y_test = np.random.randint(0, class_num, size=n)\n        >>> _, adv_x, _= attack.generate(x_test, y_test)\n    \"\"\"\n\n    def __init__(self, model, init_num_evals=100, max_num_evals=1000,\n                 stepsize_search='geometric_progression', num_iterations=20,\n                 gamma=1.0, constraint='l2', batch_size=32, clip_min=0.0,\n                 clip_max=1.0, sparse=True):\n        super(HopSkipJumpAttack, self).__init__()\n        self._model = check_model('model', model, BlackModel)\n        self._init_num_evals = check_int_positive('initial_num_evals',\n                                                  init_num_evals)\n        self._max_num_evals = check_int_positive('max_num_evals', max_num_evals)\n        self._batch_size = check_int_positive('batch_size', batch_size)\n        self._clip_min = check_value_non_negative('clip_min', clip_min)\n        self._clip_max = check_value_non_negative('clip_max', clip_max)\n        self._sparse = check_param_type('sparse', sparse, bool)\n        self._np_dtype = np.dtype('float32')\n        if stepsize_search in ['geometric_progression', 'grid_search']:\n            self._stepsize_search = stepsize_search\n        else:\n            msg = \"stepsize_search must be in ['geometric_progression',\" \\\n                  \" 'grid_search'], but got {}\".format(stepsize_search)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n        self._num_iterations = check_int_positive('num_iterations',\n                                                  num_iterations)\n        self._gamma = check_value_positive('gamma', gamma)\n        if constraint in ['l2', 'linf']:\n            self._constraint = constraint\n        else:\n            msg = \"constraint must be in ['l2', 'linf'], \" \\\n                  \"but got {}\".format(constraint)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        self.queries = 0\n        self.is_adv = True\n        self.y_targets = None\n        self.image_targets = None\n        self.y_target = None\n        self.image_target = None\n\n    def _generate_one(self, sample):\n        \"\"\"\n        Return a tensor that constructs adversarial examples for the given\n        input.\n\n        Args:\n            sample (Tensor): Input samples.\n\n        Returns:\n            Tensor, generated adversarial examples.\n        \"\"\"\n        shape = list(np.shape(sample))\n        dim = int(np.prod(shape))\n\n        # Set binary search threshold.\n        if self._constraint == 'l2':\n            theta = self._gamma / (np.sqrt(dim)*dim)\n        else:\n            theta = self._gamma / (dim*dim)\n\n        wrap = self._hsja(sample, self.y_target, self.image_target, dim, theta)\n        if wrap is None:\n            self.is_adv = False\n        else:\n            self.is_adv = True\n        return self.is_adv, wrap, self.queries\n\n    def set_target_images(self, target_images):\n        \"\"\"\n        Setting target images for target attack.\n\n        Args:\n            target_images (numpy.ndarray): Target images.\n        \"\"\"\n        self.image_targets = check_numpy_param('target_images', target_images)\n\n    def generate(self, inputs, labels):\n        \"\"\"\n        Generate adversarial images in a for loop.\n\n        Args:\n            inputs (numpy.ndarray): Origin images.\n            labels (numpy.ndarray): Target labels.\n\n        Returns:\n            - numpy.ndarray, bool values for each attack result.\n\n            - numpy.ndarray, generated adversarial examples.\n\n            - numpy.ndarray, query times for each sample.\n        \"\"\"\n        if labels is not None:\n            inputs, labels = check_pair_numpy_param('inputs', inputs,\n                                                    'labels', labels)\n\n        if not self._sparse:\n            labels = np.argmax(labels, axis=1)\n        x_adv = []\n        is_advs = []\n        queries_times = []\n\n        if labels is not None:\n            self.y_targets = labels\n\n        for i, x_single in enumerate(inputs):\n            self.queries = 0\n            if self.image_targets is not None:\n                self.image_target = self.image_targets[i]\n            if self.y_targets is not None:\n                self.y_target = self.y_targets[i]\n            is_adv, adv_img, query_time = self._generate_one(x_single)\n            x_adv.append(adv_img)\n            is_advs.append(is_adv)\n            queries_times.append(query_time)\n\n        return np.asarray(is_advs), \\\n               np.asarray(x_adv), \\\n               np.asarray(queries_times)\n\n    def _hsja(self, sample, target_label, target_image, dim, theta):\n        \"\"\"\n        The main algorithm for HopSkipJumpAttack.\n\n        Args:\n            sample (numpy.ndarray): Input image. Without the batchsize\n                dimension.\n            target_label (int): Integer for targeted attack, None for\n                nontargeted attack. Without the batchsize dimension.\n            target_image (numpy.ndarray): An array with the same size as\n                input sample, or None. Without the batchsize dimension.\n\n        Returns:\n            numpy.ndarray, perturbed images.\n        \"\"\"\n        original_label = None\n        # Original label for untargeted attack.\n        if target_label is None:\n            original_label = self._model.predict(sample)\n            original_label = np.argmax(original_label)\n\n        # Initialize perturbed image.\n        # untarget attack\n        if target_image is None:\n            perturbed = self._initialize(sample, original_label, target_label)\n            if perturbed is None:\n                msg = 'Can not find an initial adversarial example'\n                LOGGER.info(TAG, msg)\n                return perturbed\n        else:\n            # Target attack\n            perturbed = target_image\n\n        # Project the initial perturbed image to the decision boundary.\n        perturbed, dist_post_update = self._binary_search_batch(sample,\n                                                                np.expand_dims(perturbed, 0),\n                                                                original_label,\n                                                                target_label,\n                                                                theta)\n\n        # Calculate the distance of perturbed image and original sample\n        dist = self._compute_distance(perturbed, sample)\n        for j in np.arange(self._num_iterations):\n            current_iteration = j + 1\n\n            # Select delta.\n            delta = self._select_delta(dist_post_update, current_iteration, dim,\n                                       theta)\n            # Choose number of evaluations.\n            num_evals = int(min([self._init_num_evals*np.sqrt(j + 1),\n                                 self._max_num_evals]))\n\n            # approximate gradient.\n            gradf = self._approximate_gradient(perturbed, num_evals,\n                                               original_label, target_label,\n                                               delta, theta)\n            if self._constraint == 'linf':\n                update = np.sign(gradf)\n            else:\n                update = gradf\n\n            # search step size.\n            if self._stepsize_search == 'geometric_progression':\n                # find step size.\n                epsilon = self._geometric_progression_for_stepsize(\n                    perturbed,\n                    update,\n                    dist,\n                    current_iteration,\n                    original_label,\n                    target_label)\n                # Update the sample.\n                perturbed = _clip_image(perturbed + epsilon*update,\n                                        self._clip_min, self._clip_max)\n\n                # Binary search to return to the boundary.\n                perturbed, dist_post_update = self._binary_search_batch(\n                    sample,\n                    perturbed[None],\n                    original_label,\n                    target_label,\n                    theta)\n\n            elif self._stepsize_search == 'grid_search':\n                epsilons = np.logspace(-4, 0, num=20, endpoint=True)*dist\n                epsilons_shape = [20] + len(np.shape(sample))*[1]\n                perturbeds = perturbed + epsilons.reshape(\n                    epsilons_shape)*update\n                perturbeds = _clip_image(perturbeds, self._clip_min,\n                                         self._clip_max)\n                idx_perturbed = self._decision_function(perturbeds,\n                                                        original_label,\n                                                        target_label)\n\n                if np.sum(idx_perturbed) > 0:\n                    # Select the perturbation that yields the minimum distance\n                    # after binary search.\n                    perturbed, dist_post_update = self._binary_search_batch(\n                        sample, perturbeds[idx_perturbed],\n                        original_label, target_label, theta)\n\n            # compute new distance.\n            dist = self._compute_distance(perturbed, sample)\n\n            LOGGER.debug(TAG,\n                         'iteration: %d, %s distance %4f',\n                         j + 1,\n                         self._constraint, dist)\n\n        perturbed = np.expand_dims(perturbed, 0)\n        return perturbed\n\n    def _decision_function(self, images, original_label, target_label):\n        \"\"\"\n        Decision function returns 1 if the input sample is on the desired\n        side of the boundary, and 0 otherwise.\n        \"\"\"\n        images = _clip_image(images, self._clip_min, self._clip_max)\n        prob = []\n        self.queries += len(images)\n        for i in range(0, len(images), self._batch_size):\n            batch = images[i:i + self._batch_size]\n            length = len(batch)\n            prob_i = self._model.predict(batch)[:length]\n            prob.append(prob_i)\n        prob = np.concatenate(prob)\n        if target_label is None:\n            res = np.argmax(prob, axis=1) != original_label\n        else:\n            res = np.argmax(prob, axis=1) == target_label\n        return res\n\n    def _compute_distance(self, original_img, perturbation_img):\n        \"\"\"\n        Compute the distance between original image and perturbation images.\n        \"\"\"\n        if self._constraint == 'l2':\n            distance = np.linalg.norm(original_img - perturbation_img)\n        else:\n            distance = np.max(abs(original_img - perturbation_img))\n        return distance\n\n    def _approximate_gradient(self, sample, num_evals, original_label,\n                              target_label, delta, theta):\n        \"\"\"\n        Gradient direction estimation.\n        \"\"\"\n        # Generate random noise based on constraint.\n        noise_shape = [num_evals] + list(np.shape(sample))\n        if self._constraint == 'l2':\n            random_noise = np.random.randn(*noise_shape)\n        else:\n            random_noise = np.random.uniform(low=-1, high=1, size=noise_shape)\n        axis = tuple(range(1, 1 + len(np.shape(sample))))\n        random_noise = random_noise / np.sqrt(\n            np.sum(random_noise**2, axis=axis, keepdims=True))\n\n        # perturbed images\n        perturbed = sample + delta*random_noise\n        perturbed = _clip_image(perturbed, self._clip_min, self._clip_max)\n        random_noise = (perturbed - sample) / theta\n\n        # Whether the perturbed images are on the desired side of the boundary.\n        decisions = self._decision_function(perturbed, original_label,\n                                            target_label)\n        decision_shape = [len(decisions)] + [1]*len(np.shape(sample))\n        # transform decisions value from 1, 0 to 1, -2\n        re_decision = 2*np.array(decisions).astype(self._np_dtype).reshape(\n            decision_shape) - 1.0\n\n        if np.mean(re_decision) == 1.0:\n            grad_direction = np.mean(random_noise, axis=0)\n        elif np.mean(re_decision) == -1.0:\n            grad_direction = - np.mean(random_noise, axis=0)\n        else:\n            re_decision = re_decision - np.mean(re_decision)\n            grad_direction = np.mean(re_decision*random_noise, axis=0)\n\n        # The gradient direction.\n        grad_direction = grad_direction / (np.linalg.norm(grad_direction) + 1e-10)\n\n        return grad_direction\n\n    def _project(self, original_image, perturbed_images, alphas):\n        \"\"\"\n        Projection input samples onto given l2 or linf balls.\n        \"\"\"\n        alphas_shape = [len(alphas)] + [1]*len(np.shape(original_image))\n        alphas = alphas.reshape(alphas_shape)\n        if self._constraint == 'l2':\n            projected = (1 - alphas)*original_image + alphas*perturbed_images\n        else:\n            projected = _clip_image(perturbed_images, original_image - alphas,\n                                    original_image + alphas)\n\n        return projected\n\n    def _binary_search_batch(self, original_image, perturbed_images,\n                             original_label, target_label, theta):\n        \"\"\"\n        Binary search to approach the model decision boundary.\n        \"\"\"\n\n        # Compute distance between perturbed image and original image.\n        dists_post_update = np.array([self._compute_distance(original_image,\n                                                             perturbed_image,)\n                                      for perturbed_image in perturbed_images])\n\n        # Get higher thresholds\n        if self._constraint == 'l2':\n            highs = np.ones(len(perturbed_images))\n            thresholds = theta\n        else:\n            highs = dists_post_update\n            thresholds = np.minimum(dists_post_update*theta, theta)\n\n        # Get lower thresholds\n        lows = np.zeros(len(perturbed_images))\n\n        # Update thresholds.\n        while np.max((highs - lows) / thresholds) > 1:\n            mids = (highs + lows) / 2.0\n            mid_images = self._project(original_image, perturbed_images, mids)\n            decisions = self._decision_function(mid_images, original_label,\n                                                target_label)\n            lows = np.where(decisions == [0], mids, lows)\n            highs = np.where(decisions == [1], mids, highs)\n\n        out_images = self._project(original_image, perturbed_images, highs)\n\n        # Select the best choice based on the distance of the output image.\n        dists = np.array(\n            [self._compute_distance(original_image, out_image) for out_image in\n             out_images])\n        idx = np.argmin(dists)\n\n        dist = dists_post_update[idx]\n        out_image = out_images[idx]\n        return out_image, dist\n\n    def _initialize(self, sample, original_label, target_label):\n        \"\"\"\n        Implementation of BlendedUniformNoiseAttack\n        \"\"\"\n        num_evals = 0\n\n        while True:\n            random_noise = np.random.uniform(self._clip_min, self._clip_max,\n                                             size=np.shape(sample))\n            success = self._decision_function(random_noise[None],\n                                              original_label,\n                                              target_label)\n            if success:\n                break\n            num_evals += 1\n\n            if num_evals > 1e3:\n                return None\n\n        # Binary search.\n        low = 0.0\n        high = 1.0\n        while high - low > 0.001:\n            mid = (high + low) / 2.0\n            blended = (1 - mid)*sample + mid*random_noise\n            success = self._decision_function(blended[None], original_label,\n                                              target_label)\n            if success:\n                high = mid\n            else:\n                low = mid\n\n        initialization = (1 - high)*sample + high*random_noise\n        return initialization\n\n    def _geometric_progression_for_stepsize(self, perturbed, update, dist,\n                                            current_iteration, original_label,\n                                            target_label):\n        \"\"\"\n        Search for stepsize in the way of Geometric progression.\n        Keep decreasing stepsize by half until reaching the desired side of\n        the decision boundary.\n        \"\"\"\n        epsilon = dist / np.sqrt(current_iteration)\n        while True:\n            updated = perturbed + epsilon*update\n            success = self._decision_function(updated, original_label,\n                                              target_label)\n            if success:\n                break\n            epsilon = epsilon / 2.0\n\n        return epsilon\n\n    def _select_delta(self, dist_post_update, current_iteration, dim, theta):\n        \"\"\"\n        Choose the delta based on the distance between the input sample\n        and the perturbed sample.\n        \"\"\"\n        if current_iteration == 1:\n            delta = 0.1*(self._clip_max - self._clip_min)\n        else:\n            if self._constraint == 'l2':\n                delta = np.sqrt(dim)*theta*dist_post_update\n            else:\n                delta = dim*theta*dist_post_update\n\n        return delta\n"
  },
  {
    "path": "mindarmour/adv_robustness/attacks/black/natural_evolutionary_strategy.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nNatural-evolutionary-strategy Attack.\n\"\"\"\nimport time\nimport numpy as np\nfrom scipy.special import softmax\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_pair_numpy_param, check_model, \\\n    check_numpy_param, check_int_positive, check_value_positive, check_param_type\nfrom ..attack import Attack\nfrom .black_model import BlackModel\n\nLOGGER = LogUtil.get_instance()\nTAG = 'NES'\n\n\ndef _bound(image, epislon):\n    lower = np.clip(image - epislon, 0, 1)\n    upper = np.clip(image + epislon, 0, 1)\n    return lower, upper\n\n\nclass NES(Attack):\n    \"\"\"\n    The class is an implementation of the Natural Evolutionary Strategies Attack\n    Method. NES uses natural evolutionary strategies to estimate gradients to\n    improve query efficiency. NES covers three settings: Query-Limited setting,\n    Partial-Information setting and Label-Only setting. In the query-limit\n    setting, the attack has a limited number of queries to the target model but\n    access to the probabilities of all classes. In the partial-info setting,\n    the attack only has access to the probabilities for top-k classes.\n    In the label-only setting, the attack only has access to a list of k inferred\n    labels ordered by their predicted probabilities. In the Partial-Information\n    setting and Label-Only setting, NES do target attack so user need to use\n    set_target_images method to set target images of target classes.\n\n    References: `Andrew Ilyas, Logan Engstrom, Anish Athalye, and Jessy Lin.\n    Black-box adversarial attacks with limited queries and information. In\n    ICML, July 2018 <https://arxiv.org/abs/1804.08598>`_\n\n    Args:\n        model (BlackModel): Target model to be attacked.\n        scene (str): Scene in ``'Label_Only'``, ``'Partial_Info'`` or ``'Query_Limit'``.\n        max_queries (int): Maximum query numbers to generate an adversarial example. Default: ``10000``.\n        top_k (int): For Partial-Info or Label-Only setting, indicating how much (Top-k) information is\n            available for the attacker. For Query-Limited setting, this input should be set as ``-1``. Default: ``-1``.\n        num_class (int): Number of classes in dataset. Default: ``10``.\n        batch_size (int): Batch size. Default: ``128``.\n        epsilon (float): Maximum perturbation allowed in attack. Default: ``0.3``.\n        samples_per_draw (int): Number of samples draw in antithetic sampling. Default: ``128``.\n        momentum (float): Momentum. Default: ``0.9``.\n        learning_rate (float): Learning rate. Default: ``1e-3``.\n        max_lr (float): Max Learning rate. Default: ``5e-2``.\n        min_lr (float): Min Learning rate. Default: ``5e-4``.\n        sigma (float): Step size of random noise. Default: ``1e-3``.\n        plateau_length (int): Length of plateau used in Annealing algorithm. Default: ``20``.\n        plateau_drop (float): Drop of plateau used in Annealing algorithm. Default: ``2.0``.\n        adv_thresh (float): Threshold of adversarial. Default: ``0.25``.\n        zero_iters (int): Number of points to use for the proxy score. Default: ``10``.\n        starting_eps (float): Starting epsilon used in Label-Only setting. Default: ``1.0``.\n        starting_delta_eps (float): Delta epsilon used in Label-Only setting. Default: ``0.5``.\n        label_only_sigma (float): Sigma used in Label-Only setting. Default: ``1e-3``.\n        conservative (int): Conservation used in epsilon decay, it will increase if no convergence. Default: ``2``.\n        sparse (bool): If ``True``, input labels are sparse-encoded. If ``False``,\n            input labels are one-hot-encoded. Default: ``True``.\n\n    Examples:\n        >>> from mindspore import Tensor\n        >>> from mindarmour import BlackModel\n        >>> import mindspore.ops.operations as P\n        >>> from mindarmour.adv_robustness.attacks import NES\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...         self._reduce = P.ReduceSum()\n        ...         self._squeeze = P.Squeeze(1)\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         out = self._reduce(out, 2)\n        ...         out = self._squeeze(out)\n        ...         return out\n        >>> class ModelToBeAttacked(BlackModel):\n        ...     def __init__(self, network):\n        ...         super(ModelToBeAttacked, self).__init__()\n        ...         self._network = network\n        ...     def predict(self, inputs):\n        ...         if len(inputs.shape) == 1:\n        ...             inputs = np.expand_dims(inputs, axis=0)\n        ...         result = self._network(Tensor(inputs.astype(np.float32)))\n        ...         return result.asnumpy()\n        >>> net = Net()\n        >>> model = ModelToBeAttacked(net)\n        >>> SCENE = 'Query_Limit'\n        >>> TOP_K = -1\n        >>> attack= NES(model, SCENE, top_k=TOP_K)\n        >>> num_class = 5\n        >>> x_test = np.asarray(np.random.random((1, 1, 32, 32)), np.float32)\n        >>> target_image  = np.asarray(np.random.random((1, 1, 32, 32)), np.float32)\n        >>> orig_class = 0\n        >>> target_class = 2\n        >>> attack.set_target_images(target_image)\n        >>> tag, adv, queries = attack.generate(np.array(x_test), np.array([target_class]))\n    \"\"\"\n\n    def __init__(self, model, scene, max_queries=10000, top_k=-1, num_class=10, batch_size=128, epsilon=0.3,\n                 samples_per_draw=128, momentum=0.9, learning_rate=1e-3, max_lr=5e-2, min_lr=5e-4, sigma=1e-3,\n                 plateau_length=20, plateau_drop=2.0, adv_thresh=0.25, zero_iters=10, starting_eps=1.0,\n                 starting_delta_eps=0.5, label_only_sigma=1e-3, conservative=2, sparse=True):\n        super(NES, self).__init__()\n        self._model = check_model('model', model, BlackModel)\n        self._scene = scene\n\n        self._max_queries = check_int_positive('max_queries', max_queries)\n        self._num_class = check_int_positive('num_class', num_class)\n        self._batch_size = check_int_positive('batch_size', batch_size)\n        self._samples_per_draw = check_int_positive('samples_per_draw', samples_per_draw)\n        self._goal_epsilon = check_value_positive('epsilon', epsilon)\n        self._momentum = check_value_positive('momentum', momentum)\n        self._learning_rate = check_value_positive('learning_rate', learning_rate)\n        self._max_lr = check_value_positive('max_lr', max_lr)\n        self._min_lr = check_value_positive('min_lr', min_lr)\n        self._sigma = check_value_positive('sigma', sigma)\n        self._plateau_length = check_int_positive('plateau_length', plateau_length)\n        self._plateau_drop = check_value_positive('plateau_drop', plateau_drop)\n        # partial information arguments\n        self._k = top_k\n        self._adv_thresh = check_value_positive('adv_thresh', adv_thresh)\n        # label only arguments\n        self._zero_iters = check_int_positive('zero_iters', zero_iters)\n        self._starting_eps = check_value_positive('starting_eps', starting_eps)\n        self._starting_delta_eps = check_value_positive('starting_delta_eps', starting_delta_eps)\n        self._label_only_sigma = check_value_positive('label_only_sigma', label_only_sigma)\n        self._conservative = check_int_positive('conservative', conservative)\n        self._sparse = check_param_type('sparse', sparse, bool)\n        self.target_imgs = None\n        self.target_img = None\n        self.target_class = None\n\n    def generate(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples based on input data and target labels.\n\n        Args:\n            inputs (numpy.ndarray): Benign input samples.\n            labels (numpy.ndarray): Target labels.\n\n        Returns:\n            - numpy.ndarray, bool values for each attack result.\n\n            - numpy.ndarray, generated adversarial examples.\n\n            - numpy.ndarray, query times for each sample.\n\n        Raises:\n            ValueError: If the `top_k` less than 0 in Label-Only or Partial-Info setting.\n            ValueError: If the `target_imgs` is ``None`` in Label-Only or Partial-Info setting.\n            ValueError: If `scene` is not ``'Label_Only'``, ``'Partial_Info'`` or ``'Query_Limit'``.\n        \"\"\"\n        inputs, labels = check_pair_numpy_param('inputs', inputs, 'labels', labels)\n        if not self._sparse:\n            labels = np.argmax(labels, axis=1)\n\n        if self._scene == 'Label_Only' or self._scene == 'Partial_Info':\n            if self._k < 1:\n                msg = \"In 'Label_Only' or 'Partial_Info' mode, 'top_k' must more than 0.\"\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n            if self.target_imgs is None:\n                msg = \"In 'Label_Only' or 'Partial_Info' mode, 'target_imgs' must be set.\"\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n\n        elif self._scene == 'Query_Limit':\n            self._k = self._num_class\n        else:\n            msg = \"scene must be string in 'Label_Only', 'Partial_Info' or 'Query_Limit' \"\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n        is_advs = []\n        advs = []\n        queries = []\n        for sample, label, target_img in zip(inputs, labels, self.target_imgs):\n            is_adv, adv, query = self._generate_one(sample, label, target_img)\n            is_advs.append(is_adv)\n            advs.append(adv)\n            queries.append(query)\n\n        return is_advs, advs, queries\n\n    def set_target_images(self, target_images):\n        \"\"\"\n        Set target samples for target attack in the Partial-Info setting or Label-Only setting.\n\n        Args:\n            target_images (numpy.ndarray): Target samples for target attack.\n        \"\"\"\n        self.target_imgs = check_numpy_param('target_images', target_images)\n\n    def _generate_one(self, origin_image, target_label, target_image):\n        \"\"\"\n        Main algorithm for NES.\n\n        Args:\n            origin_image (numpy.ndarray): Benign input sample.\n            target_label (int): Target label.\n\n        Returns:\n            - bool.\n                - If True: successfully make an adversarial example.\n\n                - If False: unsuccessfully make an adversarial example.\n\n            - numpy.ndarray, an adversarial example.\n\n            - int, number of queries.\n        \"\"\"\n        self.target_class = target_label\n        origin_image = check_numpy_param('origin_image', origin_image)\n        self._epsilon = self._starting_eps\n        lower, upper = _bound(origin_image, self._epsilon)\n        goal_epsilon = self._goal_epsilon\n        delta_epsilon = self._starting_delta_eps\n        if self._scene == 'Label_Only' or self._scene == 'Partial_Info':\n            adv = target_image\n        else:\n            adv = origin_image.copy()\n\n        # for backtracking and momentum\n        num_queries = 0\n        gradient = 0\n        last_ls = []\n        max_iters = int(np.ceil(self._max_queries // self._samples_per_draw))\n        for i in range(max_iters):\n            start = time.time()\n            # early stop\n            eval_preds = self._model.predict(adv)\n            eval_preds = np.argmax(eval_preds, axis=1)\n            padv = np.equal(eval_preds, self.target_class)\n            if padv and self._epsilon <= goal_epsilon:\n                LOGGER.debug(TAG, 'early stopping at iteration %d', i)\n                return True, adv, num_queries\n\n            #  antithetic sampling noise\n            size = (self._batch_size // 2,) + origin_image.shape\n            noise_pos = np.random.normal(size=size)\n            noise = np.concatenate((noise_pos, -noise_pos), axis=0)\n            eval_points = adv + self._sigma*noise\n\n            prev_g = gradient\n            loss, gradient = self._get_grad(origin_image, eval_points, noise)\n            gradient = self._momentum*prev_g + (1.0 - self._momentum)*gradient\n\n            # plateau learning rate annealing\n            last_ls.append(loss)\n            last_ls = self._plateau_annealing(last_ls)\n\n            # search for learning rate and epsilon decay\n            current_lr = self._max_lr\n            prop_delta_eps = 0.0\n            if loss < self._adv_thresh and self._epsilon > goal_epsilon:\n                prop_delta_eps = delta_epsilon\n            while current_lr >= self._min_lr:\n                # in partial information only or label only setting\n                if self._scene == 'Label_Only' or self._scene == 'Partial_Info':\n                    proposed_epsilon = max(self._epsilon - prop_delta_eps, goal_epsilon)\n                    lower, upper = _bound(origin_image, proposed_epsilon)\n                proposed_adv = adv - current_lr*np.sign(gradient)\n                proposed_adv = np.clip(proposed_adv, lower, upper)\n                num_queries += 1\n\n                if self._preds_in_top_k(self.target_class, proposed_adv):\n                    # The predicted label of proposed adversarial examples is in\n                    # the top k observations.\n                    if prop_delta_eps > 0:\n                        delta_epsilon = max(prop_delta_eps, 0.1)\n                        last_ls = []\n                    adv = proposed_adv\n                    self._epsilon = self._epsilon - prop_delta_eps / self._conservative\n                    self._epsilon = max(self._epsilon, goal_epsilon)\n                    break\n                elif current_lr >= self._min_lr*2:\n                    current_lr = current_lr / 2\n                    LOGGER.debug(TAG, \"backtracking learning rate to %.3f\", current_lr)\n                else:\n                    prop_delta_eps = prop_delta_eps / 2\n                    if prop_delta_eps < 2e-3:\n                        LOGGER.debug(TAG, \"Did not converge.\")\n                        return False, adv, num_queries\n                    current_lr = self._max_lr\n                    LOGGER.debug(TAG, \"backtracking epsilon to %.3f\", self._epsilon - prop_delta_eps)\n\n            # update the number of queries\n            if self._scene == 'Label_Only':\n                num_queries += self._samples_per_draw*self._zero_iters\n            else:\n                num_queries += self._samples_per_draw\n            LOGGER.debug(TAG,\n                         'Step %d: loss %.4f, lr %.2E, eps %.3f, time %.4f.',\n                         i,\n                         loss,\n                         current_lr,\n                         self._epsilon,\n                         time.time() - start)\n\n        return False, adv, num_queries\n\n    def _plateau_annealing(self, last_loss):\n        last_loss = last_loss[-self._plateau_length:]\n        if last_loss[-1] > last_loss[0] and len(last_loss) == self._plateau_length:\n            if self._max_lr > self._min_lr:\n                LOGGER.debug(TAG, \"Annealing max learning rate.\")\n                self._max_lr = max(self._max_lr / self._plateau_drop, self._min_lr)\n            last_loss = []\n        return last_loss\n\n    def _softmax_cross_entropy_with_logit(self, logit):\n        logit = softmax(logit, axis=1)\n        onehot_label = np.zeros(self._num_class)\n        onehot_label[self.target_class] = 1\n        onehot_labels = np.tile(onehot_label, (len(logit), 1))\n        entropy = -onehot_labels*np.log(logit)\n        loss = np.mean(entropy, axis=1)\n        return loss\n\n    def _query_limit_loss(self, eval_points, noise):\n        \"\"\"\n        Loss in Query-Limit setting.\n        \"\"\"\n        LOGGER.debug(TAG, 'enter the function _query_limit_loss().')\n        loss = self._softmax_cross_entropy_with_logit(self._model.predict(eval_points))\n\n        return loss, noise\n\n    def _partial_info_loss(self, eval_points, noise):\n        \"\"\"\n        Loss in Partial-Info setting.\n        \"\"\"\n        LOGGER.debug(TAG, 'enter the function _partial_info_loss.')\n        logit = self._model.predict(eval_points)\n        loss = np.sort(softmax(logit, axis=1))[:, -self._k:]\n        inds = np.argsort(logit)[:, -self._k:]\n        good_loss = np.where(np.equal(inds, self.target_class), loss, np.zeros(np.shape(inds)))\n        good_loss = np.max(good_loss, axis=1)\n        losses = -np.log(good_loss)\n        return losses, noise\n\n    def _label_only_loss(self, origin_image, eval_points, noise):\n        \"\"\"\n        Loss in Label-Only setting.\n        \"\"\"\n        LOGGER.debug(TAG, 'enter the function _label_only_loss().')\n        tiled_points = np.tile(np.expand_dims(eval_points, 0), [self._zero_iters, *[1]*len(eval_points.shape)])\n        noised_eval_im = tiled_points + np.random.randn(self._zero_iters,\n                                                        self._batch_size,\n                                                        *origin_image.shape)*self._label_only_sigma\n        noised_eval_im = np.reshape(noised_eval_im, (self._zero_iters*self._batch_size, *origin_image.shape))\n        logits = self._model.predict(noised_eval_im)\n        inds = np.argsort(logits)[:, -self._k:]\n        real_inds = np.reshape(inds, (self._zero_iters, self._batch_size, -1))\n        rank_range = np.arange(1, self._k + 1, 1, dtype=np.float32)\n        tiled_rank_range = np.tile(np.reshape(rank_range, (1, 1, self._k)), [self._zero_iters, self._batch_size, 1])\n        batches_in = np.where(np.equal(real_inds, self.target_class),\n                              tiled_rank_range,\n                              np.zeros(np.shape(tiled_rank_range)))\n        loss = 1 - np.mean(batches_in)\n        return loss, noise\n\n    def _preds_in_top_k(self, target_class, prop_adv_):\n        # query limit setting\n        if self._k == self._num_class:\n            return True\n        # label only and partial information setting\n        eval_preds = self._model.predict(prop_adv_)\n        if not target_class in eval_preds.argsort()[:, -self._k:]:\n            return False\n        return True\n\n    def _get_grad(self, origin_image, eval_points, noise):\n        \"\"\"Calculate gradient.\"\"\"\n        losses = []\n        grads = []\n        for _ in range(self._samples_per_draw // self._batch_size):\n            if self._scene == 'Label_Only':\n                loss, np_noise = self._label_only_loss(origin_image, eval_points, noise)\n            elif self._scene == 'Partial_Info':\n                loss, np_noise = self._partial_info_loss(eval_points, noise)\n            else:\n                loss, np_noise = self._query_limit_loss(eval_points, noise)\n            # only support three channel images\n            losses_tiled = np.tile(np.reshape(loss, (-1, 1, 1, 1)), (1,) + origin_image.shape)\n            grad = np.mean(losses_tiled*np_noise, axis=0) / self._sigma\n\n            grads.append(grad)\n            losses.append(np.mean(loss))\n        return np.array(losses).mean(), np.mean(np.array(grads), axis=0)\n"
  },
  {
    "path": "mindarmour/adv_robustness/attacks/black/pointwise_attack.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nPointwise-Attack.\n\"\"\"\nimport numpy as np\n\nfrom mindarmour.utils._check_param import check_model, check_pair_numpy_param, \\\n    check_int_positive, check_param_type\nfrom mindarmour.utils.logger import LogUtil\nfrom ..attack import Attack\nfrom .black_model import BlackModel\nfrom .salt_and_pepper_attack import SaltAndPepperNoiseAttack\n\nLOGGER = LogUtil.get_instance()\nTAG = 'PointWiseAttack'\n\n\nclass PointWiseAttack(Attack):\n    \"\"\"\n    The Pointwise Attack make sure use the minimum number of changed pixels to generate adversarial sample for each\n    original sample.Those changed pixels will use binary search to make sure the distance between adversarial sample\n    and original sample is as close as possible.\n\n    References: `L. Schott, J. Rauber, M. Bethge, W. Brendel: \"Towards the\n    first adversarially robust neural network model on MNIST\", ICLR (2019)\n    <https://arxiv.org/abs/1805.09190>`_.\n\n    Args:\n        model (BlackModel): Target model.\n        max_iter (int): Max rounds of iteration to generate adversarial image. Default: ``1000``.\n        search_iter (int): Max rounds of binary search. Default: ``10``.\n        is_targeted (bool): If ``True``, targeted attack. If ``False``, untargeted attack. Default: ``False``.\n        init_attack (Union[Attack, None]): Attack used to find a starting point. Default: ``None``.\n        sparse (bool): If ``True``, input labels are sparse-encoded. If ``False``, input labels are one-hot-encoded.\n            Default: ``True``.\n\n    Examples:\n        >>> from mindspore import Tensor\n        >>> from mindarmour import BlackModel\n        >>> import mindspore.ops.operations as P\n        >>> from mindarmour.adv_robustness.attacks import PointWiseAttack\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...         self._reduce = P.ReduceSum()\n        ...         self._squeeze = P.Squeeze(1)\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         out = self._reduce(out, 2)\n        ...         out = self._squeeze(out)\n        ...         return out\n        >>> class ModelToBeAttacked(BlackModel):\n        ...     def __init__(self, network):\n        ...         super(ModelToBeAttacked, self).__init__()\n        ...         self._network = network\n        ...     def predict(self, inputs):\n        ...         result = self._network(Tensor(inputs.astype(np.float32)))\n        ...         return result.asnumpy()\n        >>> net = Net()\n        >>> np.random.seed(5)\n        >>> model = ModelToBeAttacked(net)\n        >>> attack = PointWiseAttack(model)\n        >>> x_test = np.asarray(np.random.random((1,1,32,32)), np.float32)\n        >>> y_test = np.random.randint(0, 3, size=1)\n        >>> is_adv_list, adv_list, query_times_each_adv = attack.generate(x_test, y_test)\n    \"\"\"\n\n    def __init__(self, model, max_iter=1000, search_iter=10, is_targeted=False, init_attack=None, sparse=True):\n        super(PointWiseAttack, self).__init__()\n        self._model = check_model('model', model, BlackModel)\n        self._max_iter = check_int_positive('max_iter', max_iter)\n        self._search_iter = check_int_positive('search_iter', search_iter)\n        self._is_targeted = check_param_type('is_targeted', is_targeted, bool)\n        if init_attack is None:\n            self._init_attack = SaltAndPepperNoiseAttack(model, is_targeted=self._is_targeted)\n        else:\n            self._init_attack = init_attack\n        self._sparse = check_param_type('sparse', sparse, bool)\n\n    def generate(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples based on input samples and targeted labels.\n\n        Args:\n            inputs (numpy.ndarray): Benign input samples used as references to create adversarial examples.\n            labels (numpy.ndarray): For targeted attack, labels are adversarial target labels.\n                For untargeted attack, labels are ground-truth labels.\n\n        Returns:\n            - numpy.ndarray, bool values for each attack result.\n\n            - numpy.ndarray, generated adversarial examples.\n\n            - numpy.ndarray, query times for each sample.\n        \"\"\"\n        arr_x, arr_y = check_pair_numpy_param('inputs', inputs, 'labels', labels)\n        if not self._sparse:\n            arr_y = np.argmax(arr_y, axis=1)\n        ini_bool, ini_advs, ini_count = self._initialize_starting_point(arr_x, arr_y)\n        is_adv_list = list()\n        adv_list = list()\n        query_times_each_adv = list()\n        for sample, sample_label, start_adv, ite_bool, ite_c in zip(arr_x, arr_y, ini_advs, ini_bool, ini_count):\n            if ite_bool:\n                LOGGER.info(TAG, 'Start optimizing.')\n                ori_label = np.argmax(self._model.predict(np.expand_dims(sample, axis=0))[0])\n                ini_label = np.argmax(self._model.predict(np.expand_dims(start_adv, axis=0))[0])\n                is_adv, adv_x, query_times = self._decision_optimize(sample, sample_label, start_adv)\n                adv_label = np.argmax(self._model.predict(np.expand_dims(adv_x, axis=0))[0])\n                LOGGER.info(TAG, 'before ini attack label is :{}'.format(ori_label))\n                LOGGER.info(TAG, 'after ini attack label is :{}'.format(ini_label))\n                LOGGER.info(TAG, 'INPUT optimize label is :{}'.format(sample_label))\n                LOGGER.info(TAG, 'after pointwise attack label is :{}'.format(adv_label))\n                is_adv_list.append(is_adv)\n                adv_list.append(adv_x)\n                query_times_each_adv.append(query_times + ite_c)\n            else:\n                LOGGER.info(TAG, 'Initial sample is not adversarial, pass.')\n                is_adv_list.append(False)\n                adv_list.append(start_adv)\n                query_times_each_adv.append(ite_c)\n        is_adv_list = np.array(is_adv_list)\n        adv_list = np.array(adv_list)\n        query_times_each_adv = np.array(query_times_each_adv)\n        LOGGER.info(TAG, 'ret list is: {}'.format(adv_list))\n        return is_adv_list, adv_list, query_times_each_adv\n\n    def _decision_optimize(self, unperturbed_img, input_label, perturbed_img):\n        \"\"\"\n        Make the perturbed samples more similar to unperturbed samples,\n        while maintaining the perturbed_label.\n\n        Args:\n            unperturbed_img (numpy.ndarray): Input sample as reference to create\n                adversarial example.\n            input_label (numpy.ndarray): Input label.\n            perturbed_img (numpy.ndarray): Starting point to optimize.\n\n        Returns:\n            numpy.ndarray, a generated adversarial example.\n\n        Raises:\n            ValueError: if input unperturbed and perturbed samples have different size.\n        \"\"\"\n        query_count = 0\n        img_size = unperturbed_img.size\n        img_shape = unperturbed_img.shape\n        perturbed_img = perturbed_img.reshape(-1)\n        unperturbed_img = unperturbed_img.reshape(-1)\n        recover = np.copy(perturbed_img)\n\n        if unperturbed_img.dtype != perturbed_img.dtype:\n            msg = 'unperturbed sample and perturbed sample must have the same' \\\n                  ' dtype, but got dtype of unperturbed is: {}, dtype of perturbed ' \\\n                  'is: {}'.format(unperturbed_img.dtype, perturbed_img.dtype)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        l2_dis = np.linalg.norm(perturbed_img - unperturbed_img)\n        LOGGER.info(TAG, 'Before optimize, the l2 distance between original ' \\\n                         'sample and adversarial sample is: {}'.format(l2_dis))\n        # recover pixel if image is adversarial\n        for _ in range(self._max_iter):\n            is_improve = False\n            # at the premise of adversarial feature, recover pixels\n            pixels_ind = np.arange(img_size)\n            mask = unperturbed_img != perturbed_img\n            np.random.shuffle(pixels_ind)\n            for ite_ind in pixels_ind:\n                if mask[ite_ind]:\n                    recover[ite_ind] = unperturbed_img[ite_ind]\n                    query_count += 1\n                    is_adv = self._model.is_adversarial(recover.reshape(img_shape), input_label, self._is_targeted)\n                    if is_adv:\n                        is_improve = True\n                        perturbed_img[ite_ind] = recover[ite_ind]\n                        break\n                    else:\n                        recover[ite_ind] = perturbed_img[ite_ind]\n            l2_dis = np.linalg.norm(perturbed_img - unperturbed_img)\n            if not is_improve or (np.square(l2_dis) / np.sqrt(len(pixels_ind)) <= self._get_threthod()):\n                break\n        LOGGER.debug(TAG, 'first round: Query count {}'.format(query_count))\n        LOGGER.debug(TAG, 'Starting binary searches.')\n        # tag the optimized pixels.\n        mask = unperturbed_img != perturbed_img\n        for _ in range(self._max_iter):\n            is_improve = False\n            pixels_ind = np.arange(img_size)\n            np.random.shuffle(pixels_ind)\n            for ite_ind in pixels_ind:\n                if not mask[ite_ind]:\n                    continue\n                recover[ite_ind] = unperturbed_img[ite_ind]\n                query_count += 1\n                is_adv = self._model.is_adversarial(recover.reshape(img_shape), input_label, self._is_targeted)\n                if is_adv:\n                    is_improve = True\n                    mask[ite_ind] = False\n                    perturbed_img[ite_ind] = recover[ite_ind]\n                    l2_dis = np.linalg.norm(perturbed_img - unperturbed_img)\n                    LOGGER.info(TAG, 'Reset {}th pixel value to original, l2 distance: {}.'.format(ite_ind, l2_dis))\n                    break\n                else:\n                    # use binary searches\n                    optimized_value, b_query = self._binary_search(perturbed_img,\n                                                                   unperturbed_img,\n                                                                   ite_ind,\n                                                                   input_label, img_shape)\n                    query_count += b_query\n                    if optimized_value != perturbed_img[ite_ind]:\n                        is_improve = True\n                        perturbed_img[ite_ind] = optimized_value\n                        l2_dis = np.linalg.norm(perturbed_img - unperturbed_img)\n                        LOGGER.info(TAG, 'Reset {}th pixel value to original, l2 distance: {}.'.format(ite_ind, l2_dis))\n                        break\n            l2_dis = np.linalg.norm(perturbed_img - unperturbed_img)\n            if not is_improve or (np.square(l2_dis) / np.sqrt(len(pixels_ind)) <= self._get_threthod()):\n                LOGGER.info(TAG, 'second optimized finish.')\n                break\n        LOGGER.info(TAG, 'Optimized finished, query count is {}'.format(query_count))\n        # this method use to optimized the adversarial sample\n        return True, perturbed_img.reshape(img_shape), query_count\n\n    def _binary_search(self, perturbed_img, unperturbed_img, ite_ind, input_label, img_shape):\n        \"\"\"\n        For original pixel of inputs, use binary search to get the nearest pixel\n        value with original value with adversarial feature.\n\n        Args:\n            perturbed_img (numpy.ndarray): Adversarial sample.\n            unperturbed_img (numpy.ndarray): Input sample.\n            ite_ind (int): The index of pixel in inputs.\n            input_label (numpy.ndarray): Input labels.\n            img_shape (tuple): Shape of the original sample.\n\n        Returns:\n            float, adversarial pixel value.\n        \"\"\"\n        query_count = 0\n        adv_value = perturbed_img[ite_ind]\n        non_adv_value = unperturbed_img[ite_ind]\n        for _ in range(self._search_iter):\n            next_value = (adv_value + non_adv_value) / 2\n            recover = np.copy(perturbed_img)\n            recover[ite_ind] = next_value\n            query_count += 1\n            is_adversarial = self._model.is_adversarial(\n                recover.reshape(img_shape), input_label, self._is_targeted)\n            if is_adversarial:\n                adv_value = next_value\n            else:\n                non_adv_value = next_value\n        return adv_value, query_count\n\n    def _initialize_starting_point(self, inputs, labels):\n        \"\"\"\n        Use init_attack to generate original adversarial inputs.\n\n        Args:\n            inputs (numpy.ndarray): Benign input sample used as references to create\n                adversarial examples.\n            labels (numpy.ndarray): If is targeted attack, labels is adversarial\n                labels, if is untargeted attack, labels is true labels.\n\n        Returns:\n            numpy.ndarray, adversarial image(s) generate by init_attack method.\n        \"\"\"\n        is_adv, start_adv, query_c = self._init_attack.generate(inputs, labels)\n        return is_adv, start_adv, query_c\n\n    def _get_threthod(self):\n        \"\"\"\n        Return a float number, when distance small than this number,\n        optimize will abort early.\n\n        Returns:\n            float, the optimized level, the smaller of number, the better\n            of adversarial sample.\n        \"\"\"\n        predefined_threshold = 0.01\n        return predefined_threshold\n"
  },
  {
    "path": "mindarmour/adv_robustness/attacks/black/pso_attack.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nPSO-Attack.\n\"\"\"\nimport numpy as np\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_model, check_pair_numpy_param, \\\n    check_numpy_param, check_value_positive, check_int_positive, \\\n    check_param_type, check_param_multi_types,\\\n    check_value_non_negative, check_detection_inputs\nfrom ..attack import Attack\nfrom .black_model import BlackModel\n\nLOGGER = LogUtil.get_instance()\nTAG = 'PSOAttack'\n\n\nclass PSOAttack(Attack):\n    \"\"\"\n    The PSO Attack represents the black-box attack based on Particle Swarm\n    Optimization algorithm, which belongs to differential evolution algorithms.\n    This attack was proposed by Rayan Mosli et al. (2019).\n\n    References: `Rayan Mosli, Matthew Wright, Bo Yuan, Yin Pan, \"They Might NOT\n    Be Giants: Crafting Black-Box Adversarial Examples with Fewer Queries\n    Using Particle Swarm Optimization\", arxiv: 1909.07490, 2019.\n    <https://arxiv.org/abs/1909.07490>`_\n\n    Args:\n        model (BlackModel): Target model.\n        step_size (Union[int, float]): Attack step size. Default: ``0.5``.\n        per_bounds (Union[int, float]): Relative variation range of perturbations. Default: ``0.6``.\n        c1 (Union[int, float]): Weight coefficient. Default: ``2``.\n        c2 (Union[int, float]): Weight coefficient. Default: ``2``.\n        c (Union[int, float]): Weight of perturbation loss. Default: ``2``.\n        pop_size (int): The number of particles, which should be greater\n            than zero. Default: ``6``.\n        t_max (int): The maximum round of iteration for each adversarial example,\n            which should be greater than zero. Default: ``1000``.\n        pm (Union[int, float]): The probability of mutations, which should be in the range of (0, 1).\n            Default: ``0.5``.\n        bounds (Union[list, tuple, None]): Upper and lower bounds of data. In form of (clip_min,\n            clip_max). Default: ``None``.\n        targeted (bool): If ``True``, turns on the targeted attack. If ``False``,\n            turns on untargeted attack. It should be noted that only untargeted attack\n            is supported for `model_type` is ``'detection'``, Default: ``False``.\n        sparse (bool): If ``True``, input labels are sparse-encoded. If ``False``,\n            input labels are one-hot-encoded. Default: ``True``.\n        model_type (str): The type of targeted model. ``'classification'`` and ``'detection'`` are supported now.\n            default: ``'classification'``.\n        reserve_ratio (Union[int, float]): The percentage of objects that can be detected after attacks,\n            specifically for `model_type` is ``'detection'``. Reserve_ratio should be in the range of (0, 1).\n            Default: ``0.3``.\n\n    Examples:\n        >>> import mindspore.nn as nn\n        >>> from mindspore import Tensor\n        >>> from mindspore.nn import Cell\n        >>> from mindarmour import BlackModel\n        >>> from mindarmour.adv_robustness.attacks import PSOAttack\n        >>> class ModelToBeAttacked(BlackModel):\n        ...     def __init__(self, network):\n        ...         super(ModelToBeAttacked, self).__init__()\n        ...         self._network = network\n        ...     def predict(self, inputs):\n        ...         if len(inputs.shape) == 1:\n        ...             inputs = np.expand_dims(inputs, axis=0)\n        ...         result = self._network(Tensor(inputs.astype(np.float32)))\n        ...         return result.asnumpy()\n        >>> class Net(Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._relu = nn.ReLU()\n        ...     def construct(self, inputs):\n        ...         out = self._relu(inputs)\n        ...         return out\n        >>> net = Net()\n        >>> model = ModelToBeAttacked(net)\n        >>> attack = PSOAttack(model, bounds=(0.0, 1.0), pm=0.5, sparse=False)\n        >>> batch_size = 6\n        >>> x_test = np.random.rand(batch_size, 10)\n        >>> y_test = np.random.randint(low=0, high=10, size=batch_size)\n        >>> y_test = np.eye(10)[y_test]\n        >>> y_test = y_test.astype(np.float32)\n        >>> _, adv_data, _ = attack.generate(x_test, y_test)\n    \"\"\"\n\n    def __init__(self, model, model_type='classification', targeted=False, reserve_ratio=0.3, sparse=True,\n                 step_size=0.5, per_bounds=0.6, c1=2.0, c2=2.0, c=2.0, pop_size=6, t_max=1000, pm=0.5, bounds=None):\n        super(PSOAttack, self).__init__()\n        self._model = check_model('model', model, BlackModel)\n        self._step_size = check_value_positive('step_size', step_size)\n        self._per_bounds = check_value_positive('per_bounds', per_bounds)\n        self._c1 = check_value_positive('c1', c1)\n        self._c2 = check_value_positive('c2', c2)\n        self._c = check_value_positive('c', c)\n        self._pop_size = check_int_positive('pop_size', pop_size)\n        self._pm = check_value_non_negative('pm', pm)\n        if self._pm > 1:\n            msg = \"pm should not be greater than 1.0, but got {}.\".format(self._pm)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        self._bounds = bounds\n        if self._bounds is not None:\n            self._bounds = check_param_multi_types('bounds', bounds, [list, tuple])\n            for b in self._bounds:\n                _ = check_param_multi_types('bound', b, [int, float])\n        self._targeted = check_param_type('targeted', targeted, bool)\n        self._t_max = check_int_positive('t_max', t_max)\n        self._sparse = check_param_type('sparse', sparse, bool)\n        self._model_type = check_param_type('model_type', model_type, str)\n        if self._model_type not in ('classification', 'detection'):\n            msg = \"Only 'classification' or 'detection' is supported now, but got {}.\".format(self._model_type)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        self._reserve_ratio = check_value_non_negative('reserve_ratio', reserve_ratio)\n        if self._reserve_ratio > 1:\n            msg = \"reserve_ratio should not be greater than 1.0, but got {}.\".format(self._reserve_ratio)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n    def _fitness(self, confi_ori, confi_adv, x_ori, x_adv):\n        \"\"\"\n        Calculate the fitness value for each particle.\n\n        Args:\n            confi_ori (float): Maximum confidence or target label confidence of\n                the original benign inputs' prediction confidences.\n            confi_adv (float): Maximum confidence or target label confidence of\n                the adversarial samples' prediction confidences.\n            x_ori (numpy.ndarray): Benign samples.\n            x_adv (numpy.ndarray): Adversarial samples.\n\n        Returns:\n            - float, fitness values of adversarial particles.\n\n            - int, query times after reduction.\n\n        Examples:\n            >>> fitness = self._fitness(2.4, 1.2, [0.2, 0.3, 0.1], [0.21,\n            >>> 0.34, 0.13])\n        \"\"\"\n        x_ori = check_numpy_param('x_ori', x_ori)\n        x_adv = check_numpy_param('x_adv', x_adv)\n        fit_value = abs(\n            confi_ori - confi_adv) - self._c / self._pop_size*np.linalg.norm(\n                (x_adv - x_ori).reshape(x_adv.shape[0], -1), axis=1)\n        if np.max(fit_value) < 0:\n            self._c /= 2\n        return fit_value\n\n    def _confidence_cla(self, inputs, labels):\n        \"\"\"\n        Calculate the prediction confidence of corresponding label or max confidence of inputs.\n\n        Args:\n            inputs (numpy.ndarray): Input samples.\n            labels (Union[numpy.int, numpy.int16, numpy.int32, numpy.int64]): Target labels.\n\n        Returns:\n            float, the prediction confidences of inputs.\n        \"\"\"\n        check_numpy_param('inputs', inputs)\n        check_param_multi_types('labels', labels, (np.int, np.int16, np.int32, np.int64))\n        confidences = self._model.predict(inputs)\n        if self._targeted:\n            confi_choose = confidences[:, labels]\n        else:\n            confi_choose = np.max(confidences, axis=1)\n        return confi_choose\n\n    def _mutation_op(self, cur_pop):\n        \"\"\"\n        Generate mutation samples.\n\n        Args:\n            cur_pop (numpy.ndarray): Inputs before mutation operation.\n\n        Returns:\n            numpy.ndarray, mutational inputs.\n        \"\"\"\n        LOGGER.info(TAG, 'Mutation happens...')\n        pixel_deep = self._bounds[1] - self._bounds[0]\n        cur_pop = check_numpy_param('cur_pop', cur_pop)\n        perturb_noise = (np.random.random(cur_pop.shape) - 0.5)*pixel_deep\n        mutated_pop = np.clip(perturb_noise*(np.random.random(cur_pop.shape) < self._pm) + cur_pop, self._bounds[0],\n                              self._bounds[1])\n        return mutated_pop\n\n    def _check_best_fitness(self, best_fitness, iters):\n        if best_fitness < -2:\n            LOGGER.debug(TAG, 'best fitness value is %s, which is too small. We recommend that you decrease '\n                              'the value of the initialization parameter c.', best_fitness)\n        if iters < 3 and best_fitness > 100:\n            LOGGER.debug(TAG, 'best fitness value is %s, which is too large. We recommend that you increase '\n                              'the value of the initialization parameter c.', best_fitness)\n\n    def _update_best_fit_position(self, fit_value, par_best_fit, par_best_poi, par, best_fitness, best_position):\n        for k in range(self._pop_size):\n            if fit_value[k] > par_best_fit[k]:\n                par_best_fit[k] = fit_value[k]\n                par_best_poi[k] = par[k]\n            if fit_value[k] > best_fitness:\n                best_fitness = fit_value[k]\n                best_position = par[k].copy()\n        return par_best_fit, par_best_poi, best_fitness, best_position\n\n    def _generate_classification(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples based on input data and\n        targeted labels (or ground_truth labels) for classification model.\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Input samples. The format of inputs should be numpy.ndarray.\n            labels (Union[numpy.ndarray, tuple]): Targeted labels or ground-truth labels. The format of labels should\n                be numpy.ndarray.\n\n        Returns:\n            - numpy.ndarray, bool values for each attack result.\n\n            - numpy.ndarray, generated adversarial examples.\n\n            - numpy.ndarray, query times for each sample.\n        \"\"\"\n        # inputs check\n        inputs, labels = check_pair_numpy_param('inputs', inputs,\n                                                'labels', labels)\n        if self._sparse:\n            if labels.size > 1:\n                label_squ = np.squeeze(labels)\n            else:\n                label_squ = labels\n            if len(label_squ.shape) >= 2 or label_squ.shape[0] != inputs.shape[0]:\n                msg = \"The parameter 'sparse' of PSOAttack is True, but the input labels is not sparse style and \" \\\n                      \"got its shape as {}.\".format(labels.shape)\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n        else:\n            labels = np.argmax(labels, axis=1)\n        images = inputs\n\n        # generate one adversarial each time\n        adv_list = []\n        success_list = []\n        query_times_list = []\n        for i in range(images.shape[0]):\n            is_success = False\n            q_times = 0\n            x_ori = images[i]\n            if not self._bounds:\n                self._bounds = [np.min(x_ori), np.max(x_ori)]\n            pixel_deep = self._bounds[1] - self._bounds[0]\n\n            q_times += 1\n\n            label_i = labels[i]\n            confi_ori = self._confidence_cla(x_ori, label_i)\n\n            # step1, initializing\n            # initial global optimum fitness value, cannot set to be -inf\n            best_fitness = -np.inf\n            # initial global optimum position\n            best_position = x_ori\n            x_copies = np.repeat(x_ori[np.newaxis, :], self._pop_size, axis=0)\n            cur_noise = np.clip(np.random.random(x_copies.shape)*pixel_deep,\n                                (0 - self._per_bounds)*(np.abs(x_copies) + 0.1),\n                                self._per_bounds*(np.abs(x_copies) + 0.1))\n\n            # initial advs\n            par = np.clip(x_copies + cur_noise, self._bounds[0], self._bounds[1])\n            # initial optimum positions for particles\n            par_best_poi = np.copy(par)\n            # initial optimum fitness values\n            par_best_fit = -np.inf*np.ones(self._pop_size)\n            # step2, optimization\n            # initial velocities for particles\n            v_particles = np.zeros(par.shape)\n            is_mutation = False\n            iters = 0\n            while iters < self._t_max:\n                last_best_fit = best_fitness\n                ran_1 = np.random.random(par.shape)\n                ran_2 = np.random.random(par.shape)\n                v_particles = self._step_size*(\n                    v_particles + self._c1*ran_1*(best_position - par)) \\\n                              + self._c2*ran_2*(par_best_poi - par)\n\n                par += v_particles\n\n                if iters > 6 and is_mutation:\n                    par = self._mutation_op(par)\n\n                par = np.clip(np.clip(par,\n                                      x_copies - (np.abs(x_copies) + 0.1*pixel_deep)*self._per_bounds,\n                                      x_copies + (np.abs(x_copies) + 0.1*pixel_deep)*self._per_bounds),\n                              self._bounds[0], self._bounds[1])\n\n\n                confi_adv = self._confidence_cla(par, label_i)\n\n                q_times += self._pop_size\n                fit_value = self._fitness(confi_ori, confi_adv, x_ori, par)\n                par_best_fit, par_best_poi, best_fitness, best_position = self._update_best_fit_position(fit_value,\n                                                                                                         par_best_fit,\n                                                                                                         par_best_poi,\n                                                                                                         par,\n                                                                                                         best_fitness,\n                                                                                                         best_position)\n                iters += 1\n                self._check_best_fitness(best_fitness, iters)\n\n                is_mutation = False\n                if (best_fitness - last_best_fit) < last_best_fit*0.05:\n                    is_mutation = True\n\n                q_times += 1\n\n                cur_pre = self._model.predict(best_position)\n                cur_label = np.argmax(cur_pre)\n                if (self._targeted and cur_label == label_i) or (not self._targeted and cur_label != label_i):\n                    is_success = True\n\n                if is_success:\n                    LOGGER.debug(TAG, 'successfully find one adversarial '\n                                      'sample and start Reduction process')\n                    # step3, reduction\n                    best_position, q_times = self._reduction(x_ori, q_times, label_i, best_position, self._model,\n                                                             targeted_attack=self._targeted)\n                    break\n\n            if not is_success:\n                LOGGER.debug(TAG,\n                             'fail to find adversarial sample, iteration '\n                             'times is: %d and query times is: %d',\n                             iters,\n                             q_times)\n            adv_list.append(best_position)\n            success_list.append(is_success)\n            query_times_list.append(q_times)\n            del x_copies, cur_noise, par, par_best_poi\n        return np.asarray(success_list), \\\n               np.asarray(adv_list), \\\n               np.asarray(query_times_list)\n\n\n    def _generate_detection(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples based on input data and\n        targeted labels (or ground_truth labels) for detection model.\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Input samples. The format of inputs can be (input1, input2, ...)\n                                                  or only one array.\n            labels (Union[numpy.ndarray, tuple]): Targeted labels or ground-truth labels.\n                                                  The format of labels should be (gt_boxes, gt_labels).\n\n        Returns:\n            - numpy.ndarray, bool values for each attack result.\n\n            - numpy.ndarray, generated adversarial examples.\n\n            - numpy.ndarray, query times for each sample.\n        \"\"\"\n        # inputs check\n        images, auxiliary_inputs, gt_boxes, gt_labels = check_detection_inputs(inputs, labels)\n\n        # generate one adversarial each time\n        adv_list = []\n        success_list = []\n        query_times_list = []\n        for i in range(images.shape[0]):\n            is_success = False\n            q_times = 0\n            x_ori = images[i]\n            if not self._bounds:\n                self._bounds = [np.min(x_ori), np.max(x_ori)]\n            pixel_deep = self._bounds[1] - self._bounds[0]\n\n            q_times += 1\n            auxiliary_input_i = tuple()\n            for item in auxiliary_inputs:\n                auxiliary_input_i += (np.expand_dims(item[i], axis=0),)\n            gt_boxes_i, gt_labels_i = np.expand_dims(gt_boxes[i], axis=0), np.expand_dims(gt_labels[i], axis=0)\n            inputs_i = (images[i],) + auxiliary_input_i\n            confi_ori, gt_object_num = self._detection_scores(inputs_i, gt_boxes_i, gt_labels_i, self._model)\n            LOGGER.info(TAG, 'The number of ground-truth objects is %s', gt_object_num[0])\n\n            # step1, initializing\n            # initial global optimum fitness value, cannot set to be -inf\n            best_fitness = -np.inf\n            # initial global optimum position\n            best_position = x_ori\n            x_copies = np.repeat(x_ori[np.newaxis, :], self._pop_size, axis=0)\n            cur_noise = np.clip(np.random.random(x_copies.shape)*pixel_deep,\n                                (0 - self._per_bounds)*(np.abs(x_copies) + 0.1),\n                                self._per_bounds*(np.abs(x_copies) + 0.1))\n\n            # initial advs\n            par = np.clip(x_copies + cur_noise, self._bounds[0], self._bounds[1])\n            # initial optimum positions for particles\n            par_best_poi = np.copy(par)\n            # initial optimum fitness values\n            par_best_fit = -np.inf*np.ones(self._pop_size)\n            # step2, optimization\n            # initial velocities for particles\n            v_particles = np.zeros(par.shape)\n            is_mutation = False\n            iters = 0\n            while iters < self._t_max:\n                last_best_fit = best_fitness\n                ran_1 = np.random.random(par.shape)\n                ran_2 = np.random.random(par.shape)\n                v_particles = self._step_size*(\n                    v_particles + self._c1*ran_1*(best_position - par)) \\\n                              + self._c2*ran_2*(par_best_poi - par)\n\n                par += v_particles\n\n                if iters > 6 and is_mutation:\n                    par = self._mutation_op(par)\n\n                par = np.clip(np.clip(par,\n                                      x_copies - (np.abs(x_copies) + 0.1*pixel_deep)*self._per_bounds,\n                                      x_copies + (np.abs(x_copies) + 0.1*pixel_deep)*self._per_bounds),\n                              self._bounds[0], self._bounds[1])\n\n                confi_adv, _ = self._detection_scores(\n                    (par,) + auxiliary_input_i, gt_boxes_i, gt_labels_i, self._model)\n                q_times += self._pop_size\n                fit_value = self._fitness(confi_ori, confi_adv, x_ori, par)\n                par_best_fit, par_best_poi, best_fitness, best_position = self._update_best_fit_position(fit_value,\n                                                                                                         par_best_fit,\n                                                                                                         par_best_poi,\n                                                                                                         par,\n                                                                                                         best_fitness,\n                                                                                                         best_position)\n                iters += 1\n                self._check_best_fitness(best_fitness, iters)\n\n                is_mutation = False\n                if (best_fitness - last_best_fit) < last_best_fit*0.05:\n                    is_mutation = True\n\n                q_times += 1\n\n                _, correct_nums_adv = self._detection_scores(\n                    (best_position,) + auxiliary_input_i, gt_boxes_i, gt_labels_i, self._model)\n                LOGGER.info(TAG, 'The number of correctly detected objects in adversarial image is %s',\n                            correct_nums_adv[0])\n                if correct_nums_adv <= int(gt_object_num*self._reserve_ratio):\n                    is_success = True\n\n                if is_success:\n                    LOGGER.debug(TAG, 'successfully find one adversarial '\n                                      'sample and start Reduction process')\n                    break\n            best_position, q_times = self._fast_reduction(x_ori, best_position, q_times,\n                                                          auxiliary_input_i, gt_boxes_i, gt_labels_i, self._model)\n            if not is_success:\n                LOGGER.debug(TAG,\n                             'fail to find adversarial sample, iteration '\n                             'times is: %d and query times is: %d',\n                             iters,\n                             q_times)\n            adv_list.append(best_position)\n            success_list.append(is_success)\n            query_times_list.append(q_times)\n            del x_copies, cur_noise, par, par_best_poi\n        return np.asarray(success_list), \\\n               np.asarray(adv_list), \\\n               np.asarray(query_times_list)\n\n    def generate(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples based on input data and\n        targeted labels (or ground_truth labels).\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Input samples. The format of inputs should be numpy.ndarray if\n                `model_type` is ``'classification'``. The format of inputs can be (input1, input2, ...) or only\n                one array if `model_type` is ``'detection'``.\n            labels (Union[numpy.ndarray, tuple]): Targeted labels or ground-truth labels. The format of labels should\n                be numpy.ndarray if `model_type` is ``'classification'``. The format of labels should be\n                (gt_boxes, gt_labels) if `model_type` is ``'detection'``.\n\n        Returns:\n            - numpy.ndarray, bool values for each attack result.\n\n            - numpy.ndarray, generated adversarial examples.\n\n            - numpy.ndarray, query times for each sample.\n        \"\"\"\n        # inputs check\n        if self._model_type == 'classification':\n            success_list, adv_data, query_time_list = self._generate_classification(inputs, labels)\n\n        elif self._model_type == 'detection':\n            success_list, adv_data, query_time_list = self._generate_detection(inputs, labels)\n\n        return success_list, adv_data, query_time_list\n"
  },
  {
    "path": "mindarmour/adv_robustness/attacks/black/salt_and_pepper_attack.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nSaltAndPepperNoise-Attack.\n\"\"\"\nimport time\nimport numpy as np\n\nfrom mindarmour.utils._check_param import check_model, check_pair_numpy_param, \\\n    check_param_type, check_int_positive, check_param_multi_types\nfrom mindarmour.utils.logger import LogUtil\nfrom ..attack import Attack\nfrom .black_model import BlackModel\n\nLOGGER = LogUtil.get_instance()\nTAG = 'SaltAndPepperNoise-Attack'\n\n\nclass SaltAndPepperNoiseAttack(Attack):\n    \"\"\"\n    Increases the amount of salt and pepper noise  to generate adversarial samples.\n\n    Args:\n        model (BlackModel): Target model.\n        bounds (tuple): Upper and lower bounds of data. In form of (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n        max_iter (int): Max iteration to generate an adversarial example. Default: ``100``.\n        is_targeted (bool): If ``True``, targeted attack. If ``False``, untargeted attack. Default: ``False``.\n        sparse (bool): If ``True``, input labels are sparse-encoded. If ``False``, input labels are one-hot-encoded.\n            Default: ``True``.\n\n    Examples:\n        >>> from mindspore import Tensor\n        >>> from mindarmour import BlackModel\n        >>> import mindspore.ops.operations as P\n        >>> from mindarmour.adv_robustness.attacks import SaltAndPepperNoiseAttack\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...         self._reduce = P.ReduceSum()\n        ...         self._squeeze = P.Squeeze(1)\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         out = self._reduce(out, 2)\n        ...         out = self._squeeze(out)\n        ...         return out\n        >>> class ModelToBeAttacked(BlackModel):\n        ...     def __init__(self, network):\n        ...         super(ModelToBeAttacked, self).__init__()\n        ...         self._network = network\n        ...     def predict(self, inputs):\n        ...         if len(inputs.shape) == 1:\n        ...             inputs = np.expand_dims(inputs, axis=0)\n        ...         result = self._network(Tensor(inputs.astype(np.float32)))\n        ...         return result.asnumpy()\n        >>> net = Net()\n        >>> model = ModelToBeAttacked(net)\n        >>> attack = SaltAndPepperNoiseAttack(model)\n        >>> x_test = np.asarray(np.random.random((1,1,32,32)), np.float32)\n        >>> y_test = np.random.randint(0, 3, size=1)\n        >>> _, adv_list, _ = attack.generate(x_test, y_test)\n    \"\"\"\n\n    def __init__(self, model, bounds=(0.0, 1.0), max_iter=100, is_targeted=False, sparse=True):\n        super(SaltAndPepperNoiseAttack, self).__init__()\n        self._model = check_model('model', model, BlackModel)\n        self._bounds = check_param_multi_types('bounds', bounds, [tuple, list])\n        for b in self._bounds:\n            _ = check_param_multi_types('bound', b, [int, float])\n        self._max_iter = check_int_positive('max_iter', max_iter)\n        self._is_targeted = check_param_type('is_targeted', is_targeted, bool)\n        self._sparse = check_param_type('sparse', sparse, bool)\n\n    def generate(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples based on input data and target labels.\n\n        Args:\n            inputs (numpy.ndarray): The original, unperturbed inputs.\n            labels (numpy.ndarray): The target labels.\n\n        Returns:\n            - numpy.ndarray, bool values for each attack result.\n\n            - numpy.ndarray, generated adversarial examples.\n\n            - numpy.ndarray, query times for each sample.\n        \"\"\"\n        arr_x, arr_y = check_pair_numpy_param('inputs', inputs, 'labels', labels)\n        if not self._sparse:\n            arr_y = np.argmax(arr_y, axis=1)\n\n        is_adv_list = list()\n        adv_list = list()\n        query_times_each_adv = list()\n        for sample, label in zip(arr_x, arr_y):\n            start_t = time.time()\n            is_adv, perturbed, query_times = self._generate_one(sample, label)\n            is_adv_list.append(is_adv)\n            adv_list.append(perturbed)\n            query_times_each_adv.append(query_times)\n            LOGGER.info(TAG, 'Finished one sample, adversarial is {}, cost time {:.2}s'.format(is_adv,\n                                                                                               time.time() - start_t))\n        is_adv_list = np.array(is_adv_list)\n        adv_list = np.array(adv_list)\n        query_times_each_adv = np.array(query_times_each_adv)\n        return is_adv_list, adv_list, query_times_each_adv\n\n    def _generate_one(self, one_input, label, epsilons=10):\n        \"\"\"\n        Increases the amount of salt and pepper noise to generate adversarial samples.\n\n        Args:\n            one_input (numpy.ndarray): The original, unperturbed input.\n            label (numpy.ndarray): The target label.\n            epsilons (int) : Number of steps to try probability between 0 and 1. Default: 10\n\n        Returns:\n            - numpy.ndarray, bool values for result.\n\n            - numpy.ndarray, adversarial example.\n\n            - numpy.ndarray, query times for this sample.\n\n        Examples:\n            >>> one_adv = self._generate_one(input, label)\n        \"\"\"\n        # use binary search to get epsilons\n        low_ = 0.0\n        high_ = 1.0\n        query_count = 0\n        input_shape = one_input.shape\n        one_input = one_input.reshape(-1)\n        best_adv = np.copy(one_input)\n        best_eps = high_\n        find_adv = False\n        for _ in range(self._max_iter):\n            min_eps = low_\n            max_eps = (low_ + high_) / 2\n            for _ in range(epsilons):\n                adv = np.copy(one_input)\n                noise = np.random.uniform(low=low_, high=high_, size=one_input.size)\n                eps = (min_eps + max_eps) / 2\n                # add salt\n                adv[noise < eps] = self._bounds[0]\n                # add pepper\n                adv[noise >= (high_ - eps)] = self._bounds[1]\n                query_count += 1\n                ite_bool = self._model.is_adversarial(adv.reshape(input_shape), label, is_targeted=self._is_targeted)\n                if ite_bool:\n                    find_adv = True\n                    if best_eps > eps:\n                        best_adv = adv\n                        best_eps = eps\n                    max_eps = eps\n                    LOGGER.debug(TAG, 'Attack succeed, epsilon is {}'.format(eps))\n                else:\n                    min_eps = eps\n            if find_adv:\n                break\n        return find_adv, best_adv.reshape(input_shape), query_count\n"
  },
  {
    "path": "mindarmour/adv_robustness/attacks/carlini_wagner.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nCarlini-wagner Attack.\n\"\"\"\nimport numpy as np\n\nfrom mindspore import Tensor\nfrom mindspore.nn import Cell\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_numpy_param, check_model, \\\n    check_pair_numpy_param, check_int_positive, check_param_type, \\\n    check_param_multi_types, check_value_positive, check_equal_shape\nfrom mindarmour.utils.util import GradWrap, jacobian_matrix\nfrom .attack import Attack\n\nLOGGER = LogUtil.get_instance()\nTAG = 'CW'\n\n\ndef _best_logits_of_other_class(logits, target_class, value=1):\n    \"\"\"\n    Choose the index of the largest logits exclude target class.\n\n    Args:\n        logits (numpy.ndarray): Predict logits of samples.\n        target_class (numpy.ndarray): Target labels.\n        value (float): Maximum value of output logits. Default: ``1``.\n\n    Returns:\n        numpy.ndarray, the index of the largest logits exclude the target\n        class.\n\n    Examples:\n        >>> other_class = _best_logits_of_other_class([[0.2, 0.3, 0.5],\n        >>> [0.3, 0.4, 0.3]], [2, 1])\n    \"\"\"\n    LOGGER.debug(TAG, \"enter the func _best_logits_of_other_class.\")\n    logits, target_class = check_pair_numpy_param('logits', logits,\n                                                  'target_class', target_class)\n    res = np.zeros_like(logits)\n    for i in range(logits.shape[0]):\n        res[i][target_class[i]] = value\n    return np.argmax(logits - res, axis=1)\n\n\nclass CarliniWagnerL2Attack(Attack):\n    \"\"\"\n    The Carlini & Wagner attack using L2 norm generates the adversarial examples\n    by utilizing two separate losses: an adversarial loss to make the generated example\n    actually adversarial, and a distance loss to control the quality of the adversarial example.\n\n    References: `Nicholas Carlini, David Wagner: \"Towards Evaluating\n    the Robustness of Neural Networks\" <https://arxiv.org/abs/1608.04644>`_\n\n    Args:\n        network (Cell): Target model.\n        num_classes (int): Number of labels of model output, which should be\n            greater than zero.\n        box_min (float): Lower bound of input of the target model. Default: ``0``.\n        box_max (float): Upper bound of input of the target model. Default: ``1.0``.\n        bin_search_steps (int): The number of steps for the binary search\n            used to find the optimal trade-off constant between distance\n            and confidence. Default: ``5``.\n        max_iterations (int): The maximum number of iterations, which should be\n            greater than zero. Default: ``1000``.\n        confidence (float): Confidence of the output of adversarial examples.\n            Default: ``0``.\n        learning_rate (float): The learning rate for the attack algorithm.\n            Default: ``5e-3``.\n        initial_const (float): The initial trade-off constant to use to balance\n            the relative importance of perturbation norm and confidence\n            difference. Default: ``1e-2``.\n        abort_early_check_ratio (float): Check loss progress every ratio of\n            all iteration. Default: ``5e-2``.\n        targeted (bool): If ``True``, targeted attack. If ``False``, untargeted attack.\n            Default: ``False``.\n        fast (bool): If ``True``, return the first found adversarial example.\n            If ``False``, return the adversarial samples with smaller\n            perturbations. Default: ``True``.\n        abort_early (bool): If ``True``, Adam will be aborted if the loss hasn't\n            decreased for some time. If ``False``, Adam will continue work until the\n            max iterations is arrived. Default: ``True``.\n        sparse (bool): If ``True``, input labels are sparse-coded. If ``False``,\n            input labels are onehot-coded. Default: ``True``.\n\n    Examples:\n        >>> import mindspore.ops.operations as P\n        >>> from mindarmour.adv_robustness.attacks import CarliniWagnerL2Attack\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         return out\n        >>> net = Net()\n        >>> input_np = np.array([[0.1, 0.2, 0.7, 0.5, 0.4]]).astype(np.float32)\n        >>> num_classes = input_np.shape[1]\n        >>> label_np = np.array([3]).astype(np.int64)\n        >>> attack = CarliniWagnerL2Attack(net, num_classes, targeted=False)\n        >>> adv_data = attack.generate(input_np, label_np)\n    \"\"\"\n\n    def __init__(self, network, num_classes, box_min=0.0, box_max=1.0,\n                 bin_search_steps=5, max_iterations=1000, confidence=0,\n                 learning_rate=5e-3, initial_const=1e-2,\n                 abort_early_check_ratio=5e-2, targeted=False,\n                 fast=True, abort_early=True, sparse=True):\n        LOGGER.info(TAG, \"init CW object.\")\n        super(CarliniWagnerL2Attack, self).__init__()\n        self._network = check_model('network', network, Cell)\n        self._network.set_grad(True)\n        self._num_classes = check_int_positive('num_classes', num_classes)\n        self._min = check_param_type('box_min', box_min, float)\n        self._max = check_param_type('box_max', box_max, float)\n        self._bin_search_steps = check_int_positive('search_steps', bin_search_steps)\n        self._max_iterations = check_int_positive('max_iterations', max_iterations)\n        self._confidence = check_param_multi_types('confidence', confidence, [int, float])\n        self._learning_rate = check_value_positive('learning_rate', learning_rate)\n        self._initial_const = check_value_positive('initial_const', initial_const)\n        self._abort_early = check_param_type('abort_early', abort_early, bool)\n        self._fast = check_param_type('fast', fast, bool)\n        self._abort_early_check_ratio = check_value_positive('abort_early_check_ratio', abort_early_check_ratio)\n        self._targeted = check_param_type('targeted', targeted, bool)\n        self._net_grad = GradWrap(self._network)\n        self._sparse = check_param_type('sparse', sparse, bool)\n        self._dtype = None\n\n    def _loss_function(self, logits, new_x, org_x, org_or_target_class,\n                       constant, confidence):\n        \"\"\"\n        Calculate the value of loss function and gradients of loss w.r.t inputs.\n\n        Args:\n            logits (numpy.ndarray): The output of network before softmax.\n            new_x (numpy.ndarray): Adversarial examples.\n            org_x (numpy.ndarray): Original benign input samples.\n            org_or_target_class (numpy.ndarray): Original/target labels.\n            constant (float): A trade-off constant to use to balance loss and perturbation norm.\n            confidence (float): Confidence level of the output of adversarial examples.\n\n        Returns:\n            numpy.ndarray, norm of perturbation, sum of the loss and the\n            norm, and gradients of the sum w.r.t inputs.\n\n        Raises:\n            ValueError: If loss is less than 0.\n\n        Examples:\n            >>> L2_loss, total_loss, dldx = self._loss_function([0.2 , 0.3,\n            >>> 0.5], [0.1, 0.2, 0.2, 0.4], [0.12, 0.2, 0.25, 0.4], [1], 2, 0)\n        \"\"\"\n        LOGGER.debug(TAG, \"enter the func _loss_function.\")\n\n        logits = check_numpy_param('logits', logits)\n        org_x = check_numpy_param('org_x', org_x)\n        new_x, org_or_target_class = check_pair_numpy_param('new_x',\n                                                            new_x,\n                                                            'org_or_target_class',\n                                                            org_or_target_class)\n\n        new_x, org_x = check_equal_shape('new_x', new_x, 'org_x', org_x)\n\n        other_class_index = _best_logits_of_other_class(\n            logits, org_or_target_class, value=np.inf)\n        loss1 = np.sum((new_x - org_x) ** 2,\n                       axis=tuple(range(len(new_x.shape))[1:]))\n        loss2 = np.zeros_like(loss1, dtype=self._dtype)\n        loss2_grade = np.zeros_like(new_x, dtype=self._dtype)\n        jaco_grad = jacobian_matrix(self._net_grad, new_x, self._num_classes)\n        if self._targeted:\n            for i in range(org_or_target_class.shape[0]):\n                loss2[i] = max(0, logits[i][other_class_index[i]]\n                               - logits[i][org_or_target_class[i]]\n                               + confidence)\n                loss2_grade[i] = constant[i] * (jaco_grad[other_class_index[\n                    i]][i] - jaco_grad[org_or_target_class[i]][i])\n        else:\n            for i in range(org_or_target_class.shape[0]):\n                loss2[i] = max(0, logits[i][org_or_target_class[i]]\n                               - logits[i][other_class_index[i]] + confidence)\n                loss2_grade[i] = constant[i] * (jaco_grad[org_or_target_class[\n                    i]][i] - jaco_grad[other_class_index[i]][i])\n        total_loss = loss1 + constant * loss2\n        loss1_grade = 2 * (new_x - org_x)\n        for i in range(org_or_target_class.shape[0]):\n            if loss2[i] < 0:\n                msg = 'loss value should greater than or equal to 0, ' \\\n                      'but got loss2 {}'.format(loss2[i])\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n            if loss2[i] == 0:\n                loss2_grade[i, ...] = 0\n        total_loss_grade = loss1_grade + loss2_grade\n        return loss1, total_loss, total_loss_grade\n\n    def _to_attack_space(self, inputs):\n        \"\"\"\n        Transform input data into attack space.\n\n        Args:\n            inputs (numpy.ndarray): Input data.\n\n        Returns:\n            numpy.ndarray, transformed data which belongs to attack space.\n\n        Examples:\n            >>> x_att = self._to_attack_space([0.2, 0.3, 0.3])\n        \"\"\"\n        LOGGER.debug(TAG, \"enter the func _to_attack_space.\")\n\n        inputs = check_numpy_param('inputs', inputs)\n        mean = (self._min + self._max) / 2\n        diff = (self._max - self._min) / 2\n        inputs = (inputs - mean) / diff\n        inputs = inputs * 0.999999\n        return np.arctanh(inputs)\n\n    def _to_model_space(self, inputs):\n        \"\"\"\n        Transform input data into model space.\n\n        Args:\n            inputs (numpy.ndarray): Input data.\n\n        Returns:\n            numpy.ndarray, transformed data which belongs to model space\n            and the gradient of x_model w.r.t. x_att.\n\n        Examples:\n            >>> x_att = self._to_model_space([10, 21, 9])\n        \"\"\"\n        LOGGER.debug(TAG, \"enter the func _to_model_space.\")\n\n        inputs = check_numpy_param('inputs', inputs)\n        inputs = np.tanh(inputs)\n        the_grad = 1 - np.square(inputs)\n        mean = (self._min + self._max) / 2\n        diff = (self._max - self._min) / 2\n        inputs = inputs * diff + mean\n        the_grad = the_grad * diff\n        return inputs, the_grad\n\n    def _check_success(self, logits, labels):\n        \"\"\" check if attack success (include all examples)\"\"\"\n        if self._targeted:\n            is_adv = (np.argmax(logits, axis=1) == labels)\n        else:\n            is_adv = (np.argmax(logits, axis=1) != labels)\n        return is_adv\n\n    def generate(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples based on input data and targeted labels.\n\n        Args:\n            inputs (numpy.ndarray): Input samples.\n            labels (numpy.ndarray): The ground truth label of input samples\n                or target labels.\n\n        Returns:\n            numpy.ndarray, generated adversarial examples.\n        \"\"\"\n\n        LOGGER.debug(TAG, \"enter the func generate.\")\n        inputs, labels = check_pair_numpy_param('inputs', inputs,\n                                                'labels', labels)\n        if not self._sparse:\n            labels = np.argmax(labels, axis=1)\n        self._dtype = inputs.dtype\n        att_original = self._to_attack_space(inputs)\n        reconstructed_original, _ = self._to_model_space(att_original)\n\n        # find an adversarial sample\n        const = np.ones_like(labels, dtype=self._dtype) * self._initial_const\n        lower_bound = np.zeros_like(labels, dtype=self._dtype)\n        upper_bound = np.ones_like(labels, dtype=self._dtype) * np.inf\n        adversarial_res = inputs.copy()\n        adversarial_loss = np.ones_like(labels, dtype=self._dtype) * np.inf\n        samples_num = labels.shape[0]\n        adv_flag = np.zeros_like(labels)\n        for binary_search_step in range(self._bin_search_steps):\n            if (binary_search_step == self._bin_search_steps - 1) and (self._bin_search_steps >= 10):\n                const = min(1e10, upper_bound)\n            LOGGER.debug(TAG, 'starting optimization with const = %s', str(const))\n\n            att_perturbation = np.zeros_like(att_original, dtype=self._dtype)\n            loss_at_previous_check = np.ones_like(labels, dtype=self._dtype) * np.inf\n\n            # create a new optimizer to minimize the perturbation\n            optimizer = _AdamOptimizer(att_perturbation.shape)\n\n            for iteration in range(self._max_iterations):\n                x_input, dxdp = self._to_model_space(att_original + att_perturbation)\n                logits = self._network(Tensor(x_input)).asnumpy()\n\n                current_l2_loss, current_loss, dldx = self._loss_function(logits, x_input, reconstructed_original,\n                                                                          labels, const, self._confidence)\n\n                is_adv = self._check_success(logits, labels)\n\n                for i in range(samples_num):\n                    if is_adv[i]:\n                        adv_flag[i] = True\n                        if current_l2_loss[i] < adversarial_loss[i]:\n                            adversarial_res[i] = x_input[i]\n                            adversarial_loss[i] = current_l2_loss[i]\n\n                if np.all(adv_flag):\n                    if self._fast:\n                        LOGGER.debug(TAG, \"succeed find adversarial examples.\")\n                        msg = 'iteration: {}, logits_att: {}, loss: {}, l2_dist: {}' \\\n                            .format(iteration, np.argmax(logits, axis=1), current_loss, current_l2_loss)\n                        LOGGER.debug(TAG, msg)\n                        return adversarial_res\n\n                dldx, inputs = check_equal_shape('dldx', dldx, 'inputs', inputs)\n\n                gradient = dldx * dxdp\n                att_perturbation += optimizer(gradient, self._learning_rate)\n\n                # check if should stop iteration early\n                flag = True\n                iter_check = iteration % (np.ceil(\n                    self._max_iterations * self._abort_early_check_ratio))\n                if self._abort_early and iter_check == 0:\n                    # check progress\n                    for i in range(inputs.shape[0]):\n                        if current_loss[i] <= .9999 * loss_at_previous_check[i]:\n                            flag = False\n                    # stop Adam if all samples has no progress\n                    if flag:\n                        LOGGER.debug(TAG, 'step:%d, no progress yet, stop iteration', binary_search_step)\n                        break\n                    loss_at_previous_check = current_loss\n            upper_bound, lower_bound, const = self._update_bounds(samples_num, adv_flag, const, upper_bound,\n                                                                  lower_bound)\n\n        return adversarial_res\n\n    def _update_bounds(self, samples_num, adv_flag, const, upper_bound, lower_bound):\n        \"\"\"update bound based on search result\"\"\"\n        for i in range(samples_num):\n            if adv_flag[i]:\n                LOGGER.debug(TAG, 'example %d, found adversarial with const=%f', i, const[i])\n                upper_bound[i] = const[i]\n            else:\n                LOGGER.debug(TAG, 'example %d, failed to find adversarial with const=%f', i, const[i])\n                lower_bound[i] = const[i]\n\n            if upper_bound[i] == np.inf:\n                const[i] *= 10\n            else:\n                const[i] = (lower_bound[i] + upper_bound[i]) / 2\n        return upper_bound, lower_bound, const\n\n\nclass _AdamOptimizer:\n    \"\"\"\n    AdamOptimizer is used to calculate the optimum attack step.\n\n    Args:\n        shape (tuple): The shape of perturbations.\n\n    Examples:\n        >>> optimizer = _AdamOptimizer(att_perturbation.shape)\n    \"\"\"\n\n    def __init__(self, shape):\n        self._m = np.zeros(shape)\n        self._v = np.zeros(shape)\n        self._t = 0\n\n    def __call__(self, gradient, learning_rate=0.001,\n                 beta1=0.9, beta2=0.999, epsilon=1e-8):\n        \"\"\"\n        Calculate the optimum perturbation for each iteration.\n\n        Args:\n            gradient (numpy.ndarray): The gradient of the loss w.r.t. to the\n                variable.\n            learning_rate (float): The learning rate in the current iteration.\n                Default: 0.001.\n            beta1 (float): Decay rate for calculating the exponentially\n                decaying average of past gradients. Default: 0.9.\n            beta2 (float): Decay rate for calculating the exponentially\n                decaying average of past squared gradients. Default: 0.999.\n            epsilon (float): Small value to avoid division by zero.\n                Default: 1e-8.\n\n        Returns:\n            numpy.ndarray, perturbations.\n\n        Examples:\n            >>> perturbs = optimizer([0.2, 0.1, 0.15], 0.005)\n        \"\"\"\n        gradient = check_numpy_param('gradient', gradient)\n        self._t += 1\n        self._m = beta1 * self._m + (1 - beta1) * gradient\n        self._v = beta2 * self._v + (1 - beta2) * gradient ** 2\n        alpha = learning_rate * np.sqrt(1 - beta2 ** self._t) / (1 - beta1 ** self._t)\n        pertur = -alpha * self._m / (np.sqrt(self._v) + epsilon)\n        return pertur\n"
  },
  {
    "path": "mindarmour/adv_robustness/attacks/deep_fool.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nDeepFool Attack.\n\"\"\"\nimport numpy as np\n\nfrom mindspore import Tensor\nfrom mindspore.nn import Cell\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils.util import GradWrap, jacobian_matrix, \\\n    jacobian_matrix_for_detection, calculate_iou, to_tensor_tuple\nfrom mindarmour.utils._check_param import check_pair_numpy_param, check_model, \\\n    check_value_positive, check_int_positive, check_norm_level, \\\n    check_param_multi_types, check_param_type, check_value_non_negative\nfrom .attack import Attack\n\nLOGGER = LogUtil.get_instance()\nTAG = 'DeepFool'\n\n\nclass _GetLogits(Cell):\n    def __init__(self, network):\n        super(_GetLogits, self).__init__()\n        self._network = network\n\n    def construct(self, *inputs):\n        _, pre_logits = self._network(*inputs)\n        return pre_logits\n\n\ndef _deepfool_detection_scores(inputs, gt_boxes, gt_labels, network):\n    \"\"\"\n    Evaluate the detection result of inputs, specially for object detection models.\n\n    Args:\n        inputs (numpy.ndarray): Input samples.\n        gt_boxes (numpy.ndarray): Ground-truth boxes of inputs.\n        gt_labels (numpy.ndarray): Ground-truth labels of inputs.\n        model (BlackModel): Target model.\n\n    Returns:\n        - numpy.ndarray, detection scores of inputs.\n\n        - numpy.ndarray, the number of objects that are correctly detected.\n    \"\"\"\n    network = check_param_type('network', network, Cell)\n    inputs_tensor = to_tensor_tuple(inputs)\n    box_and_confi, pred_logits = network(*inputs_tensor)\n    box_and_confi, pred_logits = box_and_confi.asnumpy(), pred_logits.asnumpy()\n    pred_labels = np.argmax(pred_logits, axis=2)\n    det_scores = []\n    correct_labels_num = []\n    gt_boxes_num = gt_boxes.shape[1]\n    iou_thres = 0.5\n    for idx, (boxes, labels) in enumerate(zip(box_and_confi, pred_labels)):\n        score = 0\n        box_num = boxes.shape[0]\n        gt_boxes_idx = gt_boxes[idx]\n        gt_labels_idx = gt_labels[idx]\n        correct_label_flag = np.zeros(gt_labels_idx.shape)\n        for i in range(box_num):\n            pred_box = boxes[i]\n            max_iou_confi = 0\n            for j in range(gt_boxes_num):\n                iou = calculate_iou(pred_box[:4], gt_boxes_idx[j][:4])\n                if labels[i] == gt_labels_idx[j] and iou > iou_thres:\n                    max_iou_confi = max(max_iou_confi, pred_box[-1] + iou)\n                    correct_label_flag[j] = 1\n            score += max_iou_confi\n        det_scores.append(score)\n        correct_labels_num.append(np.sum(correct_label_flag))\n    return np.array(det_scores), np.array(correct_labels_num)\n\n\ndef _is_success(inputs, gt_boxes, gt_labels, network, gt_object_nums, reserve_ratio):\n    _, correct_nums_adv = _deepfool_detection_scores(inputs, gt_boxes, gt_labels, network)\n    return np.all(correct_nums_adv <= (gt_object_nums*reserve_ratio).astype(np.int32))\n\n\nclass DeepFool(Attack):\n    \"\"\"\n    DeepFool is an untargeted & iterative attack achieved by moving the benign\n    sample to the nearest classification boundary and crossing the boundary.\n\n    Reference: `DeepFool: a simple and accurate method to fool deep neural\n    networks <https://arxiv.org/abs/1511.04599>`_.\n\n    Args:\n        network (Cell): Target model.\n        num_classes (int): Number of labels of model output, which should be\n            greater than zero.\n        model_type (str): Tye type of targeted model. ``'classification'`` and ``'detection'`` are supported now.\n            Default: ``'classification'``.\n        reserve_ratio (Union[int, float]): The percentage of objects that can be detected after attaks,\n            specifically for `model_type` is ``'detection'``. Reserve_ratio should be in the range of (0, 1).\n            Default: ``0.3``.\n        max_iters (int): Max iterations, which should be\n            greater than zero. Default: ``50``.\n        overshoot (float): Overshoot parameter. Default: ``0.02``.\n        norm_level (Union[int, str, numpy.inf]): Order of the vector norm. Possible values: np.inf\n            or 2. Default: ``2``.\n        bounds (Union[tuple, list]): Upper and lower bounds of data range. In form of (clip_min,\n            clip_max). Default: ``None``.\n        sparse (bool): If ``True``, input labels are sparse-coded. If ``False``,\n            input labels are onehot-coded. Default: ``True``.\n\n    Examples:\n        >>> import mindspore.ops.operations as P\n        >>> from mindspore import Tensor\n        >>> from mindarmour.adv_robustness.attacks import DeepFool\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         return out\n        >>> net = Net()\n        >>> input_shape = (1, 5)\n        >>> _, classes = input_shape\n        >>> attack = DeepFool(net, classes, max_iters=10, norm_level=2,\n        ...                   bounds=(0.0, 1.0))\n        >>> input_np = np.array([[0.1, 0.2, 0.7, 0.5, 0.4]]).astype(np.float32)\n        >>> input_me = Tensor(input_np)\n        >>> true_labels = np.argmax(net(input_me).asnumpy(), axis=1)\n        >>> advs = attack.generate(input_np, true_labels)\n    \"\"\"\n\n    def __init__(self, network, num_classes, model_type='classification',\n                 reserve_ratio=0.3, max_iters=50, overshoot=0.02, norm_level=2, bounds=None, sparse=True):\n        super(DeepFool, self).__init__()\n        self._network = check_model('network', network, Cell)\n        self._max_iters = check_int_positive('max_iters', max_iters)\n        self._overshoot = check_value_positive('overshoot', overshoot)\n        self._norm_level = check_norm_level(norm_level)\n        self._num_classes = check_int_positive('num_classes', num_classes)\n        self._net_grad = GradWrap(self._network)\n        self._bounds = bounds\n        if self._bounds is not None:\n            self._bounds = check_param_multi_types('bounds', bounds, [list, tuple])\n            for b in self._bounds:\n                _ = check_param_multi_types('bound', b, [int, float])\n        self._sparse = check_param_type('sparse', sparse, bool)\n        self._model_type = check_param_type('model_type', model_type, str)\n        if self._model_type not in ('classification', 'detection'):\n            msg = \"Only 'classification' or 'detection' is supported now, but got {}.\".format(self._model_type)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        self._reserve_ratio = check_value_non_negative('reserve_ratio', reserve_ratio)\n        if self._reserve_ratio > 1:\n            msg = 'reserve_ratio should be less than 1.0, but got {}.'.format(self._reserve_ratio)\n            LOGGER.error(TAG, msg)\n            raise ValueError(TAG, msg)\n\n    def generate(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples based on input samples and original labels.\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Input samples. The format of inputs should be numpy.ndarray if\n                `model_type` is ``'classification'``. The format of inputs can be (input1, input2, ...) or only\n                one array if `model_type` is ``'detection'``.\n            labels (Union[numpy.ndarray, tuple]): Targeted labels or ground-truth labels. The format of labels should\n                be numpy.ndarray if `model_type` is ``'classification'``. The format of labels should be\n                (gt_boxes, gt_labels) if `model_type` is ``'detection'``.\n\n        Returns:\n            numpy.ndarray, adversarial examples.\n\n        Raises:\n            NotImplementedError: If `norm_level` is not ``2``, ``np.inf``, ``'2'`` or ``'inf'``.\n        \"\"\"\n\n        if self._model_type == 'detection':\n            return self._generate_detection(inputs, labels)\n        if self._model_type == 'classification':\n            return self._generate_classification(inputs, labels)\n        return None\n\n    def _update_image(self, x_origin, r_tot):\n        \"\"\"update image based on bounds\"\"\"\n        if self._bounds is not None:\n            clip_min, clip_max = self._bounds\n            images = x_origin + (1 + self._overshoot)*r_tot*(clip_max-clip_min)\n            images = np.clip(images, clip_min, clip_max)\n        else:\n            images = x_origin + (1 + self._overshoot)*r_tot\n        return images\n\n    def _generate_detection(self, inputs, labels):\n        \"\"\"Generate adversarial examples in detection scenario\"\"\"\n        images, auxiliary_inputs = inputs[0], inputs[1:]\n        gt_boxes, gt_labels = labels\n        _, gt_object_nums = _deepfool_detection_scores(inputs, gt_boxes, gt_labels, self._network)\n        if not self._sparse:\n            gt_labels = np.argmax(gt_labels, axis=2)\n        origin_labels = np.zeros(gt_labels.shape[0])\n        for i in range(gt_labels.shape[0]):\n            origin_labels[i] = np.argmax(np.bincount(gt_labels[i]))\n        images_dtype = images.dtype\n        iteration = 0\n        num_boxes = gt_labels.shape[1]\n        merge_net = _GetLogits(self._network)\n        detection_net_grad = GradWrap(merge_net)\n        weight = np.squeeze(np.zeros(images.shape[1:]))\n        r_tot = np.zeros(images.shape)\n        x_origin = images\n        while not _is_success((images,) + auxiliary_inputs, gt_boxes, gt_labels, self._network, gt_object_nums, \\\n                         self._reserve_ratio) and iteration < self._max_iters:\n            preds_logits = merge_net(*to_tensor_tuple(images), *to_tensor_tuple(auxiliary_inputs)).asnumpy()\n            grads = jacobian_matrix_for_detection(detection_net_grad, (images,) + auxiliary_inputs,\n                                                  num_boxes, self._num_classes)\n            for idx in range(images.shape[0]):\n                diff_w = np.inf\n                label = int(origin_labels[idx])\n                auxiliary_input_i = tuple()\n                for item in auxiliary_inputs:\n                    auxiliary_input_i += (np.expand_dims(item[idx], axis=0),)\n                gt_boxes_i = np.expand_dims(gt_boxes[idx], axis=0)\n                gt_labels_i = np.expand_dims(gt_labels[idx], axis=0)\n                inputs_i = (np.expand_dims(images[idx], axis=0),) + auxiliary_input_i\n                if _is_success(inputs_i, gt_boxes_i, gt_labels_i,\n                               self._network, gt_object_nums[idx], self._reserve_ratio):\n                    continue\n                for k in range(self._num_classes):\n                    if k == label:\n                        continue\n                    w_k = grads[k, idx, ...] - grads[label, idx, ...]\n                    f_k = np.mean(np.abs(preds_logits[idx, :, k, ...] - preds_logits[idx, :, label, ...]))\n                    if self._norm_level == 2 or self._norm_level == '2':\n                        diff_w_k = abs(f_k) / (np.linalg.norm(w_k) + 1e-8)\n                    elif self._norm_level == np.inf \\\n                            or self._norm_level == 'inf':\n                        diff_w_k = abs(f_k) / (np.linalg.norm(w_k, ord=1) + 1e-8)\n                    else:\n                        msg = 'ord {} is not available.' \\\n                            .format(str(self._norm_level))\n                        LOGGER.error(TAG, msg)\n                        raise NotImplementedError(msg)\n                    if diff_w_k < diff_w:\n                        diff_w = diff_w_k\n                        weight = w_k\n                r_i = self._normalize_r_i(diff_w, weight)\n                r_tot[idx, ...] = r_tot[idx, ...] + r_i\n\n            images = self._update_image(x_origin, r_tot)\n            iteration += 1\n            images = images.astype(images_dtype)\n            del preds_logits, grads\n        return images\n\n    def _generate_classification(self, inputs, labels):\n        \"\"\"Generate adversarial examples in classification scenario\"\"\"\n        inputs, labels = check_pair_numpy_param('inputs', inputs,\n                                                'labels', labels)\n        if not self._sparse:\n            labels = np.argmax(labels, axis=1)\n        inputs_dtype = inputs.dtype\n        iteration = 0\n        origin_labels = labels\n        cur_labels = origin_labels.copy()\n        weight = np.squeeze(np.zeros(inputs.shape[1:]))\n        r_tot = np.zeros(inputs.shape)\n        x_origin = inputs\n        while np.any(cur_labels == origin_labels) and iteration < self._max_iters:\n            preds = self._network(Tensor(inputs)).asnumpy()\n            grads = jacobian_matrix(self._net_grad, inputs, self._num_classes)\n            for idx in range(inputs.shape[0]):\n                diff_w = np.inf\n                label = origin_labels[idx]\n                if cur_labels[idx] != label:\n                    continue\n                for k in range(self._num_classes):\n                    if k == label:\n                        continue\n                    w_k = grads[k, idx, ...] - grads[label, idx, ...]\n                    f_k = preds[idx, k] - preds[idx, label]\n                    if self._norm_level == 2 or self._norm_level == '2':\n                        diff_w_k = abs(f_k) / (np.linalg.norm(w_k) + 1e-8)\n                    elif self._norm_level == np.inf \\\n                            or self._norm_level == 'inf':\n                        diff_w_k = abs(f_k) / (np.linalg.norm(w_k, ord=1) + 1e-8)\n                    else:\n                        msg = 'ord {} is not available.' \\\n                            .format(str(self._norm_level))\n                        LOGGER.error(TAG, msg)\n                        raise NotImplementedError(msg)\n                    if diff_w_k < diff_w:\n                        diff_w = diff_w_k\n                        weight = w_k\n\n                r_i = self._normalize_r_i(diff_w, weight)\n                r_tot[idx, ...] = r_tot[idx, ...] + r_i\n\n            if self._bounds is not None:\n                clip_min, clip_max = self._bounds\n                inputs = x_origin + (1 + self._overshoot)*r_tot*(clip_max\n                                                                 - clip_min)\n                inputs = np.clip(inputs, clip_min, clip_max)\n            else:\n                inputs = x_origin + (1 + self._overshoot)*r_tot\n            cur_labels = np.argmax(\n                self._network(Tensor(inputs.astype(inputs_dtype))).asnumpy(),\n                axis=1)\n            iteration += 1\n            inputs = inputs.astype(inputs_dtype)\n            del preds, grads\n        return inputs\n\n    def _normalize_r_i(self, diff_w, weight):\n        \"\"\"normalize r_i used to update r_tot\"\"\"\n        if self._norm_level == 2 or self._norm_level == '2':\n            r_i = diff_w * weight / (np.linalg.norm(weight) + 1e-8)\n        elif self._norm_level == np.inf or self._norm_level == 'inf':\n            r_i = diff_w * np.sign(weight) / (np.linalg.norm(weight, ord=1) + 1e-8)\n        else:\n            msg = 'ord {} is not available in normalization,'.format(str(self._norm_level))\n            LOGGER.error(TAG, msg)\n            raise NotImplementedError(msg)\n\n        return r_i\n"
  },
  {
    "path": "mindarmour/adv_robustness/attacks/gradient_method.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nGradient-method Attack.\n\"\"\"\nfrom abc import abstractmethod\n\nimport numpy as np\n\nfrom mindspore.nn import Cell\n\nfrom mindarmour.utils.util import WithLossCell, GradWrapWithLoss, to_tensor_tuple\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_model, check_inputs_labels, \\\n    normalize_value, check_value_positive, check_param_multi_types, \\\n    check_norm_level, check_param_type\nfrom .attack import Attack\n\nLOGGER = LogUtil.get_instance()\nTAG = 'SingleGrad'\n\n\nclass GradientMethod(Attack):\n    \"\"\"\n    Abstract base class for all single-step gradient-based attacks.\n\n    Args:\n        network (Cell): Target model.\n        eps (float): Proportion of single-step adversarial perturbation generated\n            by the attack to data range. Default: ``0.07``.\n        alpha (float): Proportion of single-step random perturbation to data range.\n            Default: ``None``.\n        bounds (tuple): Upper and lower bounds of data, indicating the data range.\n            In form of (clip_min, clip_max). Default: ``None``.\n        loss_fn (Loss): Loss function for optimization. If None, the input network \\\n            is already equipped with loss function. Default: ``None``.\n    \"\"\"\n\n    def __init__(self, network, eps=0.07, alpha=None, bounds=None,\n                 loss_fn=None):\n        super(GradientMethod, self).__init__()\n        self._network = check_model('network', network, Cell)\n        self._eps = check_value_positive('eps', eps)\n        self._dtype = None\n        if bounds is not None:\n            self._bounds = check_param_multi_types('bounds', bounds,\n                                                   [list, tuple])\n            for b in self._bounds:\n                _ = check_param_multi_types('bound', b, [int, float])\n        else:\n            self._bounds = bounds\n        if alpha is not None:\n            self._alpha = check_value_positive('alpha', alpha)\n        else:\n            self._alpha = alpha\n        if loss_fn is None:\n            self._grad_all = self._network\n        else:\n            with_loss_cell = WithLossCell(self._network, loss_fn)\n            self._grad_all = GradWrapWithLoss(with_loss_cell)\n\n    def generate(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples based on input samples and original/target labels.\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Benign input samples used as references to create\n                    adversarial examples.\n            labels (Union[numpy.ndarray, tuple]): Original/target labels. \\\n                For each input if it has more than one label, it is wrapped in a tuple.\n\n        Returns:\n            numpy.ndarray, generated adversarial examples.\n        \"\"\"\n        inputs_image, inputs, labels = check_inputs_labels(inputs, labels)\n        self._dtype = inputs_image.dtype\n        gradient = self._gradient(inputs, labels)\n        # use random method or not\n        if self._alpha is not None:\n            random_part = self._alpha*np.sign(np.random.normal(\n                size=inputs.shape)).astype(self._dtype)\n            perturbation = (self._eps - self._alpha)*gradient + random_part\n        else:\n            perturbation = self._eps*gradient\n\n        if self._bounds is not None:\n            clip_min, clip_max = self._bounds\n            perturbation = perturbation*(clip_max - clip_min)\n            adv_x = inputs_image + perturbation\n            adv_x = np.clip(adv_x, clip_min, clip_max)\n        else:\n            adv_x = inputs_image + perturbation\n        return adv_x\n\n    @abstractmethod\n    def _gradient(self, inputs, labels):\n        \"\"\"\n        Calculate gradients based on input samples and original/target labels.\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Benign input samples used as references to\n                create adversarial examples.\n            labels (Union[numpy.ndarray, tuple]): Original/target labels. \\\n                For each input if it has more than one label, it is wrapped in a tuple.\n\n        Raises:\n            NotImplementedError: It is an abstract method.\n        \"\"\"\n        msg = 'The function _gradient() is an abstract method in class ' \\\n              '`GradientMethod`, and should be implemented in child class.'\n        LOGGER.error(TAG, msg)\n        raise NotImplementedError(msg)\n\n\nclass FastGradientMethod(GradientMethod):\n    \"\"\"\n    This attack is a one-step attack based on gradients calculation, and\n    the norm of perturbations includes L1, L2 and Linf.\n\n    References: `I. J. Goodfellow, J. Shlens, and C. Szegedy, \"Explaining\n    and harnessing adversarial examples,\" in ICLR, 2015.\n    <https://arxiv.org/abs/1412.6572>`_.\n\n    Args:\n        network (Cell): Target model.\n        eps (float): Proportion of single-step adversarial perturbation generated\n            by the attack to data range. Default: ``0.07``.\n        alpha (Union[float, None]): Proportion of single-step random perturbation to data range.\n            Default: ``None``.\n        bounds (tuple): Upper and lower bounds of data, indicating the data range.\n            In form of (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n        norm_level (Union[int, str, numpy.inf]): Order of the norm.\n            Possible values: ``np.inf``, ``1`` or ``2``. Default: ``2``.\n        is_targeted (bool): If True, targeted attack. If False, untargeted\n            attack. Default: ``False``.\n        loss_fn (Union[loss, None]): Loss function for optimization. If ``None``, the input network \\\n            is already equipped with loss function. Default: ``None``.\n\n    Examples:\n        >>> from mindarmour.adv_robustness.attacks import FastGradientMethod\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._relu = nn.ReLU()\n        ...     def construct(self, inputs):\n        ...         out = self._relu(inputs)\n        ...         return out\n        >>> inputs = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n        >>> labels = np.asarray([2],np.int32)\n        >>> labels = np.eye(3)[labels].astype(np.float32)\n        >>> net = Net()\n        >>> attack = FastGradientMethod(net, loss_fn=nn.SoftmaxCrossEntropyWithLogits(sparse=False))\n        >>> adv_x = attack.generate(inputs, labels)\n    \"\"\"\n\n    def __init__(self, network, eps=0.07, alpha=None, bounds=(0.0, 1.0),\n                 norm_level=2, is_targeted=False, loss_fn=None):\n\n        super(FastGradientMethod, self).__init__(network,\n                                                 eps=eps,\n                                                 alpha=alpha,\n                                                 bounds=bounds,\n                                                 loss_fn=loss_fn)\n        self._norm_level = check_norm_level(norm_level)\n        self._is_targeted = check_param_type('is_targeted', is_targeted, bool)\n\n    def _gradient(self, inputs, labels):\n        \"\"\"\n        Calculate gradients based on input samples and original/target labels.\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Input sample.\n            labels (Union[numpy.ndarray, tuple]): Original/target labels. \\\n                For each input if it has more than one label, it is wrapped in a tuple.\n\n        Returns:\n            numpy.ndarray, gradient of inputs.\n        \"\"\"\n        inputs_tensor = to_tensor_tuple(inputs)\n        labels_tensor = to_tensor_tuple(labels)\n        out_grad = self._grad_all(*inputs_tensor, *labels_tensor)\n        if isinstance(out_grad, tuple):\n            out_grad = out_grad[0]\n        gradient = out_grad.asnumpy()\n\n        if self._is_targeted:\n            gradient = -gradient\n        return normalize_value(gradient, self._norm_level)\n\n\nclass RandomFastGradientMethod(FastGradientMethod):\n    \"\"\"\n    Fast Gradient Method use Random perturbation.\n    An one-step attack based on gradients calculation. The adversarial noises\n    are generated based on the gradients of inputs, and then randomly perturbed.\n\n    References: `Florian Tramer, Alexey Kurakin, Nicolas Papernot, \"Ensemble\n    adversarial training: Attacks and defenses\" in ICLR, 2018\n    <https://arxiv.org/abs/1705.07204>`_.\n\n    Args:\n        network (Cell): Target model.\n        eps (float): Proportion of single-step adversarial perturbation generated\n            by the attack to data range. Default: ``0.07``.\n        alpha (float): Proportion of single-step random perturbation to data range.\n            Default: ``0.035``.\n        bounds (tuple): Upper and lower bounds of data, indicating the data range.\n            In form of (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n        norm_level (Union[int, str, numpy.inf]): Order of the norm.\n            Possible values: ``np.inf``, ``1`` or ``2``. Default: ``2``.\n        is_targeted (bool): If ``True``, targeted attack. If ``False``, untargeted\n            attack. Default: ``False``.\n        loss_fn (Union[loss, None]): Loss function for optimization. If ``None``, the input network \\\n            is already equipped with loss function. Default: ``None``.\n\n    Raises:\n        ValueError: `eps` is smaller than `alpha`.\n\n    Examples:\n        >>> from mindarmour.adv_robustness.attacks import RandomFastGradientMethod\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._relu = nn.ReLU()\n        ...     def construct(self, inputs):\n        ...         out = self._relu(inputs)\n        ...         return out\n        >>> net = Net()\n        >>> inputs = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n        >>> labels = np.asarray([2],np.int32)\n        >>> labels = np.eye(3)[labels].astype(np.float32)\n        >>> attack = RandomFastGradientMethod(net, loss_fn=nn.SoftmaxCrossEntropyWithLogits(sparse=False))\n        >>> adv_x = attack.generate(inputs, labels)\n    \"\"\"\n\n    def __init__(self, network, eps=0.07, alpha=0.035, bounds=(0.0, 1.0),\n                 norm_level=2, is_targeted=False, loss_fn=None):\n        if eps < alpha:\n            raise ValueError('eps must be larger than alpha!')\n        super(RandomFastGradientMethod, self).__init__(network,\n                                                       eps=eps,\n                                                       alpha=alpha,\n                                                       bounds=bounds,\n                                                       norm_level=norm_level,\n                                                       is_targeted=is_targeted,\n                                                       loss_fn=loss_fn)\n\n\nclass FastGradientSignMethod(GradientMethod):\n    \"\"\"\n    The Fast Gradient Sign Method attack calculates the gradient of the input\n    data, and then uses the sign of the gradient to create adversarial noises.\n\n    References: `Ian J. Goodfellow, J. Shlens, and C. Szegedy, \"Explaining\n    and harnessing adversarial examples,\" in ICLR, 2015\n    <https://arxiv.org/abs/1412.6572>`_.\n\n    Args:\n        network (Cell): Target model.\n        eps (float): Proportion of single-step adversarial perturbation generated\n            by the attack to data range. Default: ``0.07``.\n        alpha (Union[float, None]): Proportion of single-step random perturbation to data range.\n            Default: ``None``.\n        bounds (tuple): Upper and lower bounds of data, indicating the data range.\n            In form of (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n        is_targeted (bool): If True, targeted attack. If ``False``, untargeted\n            attack. Default: ``False``.\n        loss_fn (Union[Loss, None]): Loss function for optimization. If ``None``, the input network \\\n            is already equipped with loss function. Default: ``None``.\n\n    Examples:\n        >>> from mindarmour.adv_robustness.attacks import FastGradientSignMethod\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._relu = nn.ReLU()\n        ...     def construct(self, inputs):\n        ...         out = self._relu(inputs)\n        ...         return out\n        >>> net = Net()\n        >>> inputs = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n        >>> labels = np.asarray([2],np.int32)\n        >>> labels = np.eye(3)[labels].astype(np.float32)\n        >>> attack = FastGradientSignMethod(net, loss_fn=nn.SoftmaxCrossEntropyWithLogits(sparse=False))\n        >>> adv_x = attack.generate(inputs, labels)\n    \"\"\"\n\n    def __init__(self, network, eps=0.07, alpha=None, bounds=(0.0, 1.0),\n                 is_targeted=False, loss_fn=None):\n        super(FastGradientSignMethod, self).__init__(network,\n                                                     eps=eps,\n                                                     alpha=alpha,\n                                                     bounds=bounds,\n                                                     loss_fn=loss_fn)\n        self._is_targeted = check_param_type('is_targeted', is_targeted, bool)\n\n    def _gradient(self, inputs, labels):\n        \"\"\"\n        Calculate gradients based on input samples and original/target\n        labels.\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Input samples.\n            labels (Union[numpy.ndarray, tuple]): original/target labels. \\\n                for each input if it has more than one label, it is wrapped in a tuple.\n\n        Returns:\n            numpy.ndarray, gradient of inputs.\n        \"\"\"\n        inputs_tensor = to_tensor_tuple(inputs)\n        labels_tensor = to_tensor_tuple(labels)\n        out_grad = self._grad_all(*inputs_tensor, *labels_tensor)\n        if isinstance(out_grad, tuple):\n            out_grad = out_grad[0]\n        gradient = out_grad.asnumpy()\n        if self._is_targeted:\n            gradient = -gradient\n        gradient = np.sign(gradient)\n        return gradient\n\n\nclass RandomFastGradientSignMethod(FastGradientSignMethod):\n    \"\"\"\n    Fast Gradient Sign Method using random perturbation.\n    The Random Fast Gradient Sign Method attack calculates the gradient of the input\n    data, and then uses the sign of the gradient with random perturbation\n    to create adversarial noises.\n\n    References: `F. Tramer, et al., \"Ensemble adversarial training: Attacks\n    and defenses,\" in ICLR, 2018 <https://arxiv.org/abs/1705.07204>`_.\n\n    Args:\n        network (Cell): Target model.\n        eps (float): Proportion of single-step adversarial perturbation generated\n            by the attack to data range. Default: ``0.07``.\n        alpha (float): Proportion of single-step random perturbation to data range.\n            Default: ``0.035``.\n        bounds (tuple): Upper and lower bounds of data, indicating the data range.\n            In form of (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n        is_targeted (bool): ``True``: targeted attack. ``False``: untargeted attack.\n            Default: ``False``.\n        loss_fn (Union[Loss, None]): Loss function for optimization. If None, the input network \\\n            is already equipped with loss function. Default: ``None``.\n\n    Raises:\n        ValueError: eps is smaller than alpha!\n\n    Examples:\n        >>> from mindarmour.adv_robustness.attacks import RandomFastGradientSignMethod\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._relu = nn.ReLU()\n        ...     def construct(self, inputs):\n        ...         out = self._relu(inputs)\n        ...         return out\n        >>> net = Net()\n        >>> inputs = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n        >>> labels = np.asarray([2],np.int32)\n        >>> labels = np.eye(3)[labels].astype(np.float32)\n        >>> attack = RandomFastGradientSignMethod(net, loss_fn=nn.SoftmaxCrossEntropyWithLogits(sparse=False))\n        >>> adv_x = attack.generate(inputs, labels)\n    \"\"\"\n\n    def __init__(self, network, eps=0.07, alpha=0.035, bounds=(0.0, 1.0),\n                 is_targeted=False, loss_fn=None):\n        if eps < alpha:\n            raise ValueError('eps must be larger than alpha!')\n        super(RandomFastGradientSignMethod, self).__init__(network,\n                                                           eps=eps,\n                                                           alpha=alpha,\n                                                           bounds=bounds,\n                                                           is_targeted=is_targeted,\n                                                           loss_fn=loss_fn)\n\n\nclass LeastLikelyClassMethod(FastGradientSignMethod):\n    \"\"\"\n    The Single Step Least-Likely Class Method, a variant of FGSM, targets the\n    least-likely class to generate the adversarial examples.\n\n    References: `F. Tramer, et al., \"Ensemble adversarial training: Attacks\n    and defenses,\" in ICLR, 2018 <https://arxiv.org/abs/1705.07204>`_.\n\n    Args:\n        network (Cell): Target model.\n        eps (float): Proportion of single-step adversarial perturbation generated\n            by the attack to data range. Default: ``0.07``.\n        alpha (Union[float, None]): Proportion of single-step random perturbation to data range.\n            Default: ``None``.\n        bounds (tuple): Upper and lower bounds of data, indicating the data range.\n            In form of (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n        loss_fn (Union[Loss, None]): Loss function for optimization. If ``None``, the input network \\\n            is already equipped with loss function. Default: ``None``.\n\n    Examples:\n        >>> from mindarmour.adv_robustness.attacks import LeastLikelyClassMethod\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._relu = nn.ReLU()\n        ...     def construct(self, inputs):\n        ...         out = self._relu(inputs)\n        ...         return out\n        >>> inputs = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n        >>> labels = np.asarray([2],np.int32)\n        >>> labels = np.eye(3)[labels].astype(np.float32)\n        >>> net = Net()\n        >>> attack = LeastLikelyClassMethod(net, loss_fn=nn.SoftmaxCrossEntropyWithLogits(sparse=False))\n        >>> adv_x = attack.generate(inputs, labels)\n    \"\"\"\n\n    def __init__(self, network, eps=0.07, alpha=None, bounds=(0.0, 1.0),\n                 loss_fn=None):\n        super(LeastLikelyClassMethod, self).__init__(network,\n                                                     eps=eps,\n                                                     alpha=alpha,\n                                                     bounds=bounds,\n                                                     is_targeted=True,\n                                                     loss_fn=loss_fn)\n\n\nclass RandomLeastLikelyClassMethod(FastGradientSignMethod):\n    \"\"\"\n    Least-Likely Class Method use Random perturbation.\n\n    The Single Step Least-Likely Class Method with Random Perturbation, a variant of Random FGSM,\n    targets the least-likely class to generate the adversarial examples.\n\n    References: `F. Tramer, et al., \"Ensemble adversarial training: Attacks\n    and defenses,\" in ICLR, 2018 <https://arxiv.org/abs/1705.07204>`_.\n\n    Args:\n        network (Cell): Target model.\n        eps (float): Proportion of single-step adversarial perturbation generated\n            by the attack to data range. Default: ``0.07``.\n        alpha (float): Proportion of single-step random perturbation to data range.\n            Default: ``0.035``.\n        bounds (tuple): Upper and lower bounds of data, indicating the data range.\n            In form of (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n        loss_fn (Union[Loss, None]): Loss function for optimization. If ``None``, the input network \\\n            is already equipped with loss function. Default: ``None``.\n\n    Raises:\n        ValueError: eps is smaller than alpha!\n\n    Examples:\n        >>> from mindarmour.adv_robustness.attacks import RandomLeastLikelyClassMethod\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._relu = nn.ReLU()\n        ...     def construct(self, inputs):\n        ...         out = self._relu(inputs)\n        ...         return out\n        >>> inputs = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n        >>> labels = np.asarray([2],np.int32)\n        >>> labels = np.eye(3)[labels].astype(np.float32)\n        >>> net = Net()\n        >>> attack = RandomLeastLikelyClassMethod(net, loss_fn=nn.SoftmaxCrossEntropyWithLogits(sparse=False))\n        >>> adv_x = attack.generate(inputs, labels)\n    \"\"\"\n\n    def __init__(self, network, eps=0.07, alpha=0.035, bounds=(0.0, 1.0),\n                 loss_fn=None):\n        if eps < alpha:\n            raise ValueError('eps must be larger than alpha!')\n        super(RandomLeastLikelyClassMethod, self).__init__(network,\n                                                           eps=eps,\n                                                           alpha=alpha,\n                                                           bounds=bounds,\n                                                           is_targeted=True,\n                                                           loss_fn=loss_fn)\n"
  },
  {
    "path": "mindarmour/adv_robustness/attacks/iterative_gradient_method.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\" Iterative gradient method attack. \"\"\"\nfrom abc import abstractmethod\n\nimport copy\nimport numpy as np\nfrom PIL import Image, ImageOps\n\nimport mindspore.nn as nn\nimport mindspore.ops as ops\nimport mindspore as ms\nfrom mindspore.nn import Cell\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils.util import WithLossCell, GradWrapWithLoss, to_tensor_tuple\nfrom mindarmour.utils._check_param import check_inputs_labels, \\\n    normalize_value, check_model, check_value_positive, check_int_positive, \\\n    check_param_type, check_norm_level, check_param_multi_types\nfrom .attack import Attack\nfrom .gradient_method import FastGradientSignMethod\n\nLOGGER = LogUtil.get_instance()\nTAG = 'IterGrad'\n\n\ndef _reshape_l1_projection(values, eps=3):\n    \"\"\"\n    `Implementation of L1 ball projection from:`_.\n\n    .. _`Implementation of L1 ball projection from:`:\n        https://stanford.edu/~jduchi/projects/DuchiShSiCh08.pdf\n\n    Args:\n        values (numpy.ndarray): Input data reshape into 2-dims.\n        eps (float): L1 radius. Default: 3.\n\n    Returns:\n        numpy.ndarray, containing the projection.\n    \"\"\"\n    abs_x = np.abs(values)\n    abs_x = np.sum(abs_x, axis=1)\n    indexes_b = (abs_x > eps)\n    x_b = values[indexes_b]\n    batch_size_b = x_b.shape[0]\n    if batch_size_b == 0:\n        return values\n\n    # make the projection on l1 ball for elements outside the ball\n    b_mu = -np.sort(-np.abs(x_b), axis=1)\n    b_vv = np.arange(x_b.shape[1]).astype(np.float)\n    b_st = (np.cumsum(b_mu, axis=1)-eps)/(b_vv+1)\n    selected = (b_mu - b_st) > 0\n    rho = np.sum((np.cumsum((1-selected), axis=1) == 0), axis=1)-1\n    theta = np.take_along_axis(b_st, np.expand_dims(rho, axis=1), axis=1)\n    proj_x_b = np.maximum(0, np.abs(x_b)-theta)*np.sign(x_b)\n\n    # gather all the projected batch\n    proj_x = np.copy(values)\n    proj_x[indexes_b] = proj_x_b\n    return proj_x\n\n\ndef _projection(values, eps, clip_diff, norm_level):\n    \"\"\"\n    Implementation of values normalization within eps.\n\n    Args:\n        values (numpy.ndarray): Input data.\n        eps (float): Project radius.\n        clip_diff (float): Difference range of clip bounds.\n        norm_level (Union[int, char, numpy.inf]): Order of the norm. Possible\n            values: np.inf, 1 or 2.\n\n    Returns:\n        numpy.ndarray, normalized values.\n\n    Raises:\n        NotImplementedError: If the norm_level is not in [1, 2, np.inf, '1',\n            '2', 'inf'].\n    \"\"\"\n    if norm_level in (1, '1'):\n        sample_batch = values.shape[0]\n        x_flat = values.reshape(sample_batch, -1)\n        proj_flat = _reshape_l1_projection(x_flat, eps*clip_diff)\n        return proj_flat.reshape(values.shape)\n    if norm_level in (2, '2'):\n        return eps*normalize_value(values, norm_level)\n    if norm_level in (np.inf, 'inf'):\n        return eps*clip_diff*np.sign(values)\n    msg = 'Values of `norm_level` different from 1, 2 and `np.inf` are ' \\\n          'currently not supported.'\n    LOGGER.error(TAG, msg)\n    raise NotImplementedError(msg)\n\n\nclass IterativeGradientMethod(Attack):\n    \"\"\"\n    Abstract base class for all iterative gradient based attacks.\n\n    Args:\n        network (Cell): Target model.\n        eps (float): Proportion of adversarial perturbation generated by the\n            attack to data range. Default: ``0.3``.\n        eps_iter (float): Proportion of single-step adversarial perturbation\n            generated by the attack to data range. Default: ``0.1``.\n        bounds (tuple): Upper and lower bounds of data, indicating the data range.\n            In form of (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n        nb_iter (int): Number of iteration. Default: ``5``.\n        loss_fn (Union[Loss, None]): Loss function for optimization. If ``None``, the input network \\\n            is already equipped with loss function. Default: ``None``.\n    \"\"\"\n    def __init__(self, network, eps=0.3, eps_iter=0.1, bounds=(0.0, 1.0), nb_iter=5,\n                 loss_fn=None):\n        super(IterativeGradientMethod, self).__init__()\n        self._network = check_model('network', network, Cell)\n        self._eps = check_value_positive('eps', eps)\n        self._eps_iter = check_value_positive('eps_iter', eps_iter)\n        self._nb_iter = check_int_positive('nb_iter', nb_iter)\n        self._bounds = None\n        if bounds is not None:\n            self._bounds = check_param_multi_types('bounds', bounds, [list, tuple])\n            for b in self._bounds:\n                _ = check_param_multi_types('bound', b, [int, float])\n        if loss_fn is None:\n            self._loss_grad = network\n        else:\n            self._loss_grad = GradWrapWithLoss(WithLossCell(self._network, loss_fn))\n\n    @abstractmethod\n    def generate(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples based on input samples and original/target labels.\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Benign input samples used as references to create\n                adversarial examples.\n            labels (Union[numpy.ndarray, tuple]): Original/target labels. \\\n                For each input if it has more than one label, it is wrapped in a tuple.\n        Raises:\n            NotImplementedError: This function is not available in\n                IterativeGradientMethod.\n        \"\"\"\n        msg = 'The function generate() is an abstract method in class ' \\\n              '`IterativeGradientMethod`, and should be implemented ' \\\n              'in child class.'\n        LOGGER.error(TAG, msg)\n        raise NotImplementedError(msg)\n\n\nclass BasicIterativeMethod(IterativeGradientMethod):\n    \"\"\"\n    The Basic Iterative Method attack, an iterative FGSM method to generate\n    adversarial examples.\n\n    References: `A. Kurakin, I. Goodfellow, and S. Bengio, \"Adversarial examples\n    in the physical world,\" in ICLR, 2017 <https://arxiv.org/abs/1607.02533>`_.\n\n    Args:\n        network (Cell): Target model.\n        eps (float): Proportion of adversarial perturbation generated by the\n            attack to data range. Default: ``0.3``.\n        eps_iter (float): Proportion of single-step adversarial perturbation\n            generated by the attack to data range. Default: ``0.1``.\n        bounds (tuple): Upper and lower bounds of data, indicating the data range.\n            In form of (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n        is_targeted (bool): If ``True``, targeted attack. If ``False``, untargeted\n            attack. Default: ``False``.\n        nb_iter (int): Number of iteration. Default: ``5``.\n        loss_fn (Union[Loss, None]): Loss function for optimization. If ``None``, the input network \\\n            is already equipped with loss function. Default: ``None``.\n\n    Examples:\n        >>> from mindspore.ops import operations as P\n        >>> from mindarmour.adv_robustness.attacks import BasicIterativeMethod\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         return out\n        >>> net = Net()\n        >>> attack = BasicIterativeMethod(net, loss_fn=nn.SoftmaxCrossEntropyWithLogits(sparse=False))\n        >>> inputs = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n        >>> labels = np.asarray([2],np.int32)\n        >>> labels = np.eye(3)[labels].astype(np.float32)\n        >>> net = Net()\n        >>> adv_x = attack.generate(inputs, labels)\n    \"\"\"\n    def __init__(self, network, eps=0.3, eps_iter=0.1, bounds=(0.0, 1.0),\n                 is_targeted=False, nb_iter=5, loss_fn=None):\n        super(BasicIterativeMethod, self).__init__(network,\n                                                   eps=eps,\n                                                   eps_iter=eps_iter,\n                                                   bounds=bounds,\n                                                   nb_iter=nb_iter,\n                                                   loss_fn=loss_fn)\n        self._is_targeted = check_param_type('is_targeted', is_targeted, bool)\n        self._attack = FastGradientSignMethod(self._network,\n                                              eps=self._eps_iter,\n                                              bounds=self._bounds,\n                                              is_targeted=self._is_targeted,\n                                              loss_fn=loss_fn)\n\n    def generate(self, inputs, labels):\n\n        \"\"\"\n        Simple iterative FGSM method to generate adversarial examples.\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Benign input samples used as references to\n                create adversarial examples.\n            labels (Union[numpy.ndarray, tuple]): Original/target labels. \\\n                For each input if it has more than one label, it is wrapped in a tuple.\n        Returns:\n            numpy.ndarray, generated adversarial examples.\n        \"\"\"\n        inputs_image, inputs, labels = check_inputs_labels(inputs, labels)\n        arr_x = inputs_image\n        if self._bounds is not None:\n            clip_min, clip_max = self._bounds\n            clip_diff = clip_max - clip_min\n            for _ in range(self._nb_iter):\n                if 'self._prob' in globals():\n                    d_inputs = _transform_inputs(inputs_image, self._prob)\n                else:\n                    d_inputs = inputs_image\n                if isinstance(inputs, tuple):\n                    d_inputs = (d_inputs,) + inputs[1:]\n                adv_x = self._attack.generate(d_inputs, labels)\n                perturs = np.clip(adv_x - arr_x, (0 - self._eps)*clip_diff,\n                                  self._eps*clip_diff)\n                adv_x = arr_x + perturs\n                inputs_image = adv_x\n        else:\n            for _ in range(self._nb_iter):\n                if 'self._prob' in globals():\n                    d_inputs = _transform_inputs(inputs_image, self._prob)\n                else:\n                    d_inputs = inputs_image\n                if isinstance(inputs, tuple):\n                    d_inputs = (inputs_image,) + inputs[1:]\n                adv_x = self._attack.generate(d_inputs, labels)\n                adv_x = np.clip(adv_x, arr_x - self._eps, arr_x + self._eps)\n                inputs_image = adv_x\n        return adv_x\n\n\nclass MomentumIterativeMethod(IterativeGradientMethod):\n    \"\"\"\n    The Momentum Iterative Method attack accelerates the gradient descent algorithm,\n    such as FGSM, FGM, and LLCM, by accumulating a velocity vector in the gradient\n    direction of the loss function across iterations, and thus generates the adversarial examples.\n\n\n    References: `Y. Dong, et al., \"Boosting adversarial attacks with\n    momentum,\" arXiv:1710.06081, 2017 <https://arxiv.org/abs/1710.06081>`_.\n\n    Args:\n        network (Cell): Target model.\n        eps (float): Proportion of adversarial perturbation generated by the\n            attack to data range. Default: ``0.3``.\n        eps_iter (float): Proportion of single-step adversarial perturbation\n            generated by the attack to data range. Default: ``0.1``.\n        bounds (tuple): Upper and lower bounds of data, indicating the data range.\n            In form of (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n        is_targeted (bool): If ``True``, targeted attack. If ``False``, untargeted\n            attack. Default: ``False``.\n        nb_iter (int): Number of iteration. Default: ``5``.\n        decay_factor (float): Decay factor in iterations. Default: ``1.0``.\n        norm_level (Union[int, str, numpy.inf]): Order of the norm. Possible values:\n            ``np.inf``, ``1`` or ``2``. Default: ``'inf'``.\n        loss_fn (Union[Loss, None]): Loss function for optimization. If ``None``, the input network \\\n            is already equipped with loss function. Default: ``None``.\n\n    Examples:\n        >>> from mindspore.ops import operations as P\n        >>> from mindarmour.adv_robustness.attacks import MomentumIterativeMethod\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         return out\n        >>> net = Net()\n        >>> attack = MomentumIterativeMethod(net, loss_fn=nn.SoftmaxCrossEntropyWithLogits(sparse=False))\n        >>> inputs = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n        >>> labels = np.asarray([2],np.int32)\n        >>> labels = np.eye(3)[labels].astype(np.float32)\n        >>> net = Net()\n        >>> adv_x = attack.generate(inputs, labels)\n    \"\"\"\n\n    def __init__(self, network, eps=0.3, eps_iter=0.1, bounds=(0.0, 1.0),\n                 is_targeted=False, nb_iter=5, decay_factor=1.0,\n                 norm_level='inf', loss_fn=None):\n        super(MomentumIterativeMethod, self).__init__(network,\n                                                      eps=eps,\n                                                      eps_iter=eps_iter,\n                                                      bounds=bounds,\n                                                      nb_iter=nb_iter,\n                                                      loss_fn=loss_fn)\n        self._is_targeted = check_param_type('is_targeted', is_targeted, bool)\n        self._decay_factor = check_value_positive('decay_factor', decay_factor)\n        self._norm_level = check_norm_level(norm_level)\n\n    def generate(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples based on input data and origin/target labels.\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Benign input samples used as references to\n                create adversarial examples.\n            labels (Union[numpy.ndarray, tuple]): Original/target labels. \\\n                For each input if it has more than one label, it is wrapped in a tuple.\n\n        Returns:\n            numpy.ndarray, generated adversarial examples.\n        \"\"\"\n        inputs_image, inputs, labels = check_inputs_labels(inputs, labels)\n        arr_x = inputs_image\n        momentum = 0\n        if self._bounds is not None:\n            clip_min, clip_max = self._bounds\n            clip_diff = clip_max - clip_min\n            for _ in range(self._nb_iter):\n                if 'self._prob' in globals():\n                    d_inputs = _transform_inputs(inputs_image, self._prob)\n                else:\n                    d_inputs = inputs_image\n                if isinstance(inputs, tuple):\n                    d_inputs = (d_inputs,) + inputs[1:]\n                gradient = self._gradient(d_inputs, labels)\n                momentum = self._decay_factor*momentum + gradient\n                if isinstance(d_inputs, tuple):\n                    adv_x = d_inputs[0] + self._eps_iter*np.sign(momentum)\n                else:\n                    adv_x = d_inputs + self._eps_iter*np.sign(momentum)\n                perturs = np.clip(adv_x - arr_x, (0 - self._eps)*clip_diff,\n                                  self._eps*clip_diff)\n                adv_x = arr_x + perturs\n                adv_x = np.clip(adv_x, clip_min, clip_max)\n                inputs_image = adv_x\n        else:\n            for _ in range(self._nb_iter):\n                if 'self._prob' in globals():\n                    d_inputs = _transform_inputs(inputs_image, self._prob)\n                else:\n                    d_inputs = inputs_image\n                if isinstance(inputs, tuple):\n                    d_inputs = (d_inputs,) + inputs[1:]\n                gradient = self._gradient(d_inputs, labels)\n                momentum = self._decay_factor*momentum + gradient\n                if isinstance(d_inputs, tuple):\n                    adv_x = d_inputs[0] + self._eps_iter*np.sign(momentum)\n                else:\n                    adv_x = d_inputs + self._eps_iter*np.sign(momentum)\n                adv_x = np.clip(adv_x, arr_x - self._eps, arr_x + self._eps)\n                inputs_image = adv_x\n        return adv_x\n\n    def _gradient(self, inputs, labels):\n        \"\"\"\n        Calculate the gradient of input samples.\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Input samples.\n            labels (Union[numpy.ndarray, tuple]): Original/target labels. \\\n                For each input if it has more than one label, it is wrapped in a tuple.\n\n        Returns:\n            numpy.ndarray, gradient of labels w.r.t inputs.\n\n        Examples:\n            >>> grad = self._gradient([[0.5, 0.3, 0.4]],\n            ...                       [[0, 0, 0, 1, 0, 0, 0, 0, 0, 0])\n        \"\"\"\n        # get grad of loss over x\n        inputs_tensor = to_tensor_tuple(inputs)\n        labels_tensor = to_tensor_tuple(labels)\n        out_grad = self._loss_grad(*inputs_tensor, *labels_tensor)\n        if isinstance(out_grad, tuple):\n            out_grad = out_grad[0]\n        gradient = out_grad.asnumpy()\n\n        if self._is_targeted:\n            gradient = -gradient\n        return normalize_value(gradient, self._norm_level)\n\n\nclass ProjectedGradientDescent(BasicIterativeMethod):\n    \"\"\"\n    The Projected Gradient Descent attack is a variant of the Basic Iterative\n    Method in which, after each iteration, the perturbation is projected on an\n    lp-ball of specified radius (in addition to clipping the values of the\n    adversarial sample so that it lies in the permitted data range). This is\n    the attack proposed by Madry et al. for adversarial training.\n\n    References: `A. Madry, et al., \"Towards deep learning models resistant to\n    adversarial attacks,\" in ICLR, 2018 <https://arxiv.org/abs/1706.06083>`_.\n\n    Args:\n        network (Cell): Target model.\n        eps (float): Proportion of adversarial perturbation generated by the\n            attack to data range. Default: ``0.3``.\n        eps_iter (float): Proportion of single-step adversarial perturbation\n            generated by the attack to data range. Default: ``0.1``.\n        bounds (tuple): Upper and lower bounds of data, indicating the data range.\n            In form of (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n        is_targeted (bool): If ``True``, targeted attack. If ``False``, untargeted\n            attack. Default: ``False``.\n        nb_iter (int): Number of iteration. Default: ``5``.\n        norm_level (Union[int, str, numpy.inf]): Order of the norm. Possible values:\n            np.inf, 1 or 2. Default: ``'inf'``.\n        loss_fn (Union[Loss, None]): Loss function for optimization. If ``None``, the input network \\\n            is already equipped with loss function. Default: ``None``.\n\n    Examples:\n        >>> from mindspore.ops import operations as P\n        >>> from mindarmour.adv_robustness.attacks import ProjectedGradientDescent\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         return out\n        >>> net = Net()\n        >>> attack = ProjectedGradientDescent(net, loss_fn=nn.SoftmaxCrossEntropyWithLogits(sparse=False))\n        >>> inputs = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n        >>> labels = np.asarray([2],np.int32)\n        >>> labels = np.eye(3)[labels].astype(np.float32)\n        >>> net = Net()\n        >>> adv_x = attack.generate(inputs, labels)\n    \"\"\"\n\n    def __init__(self, network, eps=0.3, eps_iter=0.1, bounds=(0.0, 1.0),\n                 is_targeted=False, nb_iter=5, norm_level='inf', loss_fn=None):\n        super(ProjectedGradientDescent, self).__init__(network,\n                                                       eps=eps,\n                                                       eps_iter=eps_iter,\n                                                       bounds=bounds,\n                                                       is_targeted=is_targeted,\n                                                       nb_iter=nb_iter,\n                                                       loss_fn=loss_fn)\n        self._norm_level = check_norm_level(norm_level)\n\n    def generate(self, inputs, labels):\n        \"\"\"\n        Iteratively generate adversarial examples. The\n        perturbation is normalized by projected method with parameter norm_level .\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Benign input samples used as references to\n                create adversarial examples.\n            labels (Union[numpy.ndarray, tuple]): Original/target labels. \\\n                For each input if it has more than one label, it is wrapped in a tuple.\n\n        Returns:\n            numpy.ndarray, generated adversarial examples.\n        \"\"\"\n        inputs_image, inputs, labels = check_inputs_labels(inputs, labels)\n        arr_x = inputs_image\n        adv_x = copy.deepcopy(inputs_image)\n        if self._bounds is not None:\n            clip_min, clip_max = self._bounds\n            clip_diff = clip_max - clip_min\n        else:\n            clip_diff = 1\n\n        for _ in range(self._nb_iter):\n            inputs_tensor = to_tensor_tuple(inputs)\n            labels_tensor = to_tensor_tuple(labels)\n            out_grad = self._loss_grad(*inputs_tensor, *labels_tensor)\n            gradient = out_grad.asnumpy()\n            perturbs = _projection(gradient, self._eps_iter, clip_diff, norm_level=self._norm_level)\n            sum_perturbs = adv_x - arr_x + perturbs\n            sum_perturbs = np.clip(sum_perturbs, (0 - self._eps)*clip_diff, self._eps*clip_diff)\n            adv_x = arr_x + sum_perturbs\n            if self._bounds is not None:\n                adv_x = np.clip(adv_x, clip_min, clip_max)\n            if isinstance(inputs, tuple):\n                inputs = (adv_x,) + inputs[1:]\n            else:\n                inputs = adv_x\n        return adv_x\n\n\nclass AutoProjectedGradientDescent(BasicIterativeMethod):\n    \"\"\"\n    APGD (Auto Projected Gradient Descent) is an iterative method and an upgraded\n    version of the PGD method. In this approach, perturbations are projected onto\n    the Lp-ball after each iteration (in addition to clipping the values of the\n    adversarial samples so that they lie within the allowed data range) and adaptive\n    steps and momentum are introduced to accelerate convergence and improve attack\n    performance. This is the attack proposed for adversarial training by Croce et al.\n\n\n    Reference: `Croce and Hein, \"Reliable evaluation of adversarial robustness with an ensemble of \\\n    diverse parameter-free attacks\" in ICML, 2020 <https://arxiv.org/abs/2003.01690>`_.\n\n    Args:\n        network (Cell): Target model.\n        eps (float): Proportion of adversarial perturbation generated by the\n            attack to data range. Default: ``8 / 255``.\n        eps_iter (float): Proportion of single-step adversarial perturbation\n            generated by the attack to data range. Default: ``0.1``.\n        bounds (tuple): Upper and lower bounds of data, indicating the data range.\n            In form of (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n        is_targeted (bool): If ``True``, targeted attack. If ``False``, untargeted\n            attack. Default: ``False``.\n        nb_iter (int) : Number of iteration. Default: ``10``.\n        norm_level (Union[int, str, numpy.inf]): Order of the norm. Possible values:\n            ``inf``, ``1`` or ``2``. Default: ``inf``.\n        loss_fn (Union[Loss, None]): Loss function for optimization. If ``None``, the input network \\\n            is already equipped with loss function. Default: ``None``.\n        eot_iter (int): Number of iteration for EOT. Default: ``1``.\n        thr_decr (float): Parameter for step-size update. Default: ``0.75``.\n\n    Examples:\n        >>> import numpy as np\n        >>> import mindspore.ops as ops\n        >>> import mindspore.nn as nn\n        >>> from mindarmour.adv_robustness.attacks import AutoProjectedGradientDescent\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = ops.Softmax()\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         return out\n        >>> net = Net()\n        >>> attack = AutoProjectedGradientDescent(net, eps=0.3)\n        >>> inputs = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n        >>> labels = np.asarray([2],np.int32)\n        >>> labels = np.eye(3)[labels].astype(np.float32)\n        >>> net = Net()\n        >>> adv_x = attack.generate(inputs, labels)\n    \"\"\"\n\n    def __init__(self, network, eps=8 / 255, eps_iter=0.1, bounds=(0.0, 1.0), is_targeted=False, nb_iter=10,\n                 norm_level='inf', loss_fn=None, eot_iter=1, thr_decr=0.75):\n        super(AutoProjectedGradientDescent, self).__init__(network, eps=eps, eps_iter=eps_iter, bounds=bounds,\n                                                           is_targeted=is_targeted, nb_iter=nb_iter, loss_fn=loss_fn)\n        self._norm = norm_level\n        self._steps = nb_iter\n        self._eot_iter = eot_iter\n        self._eps = eps\n        self._loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')\n        self._network = network\n        self._norm_level = check_norm_level(norm_level)\n        self._thr_decr = check_value_positive('thr_decr', thr_decr)\n\n    def generate(self, inputs, labels):\n        \"\"\"\n        Iteratively generate adversarial examples. The perturbation\n        is normalized by projected method with parameter `norm_level`.\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Benign input samples used as references to\n                create adversarial examples.\n            labels (Union[numpy.ndarray, tuple]): Original/target labels. \\\n                For each input if it has more than one label, it is wrapped in a tuple.\n\n        Returns:\n            numpy.ndarray, generated adversarial examples.\n        \"\"\"\n        inputs = ms.Tensor(inputs)\n        labels = ms.Tensor(labels)\n        x = inputs.copy() if len(inputs.shape) == 4 else inputs.copy().unsqueeze(0)\n        y = labels.copy() if len(labels.shape) == 1 else labels.copy().unsqueeze(0)\n        steps_ratio, steps_min_ratio, size_decr_ratio = 0.22, 0.06, 0.03\n        steps, steps_min, size_decr = max(int(steps_ratio * self._steps), 1), max(\n            int(steps_min_ratio * self._steps), 1), max(int(size_decr_ratio * self._steps), 1)\n\n        if self._norm == 'inf':\n            t = 2 * ms.Tensor(np.random.rand(*x.shape).astype(np.float32)) - 1\n            x_adv = x + self._eps * ms.Tensor(np.ones([x.shape[0], 1, 1, 1]), dtype=ms.float32) * t / (\n                t.reshape([t.shape[0], -1]).abs().max(axis=1, keepdims=True)[0].reshape([-1, 1, 1, 1]))\n        elif self._norm == 'L2':\n            t = ms.Tensor(np.random.rand(*x.shape).astype(np.float32))\n            x_adv = x + self._eps * ms.Tensor(np.ones([x.shape[0], 1, 1, 1]), dtype=ms.float32) * t / (\n                (t ** 2).sum(axis=(1, 2, 3), keepdims=True).sqrt() + 1e-12)\n\n        x_adv = x_adv.clip(0.0, 1.0)\n        x_best = x_adv.copy()\n        x_best_adv = x_adv.copy()\n        loss_steps = np.zeros((self._steps, x.shape[0]))\n        loss_best_steps = np.zeros((self._steps + 1, x.shape[0]))\n        acc_steps = np.zeros_like(loss_best_steps)\n        criterion_indiv = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='none')\n        grad = ops.ZerosLike()(x)\n        for _ in range(self._eot_iter):\n            grad += GradWrapWithLoss(WithLossCell(self._network, self._loss_fn))(x_adv, y)\n\n        grad = ops.div(grad, self._eot_iter)\n        grad_best = grad.copy()\n        logits = self._network(x_adv)\n        loss_indiv = criterion_indiv(logits, y)\n        acc = logits.max(1)[1] == y\n        acc_steps[0] = acc + 0\n        loss_best = loss_indiv.copy()\n        step_size = self._eps * ms.Tensor(np.ones([x.shape[0], 1, 1, 1]), dtype=ms.float32) * ms.Tensor([2.0]).reshape(\n            [1, 1, 1, 1])\n        x_adv_old = x_adv.copy()\n        k = steps + 0\n        u = np.arange(x.shape[0])\n        counter = 0\n        momentum = 0.75\n\n        loss_best_last_check = loss_best.copy()\n        reduced_last_check = np.zeros(loss_best.shape) == np.zeros(loss_best.shape)\n        x_best = self._optimize_attack(x_adv, x_best, x_best_adv, x_adv_old, momentum, counter, k, step_size, grad,\n                                       x, y, logits, acc, acc_steps, loss_indiv, loss_steps, loss_best, grad_best,\n                                       loss_best_steps, reduced_last_check, loss_best_last_check, u,\n                                       size_decr, steps_min)\n\n        return x_best.asnumpy()\n\n    def _optimize_attack(self, x_adv, x_best, x_best_adv, x_adv_old, momentum, counter, k, step_size, grad,\n                         x, y, logits, acc, acc_steps, loss_indiv, loss_steps, loss_best, grad_best, loss_best_steps,\n                         reduced_last_check, loss_best_last_check, u, size_decr, steps_min):\n        \"\"\"\n        This function computes the gradient and optimizes it by updating x_adv with multiple iterations.\n        \"\"\"\n        for i in range(self._steps):\n            grad2 = x_adv - x_adv_old\n            x_adv_old = x_adv.copy()\n            a = momentum if i > 0 else 1.0\n            if self._norm == 'inf':\n                x_adv_1 = x_adv + step_size * ops.operations.Sign()(grad)\n                x_adv_1 = ops.clip_by_value(ops.clip_by_value(x_adv_1, x - self._eps, x + self._eps), 0.0, 1.0)\n                x_adv_1 = ops.clip_by_value(\n                    ops.clip_by_value(x_adv + (x_adv_1 - x_adv) * a + grad2 * (1 - a), x - self._eps, x\n                                      + self._eps), 0.0, 1.0)\n            elif self._norm == 'L2':\n                x_adv_1 = x_adv + step_size * grad / (\n                    ms.ops.square(grad).sum(axis=(1, 2, 3), keepdims=True).sqrt() + 1e-12)\n                x_adv_1 = ops.clip_by_value(x + (x_adv_1 - x) / (\n                    ((x_adv_1 - x) ** 2).sum(axis=(1, 2, 3), keepdims=True).sqrt() + 1e-12) * ops.minimum(\n                        self._eps * ops.ones(x.shape, type=ms.float32),\n                        ((x_adv_1 - x) ** 2).sum(axis=(1, 2, 3), keepdims=True).sqrt()),\n                                            0.0, 1.0)\n                x_adv_1 = x_adv + (x_adv_1 - x_adv) * a + grad2 * (1 - a)\n                x_adv_1 = ops.clip_by_value(x + (x_adv_1 - x) / (\n                    ((x_adv_1 - x) ** 2).sum(axis=(1, 2, 3), keepdims=True).sqrt() + 1e-12) * ops.minimum(\n                        self._eps * ops.ones(x.shape, type=ms.float32),\n                        ((x_adv_1 - x) ** 2).sum(axis=(1, 2, 3), keepdims=True).sqrt() + 1e-12), 0.0, 1.0)\n            x_adv = x_adv_1 + 0.\n            grad = ops.zeros_like(x)\n            for _ in range(self._eot_iter):\n                grad += GradWrapWithLoss(WithLossCell(self._network, self._loss_fn))(x_adv, y)\n            grad /= float(self._eot_iter)\n            pred = logits.max(1)[1] == y\n            acc = ops.logical_and(acc, pred)\n            acc_steps[i + 1] = acc + 0\n            zero_indices = ops.nonzero(pred == 0).squeeze()\n            x_best_adv[zero_indices] = x_adv[zero_indices] + ops.zeros_like(x_adv[zero_indices])\n            y1 = loss_indiv.copy()\n            loss_steps[i] = y1.asnumpy() + 0\n            ind = (y1 >= loss_best).nonzero().squeeze()\n            x_best[ind] = x_adv[ind].copy()\n            grad_best[ind] = grad[ind].copy()\n            loss_best[ind] = y1[ind] + 0\n            loss_best_steps[i + 1] = loss_best.asnumpy() + 0\n            counter += 1\n\n            if counter == k:\n                fl_oscillation = self._check_oscillation(loss_steps, i, k,\n                                                         k3=self._thr_decr)\n                fl_reduce_no_impr = (~reduced_last_check) * (loss_best_last_check.asnumpy() >= loss_best.asnumpy())\n                fl_oscillation = ~(~fl_oscillation * ~fl_reduce_no_impr)\n                reduced_last_check = np.copy(fl_oscillation)\n                loss_best_last_check = loss_best.copy()\n\n                if np.sum(fl_oscillation) > 0:\n                    step_size_np = step_size.asnumpy()\n                    step_size_np[u[fl_oscillation]] /= 2.0\n                    step_size = ms.Tensor(step_size_np)\n                    fl_oscillation = np.where(fl_oscillation)\n                    fl_oscillation = ms.Tensor(fl_oscillation)\n                    x_adv[fl_oscillation] = x_best[fl_oscillation].copy()\n                    grad[fl_oscillation] = grad_best[fl_oscillation].copy()\n                counter = 0\n                k = np.maximum(k - size_decr, steps_min)\n        return x_best\n\n    def _check_oscillation(self, x, j, k, k3=0.75):\n        \"\"\"\n        This function checks if there is oscillation in a given set of numbers. It counts how many\n        times the numbers go up in a certain range around a specific number. If this count is less\n        than or equal to a certain threshold, there is no oscillation. Otherwise, there is oscillation.\n        \"\"\"\n        t = np.zeros(x.shape[1])\n        for counter in range(k):\n            t += x[j - counter] > x[j - counter - 1]\n        return t <= k * k3 * np.ones(t.shape)\n\n\nclass DiverseInputIterativeMethod(BasicIterativeMethod):\n    \"\"\"\n    The Diverse Input Iterative Method attack follows the basic iterative method,\n    and applies random transformation to the input data at each iteration. Such transformation\n    on the input data could improve the transferability of the adversarial examples.\n\n    References: `Xie, Cihang and Zhang, et al., \"Improving Transferability of\n    Adversarial Examples With Input Diversity,\" in CVPR, 2019 <https://arxiv.org/abs/1803.06978>`_.\n\n    Args:\n        network (Cell): Target model.\n        eps (float): Proportion of adversarial perturbation generated by the\n            attack to data range. Default: ``0.3``.\n        bounds (tuple): Upper and lower bounds of data, indicating the data range.\n            In form of (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n        is_targeted (bool): If ``True``, targeted attack. If ``False``, untargeted\n            attack. Default: ``False``.\n        prob (float): Transformation probability. Default: ``0.5``.\n        loss_fn (Union[Loss, None]): Loss function for optimization. If ``None``, the input network \\\n            is already equipped with loss function. Default: ``None``.\n\n    Examples:\n        >>> from mindspore.ops import operations as P\n        >>> from mindarmour.adv_robustness.attacks import DiverseInputIterativeMethod\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         return out\n        >>> net = Net()\n        >>> attack = DiverseInputIterativeMethod(net, loss_fn=nn.SoftmaxCrossEntropyWithLogits(sparse=False))\n        >>> inputs = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n        >>> labels = np.asarray([2],np.int32)\n        >>> labels = np.eye(3)[labels].astype(np.float32)\n        >>> net = Net()\n        >>> adv_x = attack.generate(inputs, labels)\n    \"\"\"\n    def __init__(self, network, eps=0.3, bounds=(0.0, 1.0),\n                 is_targeted=False, prob=0.5, loss_fn=None):\n        # reference to paper hyper parameters setting.\n        eps_iter = 16*2/255\n        nb_iter = int(min(eps*255 + 4, 1.25*255*eps))\n        super(DiverseInputIterativeMethod, self).__init__(network,\n                                                          eps=eps,\n                                                          eps_iter=eps_iter,\n                                                          bounds=bounds,\n                                                          is_targeted=is_targeted,\n                                                          nb_iter=nb_iter,\n                                                          loss_fn=loss_fn)\n        self._prob = check_param_type('prob', prob, float)\n\n\nclass MomentumDiverseInputIterativeMethod(MomentumIterativeMethod):\n    \"\"\"\n    The Momentum Diverse Input Iterative Method attack is a momentum iterative method,\n    and applies random transformation to the input data at each iteration. Such transformation\n    on the input data could improve the transferability of the adversarial examples.\n\n\n    References: `Xie, Cihang and Zhang, et al., \"Improving Transferability of\n    Adversarial Examples With Input Diversity,\" in CVPR, 2019 <https://arxiv.org/abs/1803.06978>`_.\n\n    Args:\n        network (Cell): Target model.\n        eps (float): Proportion of adversarial perturbation generated by the\n            attack to data range. Default: ``0.3``.\n        bounds (tuple): Upper and lower bounds of data, indicating the data range.\n            In form of (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n        is_targeted (bool): If ``True``, targeted attack. If ``False``, untargeted\n            attack. Default: ``False``.\n        norm_level (Union[int, str, numpy.inf]): Order of the norm. Possible values:\n            np.inf, 1 or 2. Default: ``'l1'``.\n        prob (float): Transformation probability. Default: ``0.5``.\n        loss_fn (Union[Loss, None]): Loss function for optimization. If ``None``, the input network \\\n            is already equipped with loss function. Default: ``None``.\n\n    Examples:\n        >>> from mindspore.ops import operations as P\n        >>> from mindarmour.adv_robustness.attacks import MomentumDiverseInputIterativeMethod\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         return out\n        >>> net = Net()\n        >>> attack = MomentumDiverseInputIterativeMethod(net, loss_fn=nn.SoftmaxCrossEntropyWithLogits(sparse=False))\n        >>> inputs = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n        >>> labels = np.asarray([2],np.int32)\n        >>> labels = np.eye(3)[labels].astype(np.float32)\n        >>> net = Net()\n        >>> adv_x = attack.generate(inputs, labels)\n       \"\"\"\n    def __init__(self, network, eps=0.3, bounds=(0.0, 1.0),\n                 is_targeted=False, norm_level='l1', prob=0.5, loss_fn=None):\n        eps_iter = 16*2 / 255\n        nb_iter = int(min(eps*255 + 4, 1.25*255*eps))\n        super(MomentumDiverseInputIterativeMethod, self).__init__(network=network,\n                                                                  eps=eps,\n                                                                  eps_iter=eps_iter,\n                                                                  bounds=bounds,\n                                                                  nb_iter=nb_iter,\n                                                                  is_targeted=is_targeted,\n                                                                  norm_level=norm_level,\n                                                                  loss_fn=loss_fn)\n        self._prob = check_param_type('prob', prob, float)\n\n\ndef _transform_inputs(inputs, prob, low=29, high=33, full_aug=False):\n    \"\"\"\n    Inputs data augmentation.\n\n    Args:\n        inputs (Union[np.int8, np.float]): Inputs.\n        prob (float): The probability of augmentation.\n        low (int): Lower bound of resize image width. Default: 29.\n        high (int): Upper bound of resize image height. Default: 33.\n        full_aug (bool): type of augmentation method, use interpolation and padding\n            as default. Default: ``False``.\n\n    Returns:\n        numpy.ndarray, the augmentation data.\n    \"\"\"\n    raw_shape = inputs[0].shape\n    tran_mask = np.random.uniform(0, 1, size=inputs.shape[0]) < prob\n    tran_inputs = inputs[tran_mask]\n    raw_inputs = inputs[tran_mask == 0]\n    tran_outputs = []\n    for sample in tran_inputs:\n        width = np.random.choice(np.arange(low, high))\n        # resize\n        sample = (sample*255).astype(np.uint8)\n        d_image = Image.fromarray(sample, mode='L').resize((width, width), Image.NEAREST)\n        # pad\n        left_pad = (raw_shape[0] - width) // 2\n        right_pad = raw_shape[0] - width - left_pad\n        top_pad = (raw_shape[1] - width) // 2\n        bottom_pad = raw_shape[1] - width - top_pad\n        p_sample = ImageOps.expand(d_image,\n                                   border=(left_pad, top_pad, right_pad, bottom_pad))\n        tran_outputs.append(np.array(p_sample).astype(np.float) / 255)\n    if full_aug:\n        # gaussian noise\n        tran_outputs = np.random.normal(np.array(tran_outputs).shape) + tran_outputs\n    tran_outputs.extend(raw_inputs)\n    if not np.any(tran_outputs-raw_inputs):\n        LOGGER.error(TAG, 'the transform function does not take effect.')\n    return tran_outputs\n\n\nclass VarianceTuningMomentumIterativeMethod(MomentumIterativeMethod):\n    \"\"\"\n    VMI-FGSM is a momentum iterative method, it aggregate the gradient with variance on the input data\n    in each iteration, and could improve the transferability of the adversarial examples.\n\n\n    Reference: `X Wang, H Kun, \"Enhancing the Transferability of Adversarial Attacks through Variance Tuning\"\n    in CVPR, 2021 <https://arxiv.org/abs/2103.15571>`_.\n\n    Args:\n        network (Cell): Target model.\n        eps (float): Proportion of adversarial perturbation generated by the\n            attack to data range. Default: ``0.3``.\n        eps_iter (float): The proportion of perturbation in each step. Default: ``0.1``.\n        bounds (tuple): Upper and lower bounds of data, indicating the data range.\n            In form of (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n        is_targeted (bool): If ``True``, targeted attack. If ``False``, untargeted\n            attack. Default: ``False``.\n        nb_iter (int) : Number of iteration. Default: ``5``.\n        decay_factor (float): The momentum factor. Default: ``1.0``.\n        nb_neighbor (int): The number of sampled examples in the neighborhood.\n        neighbor_beta (float): The upper bound of neighborhood. Default: ``3/2``.\n        norm_level (Union[int, str, numpy.inf]): Order of the norm. Possible values:\n            np.inf, 1 or 2. Default: ``inf``.\n        loss_fn (Union[Loss, None]): Loss function for optimization. If ``None``, the input network \\\n            is already equipped with loss function. Default: ``None``.\n    Examples:\n        >>> from mindspore.ops import operations as P\n        >>> from mindarmour.adv_robustness.attacks import VarianceTuningMomentumIterativeMethod\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         return out\n        >>> net = Net()\n        >>> loss_fn=nn.SoftmaxCrossEntropyWithLogits(sparse=False)\n        >>> attack = VarianceTuningMomentumIterativeMethod(net, nb_neighbor=5, neighbor_beta=3/2, loss_fn=loss_fn)\n        >>> inputs = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n        >>> labels = np.asarray([2],np.int32)\n        >>> labels = np.eye(3)[labels].astype(np.float32)\n        >>> net = Net()\n        >>> adv_x = attack.generate(inputs, labels)\n    \"\"\"\n\n    def __init__(self, network, eps=0.3, eps_iter=0.1, bounds=(0.0, 1.0),\n                 is_targeted=False, nb_iter=5, decay_factor=1.0, nb_neighbor=5, neighbor_beta=3 / 2,\n                 norm_level='inf', loss_fn=None):\n        super(VarianceTuningMomentumIterativeMethod, self).__init__(network,\n                                                                    eps=eps,\n                                                                    eps_iter=eps_iter,\n                                                                    bounds=bounds,\n                                                                    nb_iter=nb_iter,\n                                                                    loss_fn=loss_fn)\n        self._is_targeted = check_param_type('is_targeted', is_targeted, bool)\n        self._decay_factor = check_value_positive('decay_factor', decay_factor)\n        self._norm_level = check_norm_level(norm_level)\n        self._nb_neighbor = check_int_positive('nb_neighbor', nb_neighbor)\n        self._neighbor_beta = check_value_positive('neighbor_beta', neighbor_beta)\n\n    def generate(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples based on input data and origin/target labels.\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Benign input samples used as references to\n                create adversarial examples.\n            labels (Union[numpy.ndarray, tuple]): Original/target labels. \\\n                For each input if it has more than one label, it is wrapped in a tuple.\n\n        Returns:\n            numpy.ndarray, generated adversarial examples.\n        \"\"\"\n        inputs_image, inputs, labels = check_inputs_labels(inputs, labels)\n        ndim = np.ndim(inputs_image)\n        if ndim < 4:\n            for _ in range(4-ndim):\n                inputs_image = np.expand_dims(inputs_image, axis=0)\n\n        momentum = 0\n        v = 0\n        adv_x = copy.deepcopy(inputs_image)\n\n        clip_min, clip_max = self._bounds\n        clip_diff = clip_max - clip_min\n        for _ in range(self._nb_iter):\n            adv_grad = self._gradient(adv_x, labels)\n            grad = (adv_grad + v) / (np.mean(np.abs(adv_x + v), axis=(1, 2, 3), keepdims=True) + 1e-12)\n\n            grad = grad + momentum * self._decay_factor\n            momentum = grad\n            gv_grad = 0\n            for _ in range(self._nb_neighbor):\n                neighbor_x = adv_x + np.random.uniform(-self._neighbor_beta * self._eps,\n                                                       self._eps * self._neighbor_beta,\n                                                       size=inputs_image.shape).astype(np.float32)\n                gv_grad = self._gradient(neighbor_x, labels) + gv_grad\n            v = gv_grad / self._nb_neighbor - adv_grad\n            adv_x = adv_x + self._eps_iter * np.sign(grad)\n            perturs = np.clip(adv_x - inputs_image, (0 - self._eps) * clip_diff,\n                              self._eps * clip_diff)\n            adv_x = inputs_image + perturs\n        return adv_x\n\n\nclass VarianceTuningNesterovIterativeMethod(MomentumIterativeMethod):\n    \"\"\"\n    VNI-FGSM algorithm is an iterative gradient-based adversarial attack method.\n    Compared with VMI-FGSM,VNI-FGSM uses not only the current gradient but also the average gradient of\n    all previous iterations in each iteration, thus increasing the stability and robustness of the attack.\n    Experimental results show that the attack mobility can be improved by more than 30%, and VNI-FGSM\n    has a higher attack success rate against the training model compared to the VMI-FGSM algorithm.\n\n    References: VNI-FGSM in the paper Enhancing the Transferability of Adversarial\n    Attacks through Variance Tuning [https://arxiv.org/abs/2103.15571], published as\n    a conference paper at CVPR 2021 Modified from \"https://github.com/JHL-HUST/VT\"\n\n    Args:\n        network (Cell): Target model.\n        eps (float): Proportion of adversarial perturbation generated by the\n            attack to data range. Default: ``8/255``.\n        eps_iter (float): The proportion of perturbation in each step. Default: ``2/255``.\n        bounds (tuple): Upper and lower bounds of data, indicating the data range.\n            In form of (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n        is_targeted (bool): If ``True``, targeted attack. If ``False``, untargeted\n            attack. Default: ``False``.\n        nb_iter (int) : Number of iteration. Default: ``10``.\n        decay_factor (float): The momentum factor. Default: ``1.0``.\n        nb_neighbor (int): The number of sampled examples in the neighborhood.\n        neighbor_beta (float): The upper bound of neighborhood. Default: ``3/2``.\n        norm_level (Union[int, str, numpy.inf]): Order of the norm. Possible values:\n            ``numpy.inf`` , ``1``, ``2``, ``'1'``, ``'2'``, ``'l1'``, ``'l2'``, ``'np.inf'``,\n            ``'inf'`` or ``'linf'``. Default: ``'inf'``.\n        loss_fn (Union[Loss, None]): Loss function for optimization. If ``None``, the input network\n            is already equipped with loss function. Default: ``None``.\n\n    Examples:\n        >>> import mindspore.ops as ops\n        >>> from mindarmour.adv_robustness.attacks import VarianceTuningNesterovIterativeMethod\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = ops.Softmax()\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         return out\n        >>> net = Net()\n        >>> attack = VarianceTuningNesterovIterativeMethod(net, nb_neighbor=5, neighbor_beta=3/2,\n        ...             loss_fn=nn.SoftmaxCrossEntropyWithLogits(sparse=False))\n        >>> inputs = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n        >>> labels = np.asarray([2],np.int32)\n        >>> labels = np.eye(3)[labels].astype(np.float32)\n        >>> net = Net()\n        >>> adv_x = attack.generate(inputs, labels)\n    \"\"\"\n\n    def __init__(self, network, eps=8/255, eps_iter=2/255, bounds=(0.0, 1.0),\n                 is_targeted=False, nb_iter=10, decay_factor=1.0, nb_neighbor=5, neighbor_beta=3/2,\n                 norm_level='inf', loss_fn=None):\n        super(VarianceTuningNesterovIterativeMethod, self).__init__(network,\n                                                                    eps=eps,\n                                                                    eps_iter=eps_iter,\n                                                                    bounds=bounds,\n                                                                    nb_iter=nb_iter,\n                                                                    loss_fn=loss_fn)\n        self._is_targeted = check_param_type('is_targeted', is_targeted, bool)\n        self._decay_factor = check_value_positive('decay_factor', decay_factor)\n        self._norm_level = check_norm_level(norm_level)\n        self._nb_neighbor = check_int_positive('nb_neighbor', nb_neighbor)\n        self._neighbor_beta = check_value_positive('neighbor_beta', neighbor_beta)\n\n    def generate(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples based on input data and origin/target labels.\n\n        Args:\n            inputs (Union[numpy.ndarray, tuple]): Benign input samples used as references to\n                create adversarial examples.\n            labels (Union[numpy.ndarray, tuple]): Original/target labels.\n                For each input if it has more than one label, it is wrapped in a tuple.\n\n        Returns:\n            numpy.ndarray, generated adversarial examples.\n        \"\"\"\n\n        inputs_image, inputs, labels = check_inputs_labels(inputs, labels)\n        ndim = np.ndim(inputs_image)\n        if ndim < 4:\n            for _ in range(4-ndim):\n                inputs_image = np.expand_dims(inputs_image, axis=0)\n        momentum = 0\n        v = 0\n        adv_x = copy.deepcopy(inputs_image)\n        clip_min, clip_max = self._bounds\n        clip_diff = clip_max - clip_min\n        for _ in range(self._nb_iter):\n            nes_images = adv_x + self._decay_factor * self._eps_iter * momentum\n            adv_grad = self._gradient(nes_images, labels)\n            grad = (adv_grad + v) / (np.mean(np.abs(adv_x + v), axis=(1, 2, 3), keepdims=True) + 1e-12)\n            grad = grad + momentum * self._decay_factor\n            momentum = grad\n            gv_grad = 0\n            for _ in range(self._nb_neighbor):\n                neighbor_x = adv_x + np.random.uniform(-self._neighbor_beta * self._eps,\n                                                       self._eps * self._neighbor_beta,\n                                                       size=inputs_image.shape).astype(np.float32)\n                gv_grad = self._gradient(neighbor_x, labels) + gv_grad\n            v = gv_grad / self._nb_neighbor - adv_grad\n            adv_x = adv_x + self._eps_iter * np.sign(grad)\n            perturs = np.clip(adv_x - inputs_image, (0 - self._eps) * clip_diff,\n                              self._eps * clip_diff)\n            adv_x = inputs_image + perturs\n        return adv_x\n"
  },
  {
    "path": "mindarmour/adv_robustness/attacks/jsma.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nJSMA-Attack.\n\"\"\"\nimport numpy as np\n\nfrom mindspore import Tensor\nfrom mindspore.nn import Cell\n\nfrom mindarmour.utils.util import GradWrap, jacobian_matrix\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_pair_numpy_param, check_model, \\\n    check_param_type, check_int_positive, check_value_positive, \\\n    check_value_non_negative\nfrom .attack import Attack\n\nLOGGER = LogUtil.get_instance()\nTAG = 'JSMA'\n\n\nclass JSMAAttack(Attack):\n    \"\"\"\n    Jacobian-based Saliency Map Attack is a targeted and iterative attack based on saliency\n    map of the input features. It uses the gradient of loss with each class labels with respect\n    to every component of the input. Then a saliency map is used to select the dimension which\n    produces the maximum error.\n\n    Reference: `The limitations of deep learning in adversarial settings\n    <https://arxiv.org/abs/1511.07528>`_\n\n    Args:\n        network (Cell): Target model.\n        num_classes (int): Number of labels of model output, which should be\n            greater than zero.\n        box_min (float): Lower bound of input of the target model. Default: ``0``.\n        box_max (float): Upper bound of input of the target model. Default: ``1.0``.\n        theta (float): Change ratio of one pixel (relative to\n               input data range). Default: ``1.0``.\n        max_iteration (int): Maximum round of iteration. Default: ``1000``.\n        max_count (int): Maximum times to change each pixel. Default: ``3``.\n        increase (bool): If ``True``, increase perturbation. If ``False``, decrease\n            perturbation. Default: ``True``.\n        sparse (bool): If ``True``, input labels are sparse-coded. If ``False``,\n            input labels are onehot-coded. Default: ``True``.\n\n    Examples:\n        >>> from mindarmour.adv_robustness.attacks import JSMAAttack\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._relu = nn.ReLU()\n        ...     def construct(self, inputs):\n        ...         out = self._relu(inputs)\n        ...         return out\n        >>> net = Net()\n        >>> input_shape = (1, 5)\n        >>> batch_size, classes = input_shape\n        >>> input_np = np.random.random(input_shape).astype(np.float32)\n        >>> label_np = np.random.randint(classes, size=batch_size)\n        >>> attack = JSMAAttack(net, classes, max_iteration=5)\n        >>> advs = attack.generate(input_np, label_np)\n    \"\"\"\n\n    def __init__(self, network, num_classes, box_min=0.0, box_max=1.0,\n                 theta=1.0, max_iteration=1000, max_count=3, increase=True,\n                 sparse=True):\n        super(JSMAAttack).__init__()\n        LOGGER.debug(TAG, \"init jsma class.\")\n        self._network = check_model('network', network, Cell)\n        self._network.set_grad(True)\n        self._min = check_value_non_negative('box_min', box_min)\n        self._max = check_value_non_negative('box_max', box_max)\n        self._num_classes = check_int_positive('num_classes', num_classes)\n        self._theta = check_value_positive('theta', theta)\n        self._max_iter = check_int_positive('max_iteration', max_iteration)\n        self._max_count = check_int_positive('max_count', max_count)\n        self._increase = check_param_type('increase', increase, bool)\n        self._net_grad = GradWrap(self._network)\n        self._bit_map = None\n        self._sparse = check_param_type('sparse', sparse, bool)\n\n    def _saliency_map(self, data, bit_map, target):\n        \"\"\"\n        Compute the saliency map of all pixels.\n\n        Args:\n            data (numpy.ndarray): Input sample.\n            bit_map (numpy.ndarray): Bit map to control modify frequency of\n                each pixel.\n            target (int): Target class.\n\n        Returns:\n            tuple, indices of selected pixel to modify.\n\n        Examples:\n            >>> p1_ind, p2_ind = self._saliency_map([0.2, 0.3, 0.5],\n            >>>                                     [1, 0, 1], 1)\n        \"\"\"\n        jaco_grad = jacobian_matrix(self._net_grad, data, self._num_classes)\n        jaco_grad = jaco_grad.reshape(self._num_classes, -1)\n        alpha = jaco_grad[target]*bit_map\n        alpha_trans = np.reshape(alpha, (alpha.shape[0], 1))\n        alpha_two_dim = alpha + alpha_trans\n        # pixel influence on other classes except target class\n        other_grads = [jaco_grad[class_ind] for class_ind in range(\n            self._num_classes)]\n        beta = np.sum(other_grads, axis=0)*bit_map - alpha\n        beta_trans = np.reshape(beta, (beta.shape[0], 1))\n        beta_two_dim = beta + beta_trans\n\n        if self._increase:\n            alpha_two_dim = (alpha_two_dim > 0)*alpha_two_dim\n            beta_two_dim = (beta_two_dim < 0)*beta_two_dim\n        else:\n            alpha_two_dim = (alpha_two_dim < 0)*alpha_two_dim\n            beta_two_dim = (beta_two_dim > 0)*beta_two_dim\n\n        sal_map = (-1*alpha_two_dim*beta_two_dim)\n        two_dim_index = np.argmax(sal_map)\n        p1_ind = two_dim_index % len(data.flatten())\n        p2_ind = two_dim_index // len(data.flatten())\n        return p1_ind, p2_ind\n\n    def _generate_one(self, data, target):\n        \"\"\"\n        Generate one adversarial example.\n\n        Args:\n            data (numpy.ndarray): Input sample (only one).\n            target (int): Target label.\n\n        Returns:\n            numpy.ndarray, adversarial example or zeros (if failed).\n\n        Examples:\n            >>> adv = self._generate_one([0.2, 0.3 ,0.4], 1)\n        \"\"\"\n        ori_shape = data.shape\n        temp = data.flatten()\n        bit_map = np.ones_like(temp)\n        counter = np.zeros_like(temp)\n        perturbed = np.copy(temp)\n        for _ in range(self._max_iter):\n            pre_logits = self._network(Tensor(np.expand_dims(\n                perturbed.reshape(ori_shape), axis=0)))\n            per_pred = np.argmax(pre_logits.asnumpy())\n            if per_pred == target:\n                LOGGER.debug(TAG, 'find one adversarial sample successfully.')\n                return perturbed.reshape(ori_shape)\n            if np.all(bit_map == 0):\n                LOGGER.debug(TAG, 'fail to find adversarial sample')\n                return perturbed.reshape(ori_shape)\n            p1_ind, p2_ind = self._saliency_map(perturbed.reshape(\n                ori_shape)[np.newaxis, :], bit_map, target)\n            if self._increase:\n                perturbed[p1_ind] += self._theta*(self._max - self._min)\n                perturbed[p2_ind] += self._theta*(self._max - self._min)\n            else:\n                perturbed[p1_ind] -= self._theta*(self._max - self._min)\n                perturbed[p2_ind] -= self._theta*(self._max - self._min)\n            counter[p1_ind] += 1\n            counter[p2_ind] += 1\n            if (perturbed[p1_ind] >= self._max) or (\n                    perturbed[p1_ind] <= self._min) \\\n                    or (counter[p1_ind] > self._max_count):\n                bit_map[p1_ind] = 0\n            if (perturbed[p2_ind] >= self._max) or (\n                    perturbed[p2_ind] <= self._min) \\\n                    or (counter[p2_ind] > self._max_count):\n                bit_map[p2_ind] = 0\n            perturbed = np.clip(perturbed, self._min, self._max)\n        LOGGER.debug(TAG, 'fail to find adversarial sample.')\n        return perturbed.reshape(ori_shape)\n\n    def generate(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples in batch.\n\n        Args:\n            inputs (numpy.ndarray): Input samples.\n            labels (numpy.ndarray): Target labels.\n\n        Returns:\n            numpy.ndarray, adversarial samples.\n        \"\"\"\n        inputs, labels = check_pair_numpy_param('inputs', inputs,\n                                                'labels', labels)\n        if not self._sparse:\n            labels = np.argmax(labels, axis=1)\n        LOGGER.debug(TAG, 'start to generate adversarial samples.')\n        res = []\n        for i in range(inputs.shape[0]):\n            res.append(self._generate_one(inputs[i], labels[i]))\n        LOGGER.debug(TAG, 'finished.')\n        return np.asarray(res)\n"
  },
  {
    "path": "mindarmour/adv_robustness/attacks/lbfgs.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nLBFGS-Attack.\n\"\"\"\nimport numpy as np\nimport scipy.optimize as so\n\nfrom mindspore import Tensor\nfrom mindspore.nn import Cell\nfrom mindspore.nn import SoftmaxCrossEntropyWithLogits\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils.util import WithLossCell, GradWrapWithLoss\nfrom mindarmour.utils._check_param import check_pair_numpy_param, check_model, \\\n    check_int_positive, check_value_positive, check_param_type, \\\n    check_param_multi_types\nfrom .attack import Attack\n\nLOGGER = LogUtil.get_instance()\nTAG = 'LBFGS'\n\n\nclass LBFGS(Attack):\n    \"\"\"\n    In L-BFGS-B attack, the Limited-Memory BFGS optimizaiton algorithm is used\n    to minimize the distance between the inputs and the adversarial examples.\n\n    References: `Pedro Tabacof, Eduardo Valle. \"Exploring the Space of\n    Adversarial Images\" <https://arxiv.org/abs/1510.05328>`_\n\n    Args:\n        network (Cell): The network of attacked model.\n        eps (float): Attack step size. Default: ``1e-5``.\n        bounds (tuple): Upper and lower bounds of data. Default: ``(0.0, 1.0)``.\n        is_targeted (bool): If ``True``, targeted attack. If ``False``, untargeted\n            attack. Default: ``True``.\n        nb_iter (int): Number of iteration of lbfgs-optimizer, which should be\n            greater than zero. Default: ``150``.\n        search_iters (int): Number of changes in step size, which should be\n            greater than zero. Default: ``30``.\n        loss_fn (Functions): Loss function of substitute model. Default: ``None``.\n        sparse (bool): If True, input labels are sparse-coded. If ``False``,\n            input labels are onehot-coded. Default: ``False``.\n\n    Examples:\n        >>> from mindarmour.adv_robustness.attacks import LBFGS\n        >>> import mindspore.ops.operations as P\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...         self._reduce = P.ReduceSum()\n        ...         self._squeeze = P.Squeeze(1)\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         out = self._reduce(out, 2)\n        ...         out = self._squeeze(out)\n        ...         return out\n        >>> net = Net()\n        >>> classes = 10\n        >>> attack = LBFGS(net, is_targeted=True)\n        >>> input_np = np.asarray(np.random.random((1,1,32,32)), np.float32)\n        >>> label_np = np.array([3]).astype(np.int64)\n        >>> target_np = np.array([7]).astype(np.int64)\n        >>> target_np = np.eye(10)[target_np].astype(np.float32)\n        >>> adv = attack.generate(input_np, target_np)\n    \"\"\"\n    def __init__(self, network, eps=1e-5, bounds=(0.0, 1.0), is_targeted=True,\n                 nb_iter=150, search_iters=30, loss_fn=None, sparse=False):\n        super(LBFGS, self).__init__()\n        self._network = check_model('network', network, Cell)\n        self._eps = check_value_positive('eps', eps)\n        self._is_targeted = check_param_type('is_targeted', is_targeted, bool)\n        self._nb_iter = check_int_positive('nb_iter', nb_iter)\n        self._search_iters = check_int_positive('search_iters', search_iters)\n        if loss_fn is None:\n            loss_fn = SoftmaxCrossEntropyWithLogits(sparse=False)\n        with_loss_cell = WithLossCell(self._network, loss_fn)\n        self._grad_all = GradWrapWithLoss(with_loss_cell)\n        self._dtype = None\n        self._bounds = check_param_multi_types('bounds', bounds, [list, tuple])\n        self._sparse = check_param_type('sparse', sparse, bool)\n        for b in self._bounds:\n            _ = check_param_multi_types('bound', b, [int, float])\n        box_max, box_min = bounds\n        if box_max < box_min:\n            self._box_min = box_max\n            self._box_max = box_min\n        else:\n            self._box_min = box_min\n            self._box_max = box_max\n\n    def generate(self, inputs, labels):\n        \"\"\"\n        Generate adversarial examples based on input data and target labels.\n\n        Args:\n            inputs (numpy.ndarray): Benign input samples used as references to create\n                adversarial examples.\n            labels (numpy.ndarray): Original/target labels.\n\n        Returns:\n            numpy.ndarray, generated adversarial examples.\n        \"\"\"\n        LOGGER.debug(TAG, 'start to generate adv image.')\n        arr_x, arr_y = check_pair_numpy_param('inputs', inputs, 'labels', labels)\n        self._dtype = arr_x.dtype\n        adv_list = list()\n        for original_x, label_y in zip(arr_x, arr_y):\n            adv_list.append(self._optimize(\n                original_x, label_y, epsilon=self._eps))\n        return np.array(adv_list)\n\n    def _forward_one(self, cur_input):\n        \"\"\"Forward one sample in model.\"\"\"\n        cur_input = np.expand_dims(cur_input, axis=0)\n        out_logits = self._network(Tensor(cur_input)).asnumpy()\n        return out_logits\n\n    def _gradient(self, cur_input, labels, shape):\n        \"\"\" Return model gradient to minimize loss in l-bfgs-b.\"\"\"\n        label_dtype = labels.dtype\n        labels = np.expand_dims(labels, axis=0).astype(label_dtype)\n        # input shape should like original shape\n        reshape_input = np.expand_dims(cur_input.reshape(shape),\n                                       axis=0)\n        out_grad = self._grad_all(Tensor(reshape_input), Tensor(labels))\n        if isinstance(out_grad, tuple):\n            out_grad = out_grad[0]\n        return out_grad.asnumpy()\n\n    def _loss(self, cur_input, start_input, cur_eps, shape, labels):\n        \"\"\"\n        The l-bfgs-b loss is the sum of l2 distances to the original input plus\n        the cross-entropy loss.\n        \"\"\"\n        cur_input = cur_input.astype(self._dtype)\n        l2_distance = np.linalg.norm(\n            cur_input.reshape((cur_input.shape[0], -1)) - start_input.reshape(\n                (start_input.shape[0], -1)))\n        logits = self._forward_one(cur_input.reshape(shape)).flatten()\n        logits = logits - np.max(logits)\n        if self._sparse:\n            target_class = labels\n        else:\n            target_class = np.argmax(labels)\n        if self._is_targeted:\n            crossentropy = np.log(np.sum(np.exp(logits))) - logits[target_class]\n            gradient = self._gradient(cur_input, labels, shape).flatten()\n        else:\n            crossentropy = logits[target_class] - np.log(np.sum(np.exp(logits)))\n            gradient = -self._gradient(cur_input, labels, shape).flatten()\n\n        return (l2_distance + cur_eps*crossentropy).astype(self._dtype), \\\n               gradient.astype(np.float64)\n\n    def _lbfgsb(self, start_input, cur_eps, shape, labels, bounds):\n        \"\"\"\n        A wrapper.\n        Method reference to `scipy.optimize.fmin_l_bfgs_b`_\n\n        .. _`scipy.optimize.fmin_l_bfgs_b`: https://docs.scipy.org/doc/scipy/\n        reference/generated/scipy.optimize.fmin_l_bfgs_b.html\n        \"\"\"\n        approx_grad_eps = (self._box_max - self._box_min) / 100\n        max_matrix_variable = 15\n        cur_input, _, detail_info = so.fmin_l_bfgs_b(\n            self._loss,\n            start_input,\n            args=(start_input, cur_eps, shape, labels),\n            approx_grad=False,\n            bounds=bounds,\n            m=max_matrix_variable,\n            maxiter=self._nb_iter,\n            epsilon=approx_grad_eps)\n\n        LOGGER.debug(TAG, str(detail_info))\n        # LBFGS-B does not always exactly respect the boundaries\n        if np.amax(cur_input) > self._box_max or np.amin(\n                cur_input) < self._box_min:  # pragma: no coverage\n            LOGGER.debug(TAG,\n                         'Input out of bounds (min, max = %s, %s).'\n                         ' Performing manual clip.',\n                         np.amin(cur_input),\n                         np.amax(cur_input))\n            cur_input = np.clip(cur_input, self._box_min, self._box_max)\n        cur_input = cur_input.astype(self._dtype)\n        cur_input = cur_input.reshape(shape)\n        adv_prediction = self._forward_one(cur_input)\n\n        LOGGER.debug(TAG, 'input one sample label is :{}'.format(labels))\n        if not self._sparse:\n            labels = np.argmax(labels)\n        if self._is_targeted:\n            return cur_input, np.argmax(adv_prediction) == labels\n        return cur_input, np.argmax(adv_prediction) != labels\n\n    def _optimize(self, start_input, labels, epsilon):\n        \"\"\"\n        Given loss function and gradient, use l_bfgs_b algorithm to update input\n        sample. The epsilon will be doubled until an adversarial example is found.\n\n        Args:\n            start_input (numpy.ndarray): Benign input samples used as references\n                to create adversarial examples.\n            labels (numpy.ndarray): Target labels.\n            epsilon: (float): Attack step size.\n            max_iter (int): Number of iteration.\n        \"\"\"\n        # store the shape for later and operate on the flattened input\n        ori_shape = start_input.shape\n        start_input = start_input.flatten().astype(self._dtype)\n        bounds = [self._bounds]*len(start_input)\n\n        # finding initial cur_eps\n        iter_c = epsilon\n        for _ in range(self._search_iters):\n            iter_c = 2*iter_c\n            generate_x, is_adversarial = self._lbfgsb(start_input,\n                                                      iter_c,\n                                                      ori_shape,\n                                                      labels,\n                                                      bounds)\n            LOGGER.debug(TAG, 'Tested iter_c = %f', iter_c)\n            if is_adversarial:\n                LOGGER.debug(TAG, 'find adversarial successfully.')\n                return generate_x\n            LOGGER.debug(TAG, 'failed to not adversarial.')\n        return generate_x\n"
  },
  {
    "path": "mindarmour/adv_robustness/defenses/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis module includes classical defense algorithms in defencing adversarial\nexamples and enhancing model security and trustworthy.\n\"\"\"\nfrom .adversarial_defense import AdversarialDefense\nfrom .adversarial_defense import AdversarialDefenseWithAttacks\nfrom .adversarial_defense import EnsembleAdversarialDefense\nfrom .natural_adversarial_defense import NaturalAdversarialDefense\nfrom .projected_adversarial_defense import ProjectedAdversarialDefense\n\n__all__ = ['AdversarialDefense',\n           'AdversarialDefenseWithAttacks',\n           'NaturalAdversarialDefense',\n           'ProjectedAdversarialDefense',\n           'EnsembleAdversarialDefense']\n"
  },
  {
    "path": "mindarmour/adv_robustness/defenses/adversarial_defense.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nAdversarial Defense.\n\"\"\"\nimport numpy as np\n\nfrom mindspore import Tensor\nfrom mindspore.nn import Cell, SoftmaxCrossEntropyWithLogits\nfrom mindspore.nn import WithLossCell, TrainOneStepCell\nfrom mindspore.nn.optim.momentum import Momentum\n\nfrom mindarmour.utils._check_param import check_pair_numpy_param, check_model, \\\n    check_param_in_range, check_param_type, check_param_multi_types\nfrom .defense import Defense\n\n\nclass AdversarialDefense(Defense):\n    \"\"\"\n    Adversarial training using given adversarial examples.\n\n    Args:\n        network (Cell): A MindSpore network to be defensed.\n        loss_fn (Union[Loss, None]): Loss function. Default: ``None``.\n        optimizer (Cell): Optimizer used to train the network. Default: ``None``.\n\n    Examples:\n        >>> from mindspore.nn.optim.momentum import Momentum\n        >>> import mindspore.ops.operations as P\n        >>> from mindarmour.adv_robustness.defenses import AdversarialDefense\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...         self._dense = nn.Dense(10, 10)\n        ...         self._squeeze = P.Squeeze(1)\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         out = self._dense(out)\n        ...         out = self._squeeze(out)\n        ...         return out\n        >>> net = Net()\n        >>> lr = 0.001\n        >>> momentum = 0.9\n        >>> batch_size = 16\n        >>> num_classes = 10\n        >>> loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=False)\n        >>> optimizer = Momentum(net.trainable_params(), learning_rate=lr, momentum=momentum)\n        >>> adv_defense = AdversarialDefense(net, loss_fn, optimizer)\n        >>> inputs = np.random.rand(batch_size, 1, 10).astype(np.float32)\n        >>> labels = np.random.randint(10, size=batch_size).astype(np.int32)\n        >>> labels = np.eye(num_classes)[labels].astype(np.float32)\n        >>> adv_defense.defense(inputs, labels)\n    \"\"\"\n\n    def __init__(self, network, loss_fn=None, optimizer=None):\n        super(AdversarialDefense, self).__init__(network)\n        network = check_model('network', network, Cell)\n        if loss_fn is None:\n            loss_fn = SoftmaxCrossEntropyWithLogits(sparse=True)\n\n        if optimizer is None:\n            optimizer = Momentum(\n                params=network.trainable_params(),\n                learning_rate=0.01,\n                momentum=0.9)\n\n        loss_net = WithLossCell(network, loss_fn)\n        self._train_net = TrainOneStepCell(loss_net, optimizer)\n        self._train_net.set_train()\n\n    def defense(self, inputs, labels):\n        \"\"\"\n        Enhance model via training with input samples.\n\n        Args:\n            inputs (numpy.ndarray): Input samples.\n            labels (numpy.ndarray): Labels of input samples.\n\n        Returns:\n            numpy.ndarray, loss of defense operation.\n        \"\"\"\n        inputs, labels = check_pair_numpy_param('inputs', inputs, 'labels',\n                                                labels)\n        loss = self._train_net(Tensor(inputs), Tensor(labels))\n        return loss.asnumpy()\n\n\nclass AdversarialDefenseWithAttacks(AdversarialDefense):\n    \"\"\"\n    Adversarial training using specific attacking method and the given\n    adversarial examples to enhance model robustness.\n\n    Args:\n        network (Cell): A MindSpore network to be defensed.\n        attacks (list[Attack]): List of attack method.\n        loss_fn (Union[Loss, None]): Loss function. Default: ``None``.\n        optimizer (Cell): Optimizer used to train the network. Default: ``None``.\n        bounds (tuple): Upper and lower bounds of data. In form of (clip_min,\n            clip_max). Default: ``(0.0, 1.0)``.\n        replace_ratio (float): Ratio of replacing original samples with\n            adversarial, which must be between 0 and 1. Default: ``0.5``.\n\n    Raises:\n        ValueError: If replace_ratio is not between 0 and 1.\n\n    Examples:\n        >>> from mindspore.nn.optim.momentum import Momentum\n        >>> import mindspore.ops.operations as P\n        >>> from mindarmour.adv_robustness.attacks import FastGradientSignMethod\n        >>> from mindarmour.adv_robustness.attacks import ProjectedGradientDescent\n        >>> from mindarmour.adv_robustness.defenses import AdversarialDefenseWithAttacks\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...         self._dense = nn.Dense(10, 10)\n        ...         self._squeeze = P.Squeeze(1)\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         out = self._dense(out)\n        ...         out = self._squeeze(out)\n        ...         return out\n        >>> net = Net()\n        >>> lr = 0.001\n        >>> momentum = 0.9\n        >>> batch_size = 16\n        >>> num_classes = 10\n        >>> loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=False)\n        >>> optimizer = Momentum(net.trainable_params(), learning_rate=lr, momentum=momentum)\n        >>> fgsm = FastGradientSignMethod(net, loss_fn=loss_fn)\n        >>> pgd = ProjectedGradientDescent(net, loss_fn=loss_fn)\n        >>> ead = AdversarialDefenseWithAttacks(net, [fgsm, pgd], loss_fn=loss_fn,\n        ...                                     optimizer=optimizer)\n        >>> inputs = np.random.rand(batch_size, 1, 10).astype(np.float32)\n        >>> labels = np.random.randint(10, size=batch_size).astype(np.int32)\n        >>> labels = np.eye(num_classes)[labels].astype(np.float32)\n        >>> loss = ead.defense(inputs, labels)\n    \"\"\"\n\n    def __init__(self, network, attacks, loss_fn=None, optimizer=None,\n                 bounds=(0.0, 1.0), replace_ratio=0.5):\n        super(AdversarialDefenseWithAttacks, self).__init__(network,\n                                                            loss_fn,\n                                                            optimizer)\n        self._attacks = check_param_type('attacks', attacks, list)\n        self._bounds = check_param_multi_types('bounds', bounds, [tuple, list])\n        for elem in self._bounds:\n            _ = check_param_multi_types('bound', elem, [int, float])\n        self._replace_ratio = check_param_in_range('replace_ratio',\n                                                   replace_ratio,\n                                                   0, 1)\n        self._graph_initialized = False\n        self._train_net.set_train()\n\n    def defense(self, inputs, labels):\n        \"\"\"\n        Enhance model via training with adversarial examples generated from input samples.\n\n        Args:\n            inputs (numpy.ndarray): Input samples.\n            labels (numpy.ndarray): Labels of input samples.\n\n        Returns:\n            numpy.ndarray, loss of adversarial defense operation.\n        \"\"\"\n        inputs, labels = check_pair_numpy_param('inputs', inputs, 'labels',\n                                                labels)\n        if not self._graph_initialized:\n            self._train_net(Tensor(inputs), Tensor(labels))\n            self._graph_initialized = True\n\n        x_len = inputs.shape[0]\n        n_adv = int(np.ceil(self._replace_ratio*x_len))\n        n_adv_per_attack = int(n_adv / len(self._attacks))\n\n        adv_ids = np.random.choice(x_len, size=n_adv, replace=False)\n        start = 0\n        for attack in self._attacks:\n            idx = adv_ids[start:start + n_adv_per_attack]\n            inputs[idx] = attack.generate(inputs[idx], labels[idx])\n            start += n_adv_per_attack\n\n        loss = self._train_net(Tensor(inputs), Tensor(labels))\n        return loss.asnumpy()\n\n\nclass EnsembleAdversarialDefense(AdversarialDefenseWithAttacks):\n    \"\"\"\n    Adversarial training using a list of specific attacking methods\n    and the given adversarial examples to enhance model robustness.\n\n    Args:\n        network (Cell): A MindSpore network to be defensed.\n        attacks (list[Attack]): List of attack method.\n        loss_fn (Union[Loss, None]): Loss function. Default: ``None``.\n        optimizer (Cell): Optimizer used to train the network. Default: ``None``.\n        bounds (tuple): Upper and lower bounds of data. In form of (clip_min,\n            clip_max). Default: ``(0.0, 1.0)``.\n        replace_ratio (float): Ratio of replacing original samples with\n            adversarial, which must be between 0 and 1. Default: ``0.5``.\n\n    Raises:\n        ValueError: If replace_ratio is not between 0 and 1.\n\n    Examples:\n        >>> from mindspore.nn.optim.momentum import Momentum\n        >>> import mindspore.ops.operations as P\n        >>> from mindarmour.adv_robustness.attacks import FastGradientSignMethod\n        >>> from mindarmour.adv_robustness.attacks import ProjectedGradientDescent\n        >>> from mindarmour.adv_robustness.defenses import EnsembleAdversarialDefense\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...         self._dense = nn.Dense(10, 10)\n        ...         self._squeeze = P.Squeeze(1)\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         out = self._dense(out)\n        ...         out = self._squeeze(out)\n        ...         return out\n        >>> net = Net()\n        >>> lr = 0.001\n        >>> momentum = 0.9\n        >>> batch_size = 16\n        >>> num_classes = 10\n        >>> loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=False)\n        >>> optimizer = Momentum(net.trainable_params(), learning_rate=lr, momentum=momentum)\n        >>> fgsm = FastGradientSignMethod(net, loss_fn=loss_fn)\n        >>> pgd = ProjectedGradientDescent(net, loss_fn=loss_fn)\n        >>> ead = EnsembleAdversarialDefense(net, [fgsm, pgd], loss_fn=loss_fn,\n        ...                                  optimizer=optimizer)\n        >>> inputs = np.random.rand(batch_size, 1, 10).astype(np.float32)\n        >>> labels = np.random.randint(10, size=batch_size).astype(np.int32)\n        >>> labels = np.eye(num_classes)[labels].astype(np.float32)\n        >>> loss = ead.defense(inputs, labels)\n    \"\"\"\n\n    def __init__(self, network, attacks, loss_fn=None, optimizer=None,\n                 bounds=(0.0, 1.0), replace_ratio=0.5):\n        super(EnsembleAdversarialDefense, self).__init__(network,\n                                                         attacks,\n                                                         loss_fn,\n                                                         optimizer,\n                                                         bounds,\n                                                         replace_ratio)\n"
  },
  {
    "path": "mindarmour/adv_robustness/defenses/defense.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nBase Class of Defense.\n\"\"\"\nfrom abc import abstractmethod\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_pair_numpy_param, \\\n    check_int_positive\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Defense'\n\n\nclass Defense:\n    \"\"\"\n    The abstract base class for all defense classes defending adversarial\n    examples.\n\n    Args:\n        network (Cell): A MindSpore-style deep learning model to be defensed.\n    \"\"\"\n\n    def __init__(self, network):\n        self._network = network\n\n    @abstractmethod\n    def defense(self, inputs, labels):\n        \"\"\"\n        Defense model with samples.\n\n        Args:\n            inputs (numpy.ndarray): Samples based on which adversarial\n                examples are generated.\n            labels (numpy.ndarray): Labels of input samples.\n\n        Raises:\n            NotImplementedError: It is an abstract method.\n        \"\"\"\n        msg = 'The function defense() is an abstract function in class ' \\\n              '`Defense` and should be implemented in child class.'\n        LOGGER.error(TAG, msg)\n        raise NotImplementedError(msg)\n\n    def batch_defense(self, inputs, labels, batch_size=32, epochs=5):\n        \"\"\"\n        Defense model with samples in batch.\n\n        Args:\n            inputs (numpy.ndarray): Samples based on which adversarial\n                examples are generated.\n            labels (numpy.ndarray): Labels of input samples.\n            batch_size (int): Number of samples in one batch. Default: ``32``.\n            epochs (int): Number of epochs. Default: ``5``.\n\n        Returns:\n            numpy.ndarray, loss of batch_defense operation.\n\n        Raises:\n            ValueError: If `batch_size` is 0.\n        \"\"\"\n        inputs, labels = check_pair_numpy_param('inputs', inputs, 'labels',\n                                                labels)\n        x_len = len(inputs)\n        batch_size = check_int_positive('batch_size', batch_size)\n\n        iters_per_epoch = int(x_len / batch_size)\n        loss = None\n        for _ in range(epochs):\n            for step in range(iters_per_epoch):\n                x_batch = inputs[step*batch_size:(step + 1)*batch_size]\n                y_batch = labels[step*batch_size:(step + 1)*batch_size]\n                loss = self.defense(x_batch, y_batch)\n        return loss\n"
  },
  {
    "path": "mindarmour/adv_robustness/defenses/natural_adversarial_defense.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nNatural Adversarial Defense.\n\"\"\"\nfrom ..attacks.gradient_method import FastGradientSignMethod\nfrom .adversarial_defense import AdversarialDefenseWithAttacks\n\n\nclass NaturalAdversarialDefense(AdversarialDefenseWithAttacks):\n    \"\"\"\n    Adversarial training based on FGSM.\n\n    Reference: `A. Kurakin, et al., \"Adversarial machine learning at scale,\" in\n    ICLR, 2017. <https://arxiv.org/abs/1611.01236>`_.\n\n    Args:\n        network (Cell): A MindSpore network to be defensed.\n        loss_fn (Union[Loss, None]): Loss function. Default: ``None``.\n        optimizer (Cell): Optimizer used to train the network. Default: ``None``.\n        bounds (tuple): Upper and lower bounds of data. In form of (clip_min,\n            clip_max). Default: ``(0.0, 1.0)``.\n        replace_ratio (float): Ratio of replacing original samples with\n            adversarial samples. Default: ``0.5``.\n        eps (float): Step size of the attack method(FGSM). Default: ``0.1``.\n\n    Examples:\n        >>> from mindspore.nn.optim.momentum import Momentum\n        >>> import mindspore.ops.operations as P\n        >>> from mindarmour.adv_robustness.defenses import NaturalAdversarialDefense\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...         self._dense = nn.Dense(10, 10)\n        ...         self._squeeze = P.Squeeze(1)\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         out = self._dense(out)\n        ...         out = self._squeeze(out)\n        ...         return out\n        >>> net = Net()\n        >>> lr = 0.001\n        >>> momentum = 0.9\n        >>> batch_size = 16\n        >>> num_classes = 10\n        >>> loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=False)\n        >>> optimizer = Momentum(net.trainable_params(), learning_rate=lr, momentum=momentum)\n        >>> nad = NaturalAdversarialDefense(net, loss_fn=loss_fn, optimizer=optimizer)\n        >>> inputs = np.random.rand(batch_size, 1, 10).astype(np.float32)\n        >>> labels = np.random.randint(10, size=batch_size).astype(np.int32)\n        >>> labels = np.eye(num_classes)[labels].astype(np.float32)\n        >>> loss = nad.defense(inputs, labels)\n    \"\"\"\n    def __init__(self, network, loss_fn=None, optimizer=None,\n                 bounds=(0.0, 1.0), replace_ratio=0.5, eps=0.1):\n        attack = FastGradientSignMethod(network,\n                                        eps=eps,\n                                        alpha=None,\n                                        bounds=bounds,\n                                        loss_fn=loss_fn)\n        super(NaturalAdversarialDefense, self).__init__(\n            network,\n            [attack],\n            loss_fn=loss_fn,\n            optimizer=optimizer,\n            bounds=bounds,\n            replace_ratio=replace_ratio)\n"
  },
  {
    "path": "mindarmour/adv_robustness/defenses/projected_adversarial_defense.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nProjected Adversarial Defense.\n\"\"\"\nfrom ..attacks.iterative_gradient_method import ProjectedGradientDescent\nfrom .adversarial_defense import AdversarialDefenseWithAttacks\n\n\nclass ProjectedAdversarialDefense(AdversarialDefenseWithAttacks):\n    \"\"\"\n    Adversarial training based on PGD.\n\n    Reference: `A. Madry, et al., \"Towards deep learning models resistant to\n    adversarial attacks,\" in ICLR, 2018. <https://arxiv.org/abs/1611.01236>`_.\n\n    Args:\n        network (Cell): A MindSpore network to be defensed.\n        loss_fn (Union[Loss, None]): Loss function. Default: ``None``.\n        optimizer (Cell): Optimizer used to train the nerwork. Default: ``None``.\n        bounds (tuple): Upper and lower bounds of input data. In form of\n            (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n        replace_ratio (float): Ratio of replacing original samples with\n            adversarial samples. Default: ``0.5``.\n        eps (float): PGD attack parameters, epsilon. Default: ``0.3``.\n        eps_iter (int): PGD attack parameters, inner loop epsilon.\n            Default: ``0.1``.\n        nb_iter (int): PGD attack parameters, number of iteration.\n            Default: ``5``.\n        norm_level (Union[int, char, numpy.inf]): Norm type. ``1``, ``2``, ``np.inf``,\n            ``'l1'``, ``'l2'``, ``'np.inf'`` or ``'inf'``. Default: ``'inf'``.\n\n    Examples:\n        >>> from mindspore.nn.optim.momentum import Momentum\n        >>> import mindspore.ops.operations as P\n        >>> from mindarmour.adv_robustness.defenses import ProjectedAdversarialDefense\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...         self._dense = nn.Dense(10, 10)\n        ...         self._squeeze = P.Squeeze(1)\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         out = self._dense(out)\n        ...         out = self._squeeze(out)\n        ...         return out\n        >>> net = Net()\n        >>> lr = 0.001\n        >>> momentum = 0.9\n        >>> batch_size = 16\n        >>> num_classes = 10\n        >>> loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=False)\n        >>> optimizer = Momentum(net.trainable_params(), learning_rate=lr, momentum=momentum)\n        >>> pad = ProjectedAdversarialDefense(net, loss_fn=loss_fn, optimizer=optimizer)\n        >>> inputs = np.random.rand(batch_size, 1, 10).astype(np.float32)\n        >>> labels = np.random.randint(10, size=batch_size).astype(np.int32)\n        >>> labels = np.eye(num_classes)[labels].astype(np.float32)\n        >>> loss = pad.defense(inputs, labels)\n    \"\"\"\n    def __init__(self,\n                 network,\n                 loss_fn=None,\n                 optimizer=None,\n                 bounds=(0.0, 1.0),\n                 replace_ratio=0.5,\n                 eps=0.3,\n                 eps_iter=0.1,\n                 nb_iter=5,\n                 norm_level='inf'):\n        attack = ProjectedGradientDescent(network,\n                                          eps=eps,\n                                          eps_iter=eps_iter,\n                                          nb_iter=nb_iter,\n                                          bounds=bounds,\n                                          norm_level=norm_level,\n                                          loss_fn=loss_fn)\n        super(ProjectedAdversarialDefense, self).__init__(\n            network, [attack], loss_fn=loss_fn, optimizer=optimizer,\n            bounds=bounds, replace_ratio=replace_ratio)\n"
  },
  {
    "path": "mindarmour/adv_robustness/detectors/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis module includes detector methods on distinguishing adversarial examples\nfrom benign examples.\n\"\"\"\nfrom .mag_net import ErrorBasedDetector\nfrom .mag_net import DivergenceBasedDetector\nfrom .ensemble_detector import EnsembleDetector\nfrom .region_based_detector import RegionBasedDetector\nfrom .spatial_smoothing import SpatialSmoothing\nfrom . import black\nfrom .black.similarity_detector import SimilarityDetector\n\n__all__ = ['ErrorBasedDetector',\n           'DivergenceBasedDetector',\n           'RegionBasedDetector',\n           'SpatialSmoothing',\n           'EnsembleDetector',\n           'SimilarityDetector']\n"
  },
  {
    "path": "mindarmour/adv_robustness/detectors/black/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\ninit black detector.\n\"\"\"\n"
  },
  {
    "path": "mindarmour/adv_robustness/detectors/black/similarity_detector.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nSimilarity Detector.\n\"\"\"\nimport itertools\nimport numpy as np\n\nfrom mindspore import Tensor\nfrom mindspore import Model\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_model, check_numpy_param, \\\n    check_int_positive, check_value_positive, check_param_type, \\\n    check_param_in_range\nfrom ..detector import Detector\n\nLOGGER = LogUtil.get_instance()\nTAG = 'SimilarityDetector'\n\n\ndef _pairwise_distances(x_input, y_input):\n    \"\"\"\n    Compute the Euclidean Distance matrix from a vector array x_input and\n    y_input.\n\n    Args:\n        x_input (numpy.ndarray): input data, [n_samples_x, n_features]\n        y_input (numpy.ndarray): input data, [n_samples_y, n_features]\n\n    Returns:\n        numpy.ndarray, distance matrix, [n_samples_a, n_samples_b]\n    \"\"\"\n    out = np.empty((x_input.shape[0], y_input.shape[0]), dtype='float')\n    iterator = itertools.product(\n        range(x_input.shape[0]), range(y_input.shape[0]))\n    for i, j in iterator:\n        out[i, j] = np.linalg.norm(x_input[i] - y_input[j])\n    return out\n\n\nclass SimilarityDetector(Detector):\n    \"\"\"\n    The detector measures similarity among adjacent queries and rejects queries\n    which are remarkably similar to previous queries.\n\n    Reference: `Stateful Detection of Black-Box Adversarial Attacks by Steven\n    Chen, Nicholas Carlini, and David Wagner. at arxiv 2019\n    <https://arxiv.org/abs/1907.05587>`_\n\n    Args:\n        trans_model (Model): A MindSpore model to encode input data into lower\n            dimension vector.\n        max_k_neighbor (int): The maximum number of the nearest neighbors.\n            Default: ``1000``.\n        chunk_size (int): Buffer size. Default: ``1000``.\n        max_buffer_size (int): Maximum buffer size. Default: ``10000``.\n        tuning (bool): Calculate the average distance for the nearest k\n            neighbours, if `tuning` is ``True``, k=K. If ``False`` k=1,...,K.\n            Default: ``False``.\n        fpr (float): False positive ratio on legitimate query sequences.\n            Default: ``0.001``.\n\n    Examples:\n        >>> from mindspore.ops.operations import Add\n        >>> from mindspore.nn import Cell\n        >>> from mindspore import Model\n        >>> from mindarmour.adv_robustness.detectors import SimilarityDetector\n        >>> class EncoderNet(Cell):\n        ...     def __init__(self, encode_dim):\n        ...         super(EncoderNet, self).__init__()\n        ...         self._encode_dim = encode_dim\n        ...         self.add = Add()\n        ...     def construct(self, inputs):\n        ...         return self.add(inputs, inputs)\n        ...     def get_encode_dim(self):\n        ...         return self._encode_dim\n        >>> np.random.seed(5)\n        >>> x_train = np.random.rand(10, 32, 32, 3).astype(np.float32)\n        >>> perm = np.random.permutation(x_train.shape[0])\n        >>> benign_queries = x_train[perm[:10], :, :, :]\n        >>> suspicious_queries = x_train[perm[-1], :, :, :] + np.random.normal(0, 0.05, (10,) + x_train.shape[1:])\n        >>> suspicious_queries = suspicious_queries.astype(np.float32)\n        >>> encoder = Model(EncoderNet(encode_dim=256))\n        >>> detector = SimilarityDetector(max_k_neighbor=3, trans_model=encoder)\n        >>> num_nearest_neighbors, thresholds = detector.fit(inputs=x_train)\n        >>> detector.set_threshold(num_nearest_neighbors[-1], thresholds[-1])\n        >>> detector.detect(benign_queries)\n        >>> detections = detector.get_detection_interval()\n        >>> detected_queries = detector.get_detected_queries()\n    \"\"\"\n\n    def __init__(self, trans_model, max_k_neighbor=1000, chunk_size=1000,\n                 max_buffer_size=10000, tuning=False, fpr=0.001):\n        super(SimilarityDetector, self).__init__()\n        self._max_k_neighbor = check_int_positive('max_k_neighbor',\n                                                  max_k_neighbor)\n        self._trans_model = check_model('trans_model', trans_model, Model)\n        self._tuning = check_param_type('tuning', tuning, bool)\n        self._chunk_size = check_int_positive('chunk_size', chunk_size)\n        self._max_buffer_size = check_int_positive('max_buffer_size',\n                                                   max_buffer_size)\n        self._fpr = check_param_in_range('fpr', fpr, 0, 1)\n        self._num_of_neighbors = None\n        self._threshold = None\n        self._num_queries = 0\n        # Stores recently processed queries\n        self._buffer = []\n        # Tracks indexes of detected queries\n        self._detected_queries = []\n\n    def fit(self, inputs, labels=None):\n        \"\"\"\n        Process input training data to calculate the threshold.\n        A proper threshold should make sure the false positive\n        rate is under a given value.\n\n        Args:\n            inputs (numpy.ndarray): Training data to calculate the threshold.\n            labels (numpy.ndarray): Labels of training data.\n\n        Returns:\n            - list[int], number of the nearest neighbors.\n\n            - list[float], calculated thresholds for different K.\n\n        Raises:\n            ValueError: The number of training data is less than\n                max_k_neighbor!\n        \"\"\"\n        data = check_numpy_param('inputs', inputs)\n        data_len = data.shape[0]\n        if data_len < self._max_k_neighbor:\n            raise ValueError('The number of training data must be larger than '\n                             'max_k_neighbor!')\n        data = self._trans_model.predict(Tensor(data)).asnumpy()\n        data = data.reshape((data.shape[0], -1))\n        distances = []\n        for i in range(data.shape[0] // self._chunk_size):\n            distance_mat = _pairwise_distances(\n                x_input=data[i*self._chunk_size:(i + 1)*self._chunk_size, :],\n                y_input=data)\n            distance_mat = np.sort(distance_mat, axis=-1)\n            distances.append(distance_mat[:, :self._max_k_neighbor])\n        # the rest\n        distance_mat = _pairwise_distances(x_input=data[(data.shape[0] // self._chunk_size) * self._chunk_size:, :],\n                                           y_input=data)\n        distance_mat = np.sort(distance_mat, axis=-1)\n        distances.append(distance_mat[:, :self._max_k_neighbor])\n\n        distance_matrix = np.concatenate(distances, axis=0)\n\n        start = 1 if self._tuning else self._max_k_neighbor\n\n        thresholds = []\n        num_nearest_neighbors = []\n        for k in range(start, self._max_k_neighbor + 1):\n            avg_dist = distance_matrix[:, :k].mean(axis=-1)\n            index = int(len(avg_dist)*self._fpr)\n            threshold = np.sort(avg_dist, axis=None)[index]\n            num_nearest_neighbors.append(k)\n            thresholds.append(threshold)\n        if thresholds:\n            self._threshold = thresholds[-1]\n            self._num_of_neighbors = num_nearest_neighbors[-1]\n        return num_nearest_neighbors, thresholds\n\n    def detect(self, inputs):\n        \"\"\"\n        Process queries to detect black-box attack.\n\n        Args:\n             inputs (numpy.ndarray): Query sequence.\n\n        Raises:\n            ValueError: The parameters of threshold or num_of_neighbors is\n                not available.\n        \"\"\"\n        if self._threshold is None or self._num_of_neighbors is None:\n            msg = 'Explicit detection threshold and number of nearest ' \\\n                  'neighbors must be provided using set_threshold(), ' \\\n                  'or call fit() to calculate.'\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        queries = check_numpy_param('inputs', inputs)\n        queries = self._trans_model.predict(Tensor(queries)).asnumpy()\n        queries = queries.reshape((queries.shape[0], -1))\n        for query in queries:\n            self._process_query(query)\n\n    def _process_query(self, query):\n        \"\"\"\n        Process each query to detect black-box attack.\n\n        Args:\n             query (numpy.ndarray): Query input.\n        \"\"\"\n        if len(self._buffer) < self._num_of_neighbors:\n            self._buffer.append(query)\n            self._num_queries += 1\n            return\n        k = self._num_of_neighbors\n\n        if self._buffer:\n            queries = np.stack(self._buffer, axis=0)\n            dists = np.linalg.norm(queries - query, axis=-1)\n\n        k_nearest_dists = np.partition(dists, k - 1)[:k, None]\n        k_avg_dist = np.mean(k_nearest_dists)\n\n        self._buffer.append(query)\n        self._num_queries += 1\n\n        if len(self._buffer) >= self._max_buffer_size:\n            self.clear_buffer()\n\n        # an attack is detected\n        if k_avg_dist < self._threshold:\n            self._detected_queries.append(self._num_queries)\n            self.clear_buffer()\n\n    def clear_buffer(self):\n        \"\"\"\n        Clear the buffer memory.\n        \"\"\"\n        while self._buffer:\n            self._buffer.pop()\n\n    def set_threshold(self, num_of_neighbors, threshold):\n        \"\"\"\n        Set the parameters num_of_neighbors and threshold.\n\n        Args:\n            num_of_neighbors (int): Number of the nearest neighbors.\n            threshold (float): Detection threshold.\n        \"\"\"\n        self._num_of_neighbors = check_int_positive('num_of_neighbors',\n                                                    num_of_neighbors)\n        self._threshold = check_value_positive('threshold', threshold)\n\n    def get_detection_interval(self):\n        \"\"\"\n        Get the interval between adjacent detections.\n\n        Returns:\n            list[int], number of queries between adjacent detections.\n        \"\"\"\n        detected_queries = self._detected_queries\n        interval = []\n        for i in range(len(detected_queries) - 1):\n            interval.append(detected_queries[i + 1] - detected_queries[i])\n        return interval\n\n    def get_detected_queries(self):\n        \"\"\"\n        Get the indexes of detected queries.\n\n        Returns:\n            list[int], sequence number of detected malicious queries.\n        \"\"\"\n        detected_queries = self._detected_queries\n        return detected_queries\n\n    def detect_diff(self, inputs):\n        \"\"\"\n        Detect adversarial samples from input samples, like the predict_proba\n        function in common machine learning model.\n\n        Args:\n            inputs (Union[numpy.ndarray, list, tuple]): Data been used as\n                references to create adversarial examples.\n\n        Raises:\n            NotImplementedError: This function is not available\n                in class `SimilarityDetector`.\n        \"\"\"\n        msg = 'The function detect_diff() is not available in the class ' \\\n              '`SimilarityDetector`.'\n        LOGGER.error(TAG, msg)\n        raise NotImplementedError(msg)\n\n    def transform(self, inputs):\n        \"\"\"\n        Filter adversarial noises in input samples.\n\n        Args:\n            inputs (Union[numpy.ndarray, list, tuple]): Data been used as references to create adversarial examples.\n\n        Raises:\n            NotImplementedError: This function is not available in class `SimilarityDetector`.\n        \"\"\"\n        msg = 'The function transform() is not available in the class `SimilarityDetector`.'\n        LOGGER.error(TAG, msg)\n        raise NotImplementedError(msg)\n"
  },
  {
    "path": "mindarmour/adv_robustness/detectors/detector.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nBase Class of Detector.\n\"\"\"\nfrom abc import abstractmethod\n\nfrom mindarmour.utils.logger import LogUtil\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Detector'\n\n\nclass Detector:\n    \"\"\"\n    The abstract base class for all adversarial example detectors.\n    \"\"\"\n    def __init__(self):\n        pass\n\n\n    @abstractmethod\n    def fit(self, inputs, labels=None):\n        \"\"\"\n        Fit a threshold and refuse adversarial examples whose difference from\n        their denoised versions are larger than the threshold. The threshold is\n        determined by a certain false positive rate when applying to normal samples.\n\n        Args:\n            inputs (numpy.ndarray): The input samples to calculate the threshold.\n            labels (numpy.ndarray): Labels of training data. Default: ``None``.\n\n        Raises:\n            NotImplementedError: It is an abstract method.\n        \"\"\"\n        msg = 'The function fit() is an abstract function in class ' \\\n              '`Detector` and should be implemented in child class.'\n        LOGGER.error(TAG, msg)\n        raise NotImplementedError(msg)\n\n    @abstractmethod\n    def detect(self, inputs):\n        \"\"\"\n        Detect adversarial examples from input samples.\n\n        Args:\n            inputs (Union[numpy.ndarray, list, tuple]): The input samples to be\n                detected.\n\n        Raises:\n            NotImplementedError: It is an abstract method.\n        \"\"\"\n        msg = 'The function detect() is an abstract function in class ' \\\n              '`Detector` and should be implemented in child class.'\n        LOGGER.error(TAG, msg)\n        raise NotImplementedError(msg)\n\n    @abstractmethod\n    def detect_diff(self, inputs):\n        \"\"\"\n        Calculate the difference between the input samples and de-noised samples.\n\n        Args:\n            inputs (Union[numpy.ndarray, list, tuple]): The input samples to be\n                detected.\n\n        Raises:\n            NotImplementedError: It is an abstract method.\n\n        \"\"\"\n        msg = 'The function detect_diff() is an abstract function in class ' \\\n              '`Detector` and should be implemented in child class.'\n        LOGGER.error(TAG, msg)\n        raise NotImplementedError(msg)\n\n    @abstractmethod\n    def transform(self, inputs):\n        \"\"\"\n        Filter adversarial noises in input samples.\n\n        Args:\n            inputs (Union[numpy.ndarray, list, tuple]): The input samples to be\n                transformed.\n        Raises:\n            NotImplementedError: It is an abstract method.\n        \"\"\"\n        msg = 'The function transform() is an abstract function in class ' \\\n              '`Detector` and should be implemented in child class.'\n        LOGGER.error(TAG, msg)\n        raise NotImplementedError(msg)\n"
  },
  {
    "path": "mindarmour/adv_robustness/detectors/ensemble_detector.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nEnsemble Detector.\n\"\"\"\nimport numpy as np\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_numpy_param, \\\n    check_param_multi_types\nfrom .detector import Detector\n\nLOGGER = LogUtil.get_instance()\nTAG = 'EnsembleDetector'\n\n\nclass EnsembleDetector(Detector):\n    \"\"\"\n    The ensemble detector uses a list of detectors to detect the adversarial\n    examples from the input samples.\n\n    Args:\n        detectors (Union[tuple, list]): List of detector methods.\n        policy (str): Decision policy, could be ``'vote'``, ``'all'`` or ``'any'``.\n            Default: ``'vote'``.\n    Examples:\n        >>> from mindspore.ops.operations import Add\n        >>> from mindspore import Model\n        >>> from mindarmour.adv_robustness.detectors import ErrorBasedDetector\n        >>> from mindarmour.adv_robustness.detectors import RegionBasedDetector\n        >>> from mindarmour.adv_robustness.detectors import EnsembleDetector\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self.add = Add()\n        ...     def construct(self, inputs):\n        ...         return self.add(inputs, inputs)\n        >>> class AutoNet(Cell):\n        ...     def __init__(self):\n        ...         super(AutoNet, self).__init__()\n        ...         self.add = Add()\n        ...     def construct(self, inputs):\n        ...         return self.add(inputs, inputs)\n        >>> np.random.seed(6)\n        >>> adv = np.random.rand(4, 4).astype(np.float32)\n        >>> model = Model(Net())\n        >>> auto_encoder = Model(AutoNet())\n        >>> random_label = np.random.randint(10, size=4)\n        >>> labels = np.eye(10)[random_label]\n        >>> magnet_detector = ErrorBasedDetector(auto_encoder)\n        >>> region_detector = RegionBasedDetector(model)\n        >>> region_detector.fit(adv, labels)\n        >>> detectors = [magnet_detector, region_detector]\n        >>> detector = EnsembleDetector(detectors)\n        >>> adv_ids = detector.detect(adv)\n    \"\"\"\n\n    def __init__(self, detectors, policy=\"vote\"):\n        super(EnsembleDetector, self).__init__()\n        self._detectors = check_param_multi_types('detectors', detectors,\n                                                  [list, tuple])\n        self._num_detectors = len(detectors)\n        self._policy = policy\n\n    def fit(self, inputs, labels=None):\n        \"\"\"\n        Fit detector like a machine learning model. This method is not available\n        in this class.\n\n        Args:\n            inputs (numpy.ndarray): Data to calculate the threshold.\n            labels (numpy.ndarray): Labels of data. Default: ``None``.\n\n        Raises:\n            NotImplementedError: This function is not available in ensemble.\n        \"\"\"\n        msg = 'The function fit() is not available in the class ' \\\n              '`EnsembleDetector`.'\n        LOGGER.error(TAG, msg)\n        raise NotImplementedError(msg)\n\n    def detect(self, inputs):\n        \"\"\"\n        Detect adversarial examples from input samples.\n\n        Args:\n            inputs (numpy.ndarray): Input samples.\n\n        Returns:\n            list[int], whether a sample is adversarial. if res[i]=1, then the\n            input sample with index i is adversarial.\n\n        Raises:\n            ValueError: If policy is not supported.\n        \"\"\"\n\n        inputs = check_numpy_param('inputs', inputs)\n        x_len = inputs.shape[0]\n        counts = np.zeros(x_len)\n        res = np.zeros(x_len, dtype=np.int)\n        for detector in list(self._detectors):\n            idx = detector.detect(inputs)\n            counts[idx] += 1\n\n        if self._policy == \"vote\":\n            idx_adv = np.argwhere(counts > self._num_detectors / 2)\n        elif self._policy == \"all\":\n            idx_adv = np.argwhere(counts == self._num_detectors)\n        elif self._policy == \"any\":\n            idx_adv = np.argwhere(counts > 0)\n        else:\n            msg = 'Policy {} is not supported.'.format(self._policy)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        res[idx_adv] = 1\n        return list(res)\n\n    def detect_diff(self, inputs):\n        \"\"\"\n        This method is not available in this class.\n\n        Args:\n            inputs (Union[numpy.ndarray, list, tuple]): Data been used as\n                references to create adversarial examples.\n\n        Raises:\n            NotImplementedError: This function is not available in ensemble.\n        \"\"\"\n        msg = 'The function detect_diff() is not available in the class ' \\\n              '`EnsembleDetector`.'\n        LOGGER.error(TAG, msg)\n        raise NotImplementedError(msg)\n\n    def transform(self, inputs):\n        \"\"\"\n        Filter adversarial noises in input samples.\n        This method is not available in this class.\n\n        Args:\n            inputs (Union[numpy.ndarray, list, tuple]): Data been used as\n                references to create adversarial examples.\n\n        Raises:\n            NotImplementedError: This function is not available in ensemble.\n        \"\"\"\n        msg = 'The function transform() is not available in the class ' \\\n              '`EnsembleDetector`.'\n        LOGGER.error(TAG, msg)\n        raise NotImplementedError(msg)\n"
  },
  {
    "path": "mindarmour/adv_robustness/detectors/mag_net.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nError-Based detector.\n\"\"\"\nimport numpy as np\nfrom scipy import stats\nfrom scipy.special import softmax\n\nfrom mindspore import Tensor\nfrom mindspore import Model\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_numpy_param, check_model, \\\n    check_param_in_range, check_param_multi_types, check_int_positive, \\\n    check_value_positive\nfrom .detector import Detector\n\nLOGGER = LogUtil.get_instance()\nTAG = 'MagNet'\n\n\nclass ErrorBasedDetector(Detector):\n    \"\"\"\n    The detector reconstructs input samples, measures reconstruction errors and\n    rejects samples with large reconstruction errors.\n\n    Reference: `MagNet: a Two-Pronged Defense against Adversarial Examples,\n    by Dongyu Meng and Hao Chen, at CCS 2017.\n    <https://arxiv.org/abs/1705.09064>`_\n\n    Args:\n        auto_encoder (Model): An (trained) auto encoder which reconstructs the input image.\n        false_positive_rate (float): Detector's false positive rate. Default: ``0.01``.\n        bounds (tuple): (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n\n    Examples:\n        >>> from mindspore.ops.operations import Add\n        >>> from mindspore import Model\n        >>> from mindarmour.adv_robustness.detectors import ErrorBasedDetector\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self.add = Add()\n        ...     def construct(self, inputs):\n        ...         return self.add(inputs, inputs)\n        >>> np.random.seed(5)\n        >>> ori = np.random.rand(4, 4, 4).astype(np.float32)\n        >>> np.random.seed(6)\n        >>> adv = np.random.rand(4, 4, 4).astype(np.float32)\n        >>> model = Model(Net())\n        >>> detector = ErrorBasedDetector(model)\n        >>> detector.fit(ori)\n        >>> adv_ids = detector.detect(adv)\n        >>> adv_trans = detector.transform(adv)\n    \"\"\"\n\n    def __init__(self, auto_encoder, false_positive_rate=0.01,\n                 bounds=(0.0, 1.0)):\n        super(ErrorBasedDetector, self).__init__()\n        self._auto_encoder = check_model('auto_encoder', auto_encoder, Model)\n        self._false_positive_rate = check_param_in_range('false_positive_rate',\n                                                         false_positive_rate,\n                                                         0, 1)\n        self._threshold = 0.0\n        self._bounds = check_param_multi_types('bounds', bounds, [list, tuple])\n        for b in self._bounds:\n            _ = check_param_multi_types('bound', b, [int, float])\n\n    def fit(self, inputs, labels=None):\n        \"\"\"\n        Find a threshold for a given dataset to distinguish adversarial examples.\n\n        Args:\n            inputs (numpy.ndarray): Input samples.\n            labels (numpy.ndarray): Labels of input samples. Default: ``None``.\n\n        Returns:\n            float, threshold to distinguish adversarial samples from benign ones.\n        \"\"\"\n        inputs = check_numpy_param('inputs', inputs)\n\n        marks = self.detect_diff(inputs)\n        num = int(inputs.shape[0]*self._false_positive_rate)\n        marks = np.sort(marks)\n        if num <= len(marks):\n            self._threshold = marks[-num]\n        return self._threshold\n\n    def detect(self, inputs):\n        \"\"\"\n        Detect if input samples are adversarial or not.\n\n        Args:\n            inputs (numpy.ndarray): Suspicious samples to be judged.\n\n        Returns:\n            list[int], whether a sample is adversarial. if res[i]=1, then the\n            input sample with index i is adversarial.\n        \"\"\"\n        inputs = check_numpy_param('inputs', inputs)\n        dist = self.detect_diff(inputs)\n        res = [0]*len(dist)\n        for i, elem in enumerate(dist):\n            if elem > self._threshold:\n                res[i] = 1\n        return res\n\n    def detect_diff(self, inputs):\n        \"\"\"\n        Detect the distance between the original samples and reconstructed samples.\n\n        Args:\n            inputs (numpy.ndarray): Input samples.\n\n        Returns:\n            float, the distance between reconstructed and original samples.\n        \"\"\"\n        inputs = check_numpy_param('inputs', inputs)\n        x_trans = self._auto_encoder.predict(Tensor(inputs)).asnumpy()\n        diff = np.abs(inputs - x_trans)\n        dims = tuple(np.arange(len(inputs.shape))[1:])\n        marks = np.mean(np.power(diff, 2), axis=dims)\n        return marks\n\n    def transform(self, inputs):\n        \"\"\"\n        Reconstruct input samples.\n\n        Args:\n            inputs (numpy.ndarray): Input samples.\n\n        Returns:\n            numpy.ndarray, reconstructed images.\n        \"\"\"\n        inputs = check_numpy_param('inputs', inputs)\n        x_trans = self._auto_encoder.predict(Tensor(inputs)).asnumpy()\n        if self._bounds is not None:\n            clip_min, clip_max = self._bounds\n            x_trans = np.clip(x_trans, clip_min, clip_max)\n        return x_trans\n\n    def set_threshold(self, threshold):\n        \"\"\"\n        Set the parameters threshold.\n\n        Args:\n            threshold (float): Detection threshold.\n        \"\"\"\n        self._threshold = check_value_positive('threshold', threshold)\n\n\nclass DivergenceBasedDetector(ErrorBasedDetector):\n    \"\"\"\n    The divergence-based detector learns to distinguish normal and adversarial\n    examples by their js-divergence.\n\n    Reference: `MagNet: a Two-Pronged Defense against Adversarial Examples,\n    by Dongyu Meng and Hao Chen, at CCS 2017.\n    <https://arxiv.org/abs/1705.09064>`_\n\n    Args:\n        auto_encoder (Model): Encoder model.\n        model (Model): Targeted model.\n        option (str): Method used to calculate Divergence. Default: ``\"jsd\"``.\n        t (int): Temperature used to overcome numerical problem. Default: ``1``.\n        bounds (tuple): Upper and lower bounds of data.\n            In form of (clip_min, clip_max). Default: ``(0.0, 1.0)``.\n\n    Examples:\n        >>> import mindspore.ops.operations as P\n        >>> from mindspore.nn import Cell\n        >>> from mindspore import Model\n        >>> from mindarmour.adv_robustness.detectors import DivergenceBasedDetector\n        >>> class PredNet(Cell):\n        ...     def __init__(self):\n        ...         super(PredNet, self).__init__()\n        ...         self.shape = P.Shape()\n        ...         self.reshape = P.Reshape()\n        ...         self._softmax = P.Softmax()\n        ...     def construct(self, inputs):\n        ...         data = self.reshape(inputs, (self.shape(inputs)[0], -1))\n        ...         return self._softmax(data)\n        >>> class Net(Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self.add = P.Add()\n        ...     def construct(self, inputs):\n        ...         return self.add(inputs, inputs)\n        >>> np.random.seed(5)\n        >>> ori = np.random.rand(4, 4, 4).astype(np.float32)\n        >>> np.random.seed(6)\n        >>> adv = np.random.rand(4, 4, 4).astype(np.float32)\n        >>> encoder = Model(Net())\n        >>> model = Model(PredNet())\n        >>> detector = DivergenceBasedDetector(encoder, model)\n        >>> threshold = detector.fit(ori)\n        >>> detector.set_threshold(threshold)\n        >>> adv_ids = detector.detect(adv)\n        >>> adv_trans = detector.transform(adv)\n    \"\"\"\n\n    def __init__(self, auto_encoder, model, option=\"jsd\",\n                 t=1, bounds=(0.0, 1.0)):\n        super(DivergenceBasedDetector, self).__init__(auto_encoder,\n                                                      bounds=bounds)\n        self._auto_encoder = auto_encoder\n        self._model = check_model('targeted model', model, Model)\n        self._threshold = 0.0\n        self._option = option\n        self._t = check_int_positive('t', t)\n        self._bounds = check_param_multi_types('bounds', bounds, [tuple, list])\n        for b in self._bounds:\n            _ = check_param_multi_types('bound', b, [int, float])\n\n    def detect_diff(self, inputs):\n        \"\"\"\n        Detect the distance between original samples and reconstructed samples.\n\n        The distance is calculated by JSD.\n\n        Args:\n            inputs (numpy.ndarray): Input samples.\n\n        Returns:\n             float, the distance.\n\n        Raises:\n            NotImplementedError: If the param `option` is not supported.\n        \"\"\"\n        inputs = check_numpy_param('inputs', inputs)\n        x_len = inputs.shape[0]\n        x_transformed = self._auto_encoder.predict(Tensor(inputs)).asnumpy()\n        x_origin = self._model.predict(Tensor(inputs)).asnumpy()\n        x_trans = self._model.predict(Tensor(x_transformed)).asnumpy()\n\n        y_pred = softmax(x_origin / self._t, axis=1)\n        y_trans_pred = softmax(x_trans / self._t, axis=1)\n\n        if self._option == 'jsd':\n            marks = [_jsd(y_pred[i], y_trans_pred[i]) for i in range(x_len)]\n        else:\n            msg = '{} is not implemented.'.format(self._option)\n            LOGGER.error(TAG, msg)\n            raise NotImplementedError(msg)\n        return np.array(marks)\n\n\ndef _jsd(prob_dist_p, prob_dist_q):\n    \"\"\"\n    Compute the Jensen-Shannon Divergence between two probability distributions\n        with equal weights.\n\n    Args:\n        prob_dist_p (numpy.ndarray): Probability distribution p.\n        prob_dist_q (numpy.ndarray): Probability distribution q.\n\n    Returns:\n        float, the Jensen-Shannon Divergence.\n    \"\"\"\n    prob_dist_p = check_numpy_param('prob_dist_p', prob_dist_p)\n    prob_dist_q = check_numpy_param('prob_dist_q', prob_dist_q)\n    norm_dist_p = prob_dist_p / (np.linalg.norm(prob_dist_p, ord=1) + 1e-12)\n    norm_dist_q = prob_dist_q / (np.linalg.norm(prob_dist_q, ord=1) + 1e-12)\n    norm_mean = 0.5*(norm_dist_p + norm_dist_q)\n    return 0.5*(stats.entropy(norm_dist_p, norm_mean)\n                + stats.entropy(norm_dist_q, norm_mean))\n"
  },
  {
    "path": "mindarmour/adv_robustness/detectors/region_based_detector.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nRegion-Based detector\n\"\"\"\nimport time\n\nimport numpy as np\n\nfrom mindspore import Model\nfrom mindspore import Tensor\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_numpy_param, check_param_type, \\\n    check_pair_numpy_param, check_model, check_int_positive, \\\n    check_value_positive, check_value_non_negative, check_param_in_range, \\\n    check_equal_shape\nfrom .detector import Detector\n\nLOGGER = LogUtil.get_instance()\nTAG = 'RegionBasedDetector'\n\n\nclass RegionBasedDetector(Detector):\n    \"\"\"\n    The region-based detector uses the fact that adversarial examples are close\n    to the classification boundary, and ensembles information around the given example\n    to predict whether it is an adversarial example or not.\n\n    Reference: `Mitigating evasion attacks to deep neural networks via\n    region-based classification <https://arxiv.org/abs/1709.05583>`_\n\n    Args:\n        model (Model): Target model.\n        number_points (int): The number of samples generate from the\n            hyper cube of original sample. Default: ``10``.\n        initial_radius (float): Initial radius of hyper cube. Default: ``0.0``.\n        max_radius (float): Maximum radius of hyper cube. Default: ``1.0``.\n        search_step (float): Incremental during search of radius. Default: ``0.01``.\n        degrade_limit (float): Acceptable decrease of classification accuracy.\n            Default: ``0.0``.\n        sparse (bool): If ``True``, input labels are sparse-encoded. If ``False``,\n            input labels are one-hot-encoded. Default: ``False``.\n\n    Examples:\n        >>> from mindspore.ops.operations import Add\n        >>> from mindspore import Model\n        >>> from mindarmour.adv_robustness.detectors import RegionBasedDetector\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self.add = Add()\n        ...     def construct(self, inputs):\n        ...         return self.add(inputs, inputs)\n        >>> np.random.seed(5)\n        >>> ori = np.random.rand(4, 4).astype(np.float32)\n        >>> labels = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 0, 1, 0],\n        ...                   [0, 1, 0, 0]]).astype(np.int32)\n        >>> np.random.seed(6)\n        >>> adv = np.random.rand(4, 4).astype(np.float32)\n        >>> model = Model(Net())\n        >>> detector = RegionBasedDetector(model)\n        >>> radius = detector.fit(ori, labels)\n        >>> detector.set_radius(radius)\n        >>> adv_ids = detector.detect(adv)\n    \"\"\"\n\n    def __init__(self, model, number_points=10, initial_radius=0.0,\n                 max_radius=1.0, search_step=0.01, degrade_limit=0.0,\n                 sparse=False):\n        super(RegionBasedDetector, self).__init__()\n        self._model = check_model('targeted model', model, Model)\n        self._number_points = check_int_positive('number_points', number_points)\n        self._initial_radius = check_value_non_negative('initial_radius',\n                                                        initial_radius)\n        self._max_radius = check_value_positive('max_radius', max_radius)\n        self._search_step = check_value_positive('search_step', search_step)\n        self._degrade_limit = check_value_non_negative('degrade_limit',\n                                                       degrade_limit)\n        self._sparse = check_param_type('sparse', sparse, bool)\n        self._radius = None\n\n    def set_radius(self, radius):\n        \"\"\"\n        Set radius.\n\n        Args:\n            radius (float): Radius of region.\n        \"\"\"\n        self._radius = check_param_in_range('radius', radius,\n                                            self._initial_radius,\n                                            self._max_radius)\n\n    def fit(self, inputs, labels=None):\n        \"\"\"\n        Train detector to decide the best radius.\n\n        Args:\n            inputs (numpy.ndarray): Benign samples.\n            labels (numpy.ndarray): Ground truth labels of the input samples.\n                Default:None.\n\n        Returns:\n            float, the best radius.\n        \"\"\"\n        inputs, labels = check_pair_numpy_param('inputs', inputs,\n                                                'labels', labels)\n        LOGGER.debug(TAG, 'enter fit() function.')\n        time_start = time.time()\n        search_iters = (self._max_radius\n                        - self._initial_radius) / self._search_step\n        search_iters = np.round(search_iters).astype(int)\n        radius = self._initial_radius\n        pred = self._model.predict(Tensor(inputs))\n        raw_preds = np.argmax(pred.asnumpy(), axis=1)\n        if not self._sparse:\n            labels = np.argmax(labels, axis=1)\n        raw_preds, labels = check_equal_shape('raw_preds', raw_preds, 'labels',\n                                              labels)\n        raw_acc = np.sum(raw_preds == labels) / inputs.shape[0]\n\n        for _ in range(search_iters):\n            rc_preds = self._rc_forward(inputs, radius)\n            rc_preds, labels = check_equal_shape('rc_preds', rc_preds, 'labels',\n                                                 labels)\n            def_acc = np.sum(rc_preds == labels) / inputs.shape[0]\n            if def_acc >= raw_acc - self._degrade_limit:\n                radius += self._search_step\n                continue\n            break\n\n        self._radius = radius - self._search_step\n        LOGGER.debug(TAG, 'best radius is: %s', self._radius)\n        LOGGER.debug(TAG,\n                     'time used to train detector of %d samples is: %s seconds',\n                     inputs.shape[0],\n                     time.time() - time_start)\n        return self._radius\n\n    def _generate_hyper_cube(self, inputs, radius):\n        \"\"\"\n        Generate random samples in the hyper cubes around input samples.\n\n        Args:\n            inputs (numpy.ndarray): Input samples.\n            radius (float): The scope to generate hyper cubes around input samples.\n\n        Returns:\n            numpy.ndarray, randomly chosen samples in the hyper cubes.\n        \"\"\"\n        LOGGER.debug(TAG, 'enter _generate_hyper_cube().')\n        res = []\n        for _ in range(self._number_points):\n            res.append(np.clip((inputs + np.random.uniform(\n                -radius, radius, len(inputs))), 0.0, 1.0).astype(inputs.dtype))\n        return np.asarray(res)\n\n    def _rc_forward(self, inputs, radius):\n        \"\"\"\n        Generate region-based predictions for input samples.\n\n        Args:\n            inputs (numpy.ndarray): Input samples.\n            radius (float): The scope to generate hyper cubes around input samples.\n\n        Returns:\n            numpy.ndarray, classification result for input samples.\n        \"\"\"\n        LOGGER.debug(TAG, 'enter _rc_forward().')\n        res = []\n        for _, elem in enumerate(inputs):\n            hyper_cube_x = self._generate_hyper_cube(elem, radius)\n            hyper_cube_preds = []\n            for ite_hyper_cube_x in hyper_cube_x:\n                model_inputs = Tensor(np.expand_dims(ite_hyper_cube_x, axis=0))\n                ite_preds = self._model.predict(model_inputs).asnumpy()[0]\n                hyper_cube_preds.append(ite_preds)\n            pred_labels = np.argmax(hyper_cube_preds, axis=1)\n            bin_count = np.bincount(pred_labels)\n            # count the number of different class and choose the max one\n            # as final class\n            hyper_cube_tag = np.argmax(bin_count, axis=0)\n            res.append(hyper_cube_tag)\n        return np.asarray(res)\n\n    def detect(self, inputs):\n        \"\"\"\n        Tell whether input samples are adversarial or not.\n\n        Args:\n            inputs (numpy.ndarray): Suspicious samples to be judged.\n\n        Returns:\n            list[int], whether a sample is adversarial. if res[i]=1, then the\n            input sample with index i is adversarial.\n        \"\"\"\n        LOGGER.debug(TAG, 'enter detect().')\n        self._radius = check_param_type('radius', self._radius, float)\n        inputs = check_numpy_param('inputs', inputs)\n        time_start = time.time()\n        res = [1]*inputs.shape[0]\n        raw_preds = np.argmax(self._model.predict(Tensor(inputs)).asnumpy(),\n                              axis=1)\n        rc_preds = self._rc_forward(inputs, self._radius)\n        for i in range(inputs.shape[0]):\n            if raw_preds[i] == rc_preds[i]:\n                res[i] = 0\n        LOGGER.debug(TAG,\n                     'time used to detect %d samples is : %s seconds',\n                     inputs.shape[0],\n                     time.time() - time_start)\n        return res\n\n    def detect_diff(self, inputs):\n        \"\"\"\n        Return raw prediction results and region-based prediction results.\n\n        Args:\n            inputs (numpy.ndarray): Input samples.\n\n        Returns:\n            numpy.ndarray, raw prediction results and region-based prediction results of input samples.\n        \"\"\"\n        LOGGER.debug(TAG, 'enter detect_diff().')\n        inputs = check_numpy_param('inputs', inputs)\n\n        raw_preds = self._model.predict(Tensor(inputs))\n        rc_preds = self._rc_forward(inputs, self._radius)\n\n        return raw_preds.asnumpy(), rc_preds\n\n    def transform(self, inputs):\n        \"\"\"\n        Generate hyper cube for input samples.\n\n        Args:\n            inputs (numpy.ndarray): Input samples.\n\n        Returns:\n            numpy.ndarray, hyper cube corresponds to every sample.\n        \"\"\"\n        LOGGER.debug(TAG, 'enter transform().')\n        inputs = check_numpy_param('inputs', inputs)\n        res = []\n        for _, elem in enumerate(inputs):\n            res.append(self._generate_hyper_cube(elem, self._radius))\n        return np.asarray(res)\n"
  },
  {
    "path": "mindarmour/adv_robustness/detectors/spatial_smoothing.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nSpatial-Smoothing detector.\n\"\"\"\nimport numpy as np\nfrom scipy import ndimage\n\nfrom mindspore import Model\nfrom mindspore import Tensor\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_model, check_numpy_param, \\\n    check_pair_numpy_param, check_int_positive, check_param_type, \\\n    check_param_in_range, check_equal_shape, check_value_positive\nfrom .detector import Detector\n\nLOGGER = LogUtil.get_instance()\nTAG = 'SpatialSmoothing'\n\n\ndef _median_filter_np(inputs, size=2):\n    \"\"\"median filter using numpy\"\"\"\n    return ndimage.filters.median_filter(inputs, size=size, mode='reflect')\n\n\nclass SpatialSmoothing(Detector):\n    \"\"\"\n    Detect method based on spatial smoothing.\n    Using Gaussian filtering, median filtering, and mean filtering, to blur\n    the original image. When the model has a large threshold difference\n    between the predicted values before and after the sample is blurred,\n    it is judged as an adversarial example.\n\n    Args:\n        model (Model): Target model.\n        ksize (int): Smooth window size. Default: ``3``.\n        is_local_smooth (bool): If ``True``, trigger local smooth. If ``False``, none\n            local smooth. Default: ``True``.\n        metric (str): Distance method. Default: ``'l1'``.\n        false_positive_ratio (float): False positive rate over\n            benign samples. Default: ``0.05``.\n\n    Examples:\n        >>> import mindspore.ops.operations as P\n        >>> from mindspore import Model\n        >>> from mindarmour.adv_robustness.detectors import SpatialSmoothing\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...     def construct(self, inputs):\n        ...         return self._softmax(inputs)\n        >>> input_shape = (50, 3)\n        >>> np.random.seed(1)\n        >>> input_np = np.random.randn(*input_shape).astype(np.float32)\n        >>> np.random.seed(2)\n        >>> adv_np = np.random.randn(*input_shape).astype(np.float32)\n        >>> model = Model(Net())\n        >>> detector = SpatialSmoothing(model)\n        >>> threshold = detector.fit(input_np)\n        >>> detector.set_threshold(threshold.item())\n        >>> detected_res = np.array(detector.detect(adv_np))\n    \"\"\"\n\n    def __init__(self, model, ksize=3, is_local_smooth=True,\n                 metric='l1', false_positive_ratio=0.05):\n        super(SpatialSmoothing, self).__init__()\n        self._ksize = check_int_positive('ksize', ksize)\n        self._is_local_smooth = check_param_type('is_local_smooth',\n                                                 is_local_smooth,\n                                                 bool)\n        self._model = check_model('model', model, Model)\n        self._metric = metric\n        self._fpr = check_param_in_range('false_positive_ratio',\n                                         false_positive_ratio,\n                                         0, 1)\n        self._threshold = None\n\n    def fit(self, inputs, labels=None):\n        \"\"\"\n        Train detector to decide the threshold. The proper threshold make\n        sure the actual false positive rate over benign sample is less than\n        the given value.\n\n        Args:\n            inputs (numpy.ndarray): Benign samples.\n            labels (numpy.ndarray): Default ``None``.\n\n        Returns:\n            float, threshold, distance larger than which is reported\n            as positive, i.e. adversarial.\n        \"\"\"\n        inputs = check_numpy_param('inputs', inputs)\n        raw_pred = self._model.predict(Tensor(inputs)).asnumpy()\n        smoothing_pred = self._model.predict(Tensor(self.transform(inputs))).asnumpy()\n\n        dist = self._dist(raw_pred, smoothing_pred)\n        index = int(len(dist)*(1 - self._fpr))\n        threshold = np.sort(dist, axis=None)[index]\n        self._threshold = threshold\n        return self._threshold\n\n    def detect(self, inputs):\n        \"\"\"\n        Detect if an input sample is an adversarial example.\n\n        Args:\n            inputs (numpy.ndarray): Suspicious samples to be judged.\n\n        Returns:\n            list[int], whether a sample is adversarial. if res[i]=1, then the\n            input sample with index i is adversarial.\n        \"\"\"\n        inputs = check_numpy_param('inputs', inputs)\n        raw_pred = self._model.predict(Tensor(inputs)).asnumpy()\n        smoothing_pred = self._model.predict(Tensor(self.transform(inputs))).asnumpy()\n        dist = self._dist(raw_pred, smoothing_pred)\n\n        res = [0]*len(dist)\n        for i, elem in enumerate(dist):\n            if elem > self._threshold:\n                res[i] = 1\n\n        return res\n\n    def detect_diff(self, inputs):\n        \"\"\"\n        Return the raw distance value (before apply the threshold) between\n        the input sample and its smoothed counterpart.\n\n        Args:\n            inputs (numpy.ndarray): Suspicious samples to be judged.\n\n        Returns:\n            float, distance.\n        \"\"\"\n        inputs = check_numpy_param('inputs', inputs)\n        raw_pred = self._model.predict(Tensor(inputs)).asnumpy()\n        smoothing_pred = self._model.predict(Tensor(self.transform(inputs))).asnumpy()\n        dist = self._dist(raw_pred, smoothing_pred)\n        return dist\n\n    def transform(self, inputs):\n        inputs = check_numpy_param('inputs', inputs)\n        return _median_filter_np(inputs, self._ksize)\n\n    def set_threshold(self, threshold):\n        \"\"\"\n        Set the parameters threshold.\n\n        Args:\n            threshold (float): Detection threshold.\n        \"\"\"\n        self._threshold = check_value_positive('threshold', threshold)\n\n    def _dist(self, before, after):\n        \"\"\"\n        Calculate the distance between the model outputs of a raw sample and\n            its smoothed counterpart.\n\n        Args:\n            before (numpy.ndarray): Model output of raw samples.\n            after (numpy.ndarray): Model output of smoothed counterparts.\n\n        Returns:\n            float, distance based on specified norm.\n        \"\"\"\n        before, after = check_pair_numpy_param('before', before, 'after', after)\n        before, after = check_equal_shape('before', before, 'after', after)\n        res = []\n        diff = after - before\n        for _, elem in enumerate(diff):\n            if self._metric == 'l1':\n                res.append(np.linalg.norm(elem, ord=1))\n            elif self._metric == 'l2':\n                res.append(np.linalg.norm(elem, ord=2))\n            else:\n                res.append(np.linalg.norm(elem, ord=1))\n        return res\n"
  },
  {
    "path": "mindarmour/adv_robustness/evaluations/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis module includes various metrics to evaluate the result of attacks or\ndefenses.\n\"\"\"\nfrom .attack_evaluation import AttackEvaluate\nfrom .defense_evaluation import DefenseEvaluate\nfrom .visual_metrics import RadarMetric\nfrom .neuron_metrics import NeuronMetric\nfrom . import black\nfrom .black.defense_evaluation import BlackDefenseEvaluate\n\n__all__ = ['AttackEvaluate',\n           'BlackDefenseEvaluate',\n           'DefenseEvaluate',\n           'RadarMetric',\n           'NeuronMetric']\n"
  },
  {
    "path": "mindarmour/adv_robustness/evaluations/attack_evaluation.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nAttack evaluation.\n\"\"\"\n\nimport numpy as np\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_pair_numpy_param, \\\n    check_param_type, check_numpy_param\nfrom mindarmour.utils.util import calculate_lp_distance, compute_ssim\n\nLOGGER = LogUtil.get_instance()\nTAG = 'AttackEvaluate'\n\n\nclass AttackEvaluate:\n    \"\"\"\n    Evaluation metrics of attack methods.\n\n    Args:\n        inputs (numpy.ndarray): Original samples.\n        labels (numpy.ndarray): Original samples' label by one-hot format.\n        adv_inputs (numpy.ndarray): Adversarial samples generated from original\n            samples.\n        adv_preds (numpy.ndarray): Probability of all output classes of\n            adversarial examples.\n        targeted (bool): If ``True``, it is a targeted attack. If ``False``, it is an\n            untargeted attack. Default: ``False``.\n        target_label (numpy.ndarray): Targeted classes of adversarial examples,\n            which is one dimension whose size is adv_inputs.shape[0].\n            Default: ``None``.\n\n    Raises:\n        ValueError: If `target_label` is ``None`` when `targeted` is ``True``.\n\n    Examples:\n        >>> from mindarmour.adv_robustness.evaluations import AttackEvaluate\n        >>> x = np.random.normal(size=(3, 512, 512, 3))\n        >>> adv_x = np.random.normal(size=(3, 512, 512, 3))\n        >>> y = np.array([[0.1, 0.1, 0.2, 0.6],\n        ...               [0.1, 0.7, 0.0, 0.2],\n        ...               [0.8, 0.1, 0.0, 0.1]])\n        >>> adv_y = np.array([[0.1, 0.1, 0.2, 0.6],\n        ...                   [0.1, 0.0, 0.8, 0.1],\n        ...                   [0.0, 0.9, 0.1, 0.0]])\n        >>> attack_eval = AttackEvaluate(x, y, adv_x, adv_y)\n        >>> mr = attack_eval.mis_classification_rate()\n        >>> acac = attack_eval.avg_conf_adv_class()\n        >>> l_0, l_2, l_inf = attack_eval.avg_lp_distance()\n        >>> ass = attack_eval.avg_ssim()\n        >>> nte = attack_eval.nte()\n        >>> actc = attack_eval.avg_conf_true_class()\n\n    \"\"\"\n\n    def __init__(self, inputs, labels, adv_inputs, adv_preds,\n                 targeted=False, target_label=None):\n        self._inputs, self._labels = check_pair_numpy_param('inputs',\n                                                            inputs,\n                                                            'labels',\n                                                            labels)\n        self._adv_inputs, self._adv_preds = check_pair_numpy_param('adv_inputs',\n                                                                   adv_inputs,\n                                                                   'adv_preds',\n                                                                   adv_preds)\n        targeted = check_param_type('targeted', targeted, bool)\n        self._targeted = targeted\n        if target_label is not None:\n            target_label = check_numpy_param('target_label', target_label)\n        self._target_label = target_label\n        self._true_label = np.argmax(self._labels, axis=1)\n        self._adv_label = np.argmax(self._adv_preds, axis=1)\n\n        idxes = np.arange(self._adv_preds.shape[0])\n        if self._targeted:\n            if target_label is None:\n                msg = 'targeted attack need target_label, but got None.'\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n            self._adv_preds, self._target_label = check_pair_numpy_param('adv_pred',\n                                                                         self._adv_preds,\n                                                                         'target_label',\n                                                                         target_label)\n            self._success_idxes = idxes[self._adv_label == self._target_label]\n        else:\n            self._success_idxes = idxes[self._adv_label != self._true_label]\n\n    def mis_classification_rate(self):\n        \"\"\"\n        Calculate misclassification rate(MR).\n\n        Returns:\n            float, ranges between (0, 1). The higher, the more successful the attack is.\n        \"\"\"\n        return self._success_idxes.shape[0]*1.0 / self._inputs.shape[0]\n\n    def avg_conf_adv_class(self):\n        \"\"\"\n        Calculate average confidence of adversarial class (ACAC).\n\n        Returns:\n            float, ranges between (0, 1). The higher, the more successful the attack is.\n        \"\"\"\n        idxes = self._success_idxes\n        success_num = idxes.shape[0]\n        if success_num == 0:\n            return 0\n        if self._targeted:\n            return np.mean(self._adv_preds[idxes, self._target_label[idxes]])\n        return np.mean(self._adv_preds[idxes, self._adv_label[idxes]])\n\n    def avg_conf_true_class(self):\n        \"\"\"\n        Calculate average confidence of true class (ACTC).\n\n        Returns:\n            float, ranges between (0, 1). The lower, the more successful the attack is.\n        \"\"\"\n        idxes = self._success_idxes\n        success_num = idxes.shape[0]\n        if success_num == 0:\n            return 0\n        return np.mean(self._adv_preds[idxes, self._true_label[idxes]])\n\n    def avg_lp_distance(self):\n        \"\"\"\n        Calculate average lp distance (lp-dist).\n\n        Returns:\n            - float, return average l0, l2, or linf distance of all success\n              adversarial examples, return value includes following cases.\n\n              - If return value :math:`>=` 0, average lp distance. The lower,\n                the more successful the attack is.\n\n              - If return value is -1, there is no success adversarial examples.\n        \"\"\"\n        idxes = self._success_idxes\n        success_num = idxes.shape[0]\n        if success_num == 0:\n            return -1, -1, -1\n        l0_dist = 0\n        l2_dist = 0\n        linf_dist = 0\n        for i in idxes:\n            l0_dist_i, l2_dist_i, linf_dist_i = calculate_lp_distance(self._inputs[i], self._adv_inputs[i])\n            l0_dist += l0_dist_i\n            l2_dist += l2_dist_i\n            linf_dist += linf_dist_i\n\n        return l0_dist / success_num, l2_dist / success_num, \\\n               linf_dist / success_num\n\n    def avg_ssim(self):\n        \"\"\"\n        Calculate average structural similarity (ASS).\n\n        Returns:\n            - float, average structural similarity.\n\n              - If return value ranges between (0, 1), the higher, the more\n                successful the attack is.\n\n              - If return value is -1: there is no success adversarial examples.\n        \"\"\"\n        success_num = self._success_idxes.shape[0]\n        if success_num == 0:\n            return -1\n\n        total_ssim = 0.0\n        for _, i in enumerate(self._success_idxes):\n            total_ssim += compute_ssim(self._adv_inputs[i], self._inputs[i])\n\n        return total_ssim / success_num\n\n    def nte(self):\n        \"\"\"\n        Calculate noise tolerance estimation (NTE).\n\n        References: `Towards Imperceptible and Robust Adversarial Example Attacks\n        against Neural Networks <https://arxiv.org/abs/1801.04693>`_\n\n        Returns:\n            float, ranges between (0, 1). The higher, the more successful the\n            attack is.\n        \"\"\"\n        idxes = self._success_idxes\n        success_num = idxes.shape[0]\n        adv_y = self._adv_preds[idxes]\n        adv_y_2 = np.copy(adv_y)\n        adv_y_2[range(success_num), np.argmax(adv_y_2, axis=1)] = 0\n        net = np.mean(np.abs(np.max(adv_y_2, axis=1) - np.max(adv_y, axis=1)))\n\n        return net\n"
  },
  {
    "path": "mindarmour/adv_robustness/evaluations/black/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "mindarmour/adv_robustness/evaluations/black/defense_evaluation.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n\"\"\"\r\nEvaluating Defense against Black-box Attacks.\r\n\"\"\"\r\nimport numpy as np\r\n\r\nfrom mindarmour.utils.logger import LogUtil\r\nfrom mindarmour.utils._check_param import check_pair_numpy_param, \\\r\n    check_equal_length, check_int_positive, check_numpy_param\r\n\r\nLOGGER = LogUtil.get_instance()\r\nTAG = 'BlackDefenseEvaluate'\r\n\r\n\r\nclass BlackDefenseEvaluate:\r\n    \"\"\"\r\n    Evaluation metrics of anti-black-box defense method.\r\n\r\n    Args:\r\n        raw_preds (numpy.ndarray): Predict results of some certain samples on\r\n            raw model.\r\n        def_preds (numpy.ndarray): Predict results of some certain samples on\r\n            defensed model.\r\n        raw_query_counts (numpy.ndarray): Number of queries to generate\r\n            adversarial examples on raw model, which is one dimensional whose\r\n            size is raw_preds.shape[0]. For benign samples, query count must be\r\n            set to 0.\r\n        def_query_counts (numpy.ndarray): Number of queries to generate\r\n            adversarial examples on defensed model, which is one dimensional\r\n            whose size is raw_preds.shape[0].\r\n            For benign samples, query count must be set to 0.\r\n        raw_query_time (numpy.ndarray): The total time duration to generate\r\n            an adversarial example on raw model, which is one dimensional\r\n            whose size is raw_preds.shape[0].\r\n        def_query_time (numpy.ndarray): The total time duration to generate an\r\n            adversarial example on defensed model, which is one dimensional\r\n            whose size is raw_preds.shape[0].\r\n        def_detection_counts (numpy.ndarray): Total number of detected queries\r\n            during each adversarial example generation, which is one dimensional\r\n            whose size is raw_preds.shape[0]. For a benign sample, the\r\n            def_detection_counts is set to 1 if the query is identified as\r\n            suspicious, and 0 otherwise.\r\n        true_labels (numpy.ndarray): True labels in one-dim whose size is\r\n            raw_preds.shape[0].\r\n        max_queries (int): Attack budget, the maximum number of queries.\r\n\r\n    Examples:\r\n        >>> from mindarmour.adv_robustness.evaluations import BlackDefenseEvaluate\r\n        >>> raw_preds = np.array([[0.1, 0.1, 0.2, 0.6],\r\n        ...                       [0.1, 0.7, 0.0, 0.2],\r\n        ...                       [0.8, 0.1, 0.0, 0.1]])\r\n        >>> def_preds = np.array([[0.1, 0.1, 0.1, 0.7],\r\n        ...                       [0.1, 0.6, 0.2, 0.1],\r\n        ...                       [0.1, 0.2, 0.1, 0.6]])\r\n        >>> raw_query_counts = np.array([0,20,10])\r\n        >>> def_query_counts = np.array([0,50,60])\r\n        >>> raw_query_time = np.array([0.1, 2, 1])\r\n        >>> def_query_time = np.array([0.2, 6, 5])\r\n        >>> def_detection_counts = np.array([1, 5, 10])\r\n        >>> true_labels = np.array([3, 1, 0])\r\n        >>> max_queries = 100\r\n        >>> def_eval = BlackDefenseEvaluate(raw_preds,\r\n        ...                             def_preds,\r\n        ...                             raw_query_counts,\r\n        ...                             def_query_counts,\r\n        ...                             raw_query_time,\r\n        ...                             def_query_time,\r\n        ...                             def_detection_counts,\r\n        ...                             true_labels,\r\n        ...                             max_queries)\r\n        >>> qcv = def_eval.qcv()\r\n        >>> asv = def_eval.asv()\r\n        >>> fpr = def_eval.fpr()\r\n        >>> qrv = def_eval.qrv()\r\n    \"\"\"\r\n\r\n    def __init__(self, raw_preds, def_preds, raw_query_counts, def_query_counts,\r\n                 raw_query_time, def_query_time, def_detection_counts,\r\n                 true_labels, max_queries):\r\n        self._raw_preds, self._def_preds = check_pair_numpy_param('raw_preds',\r\n                                                                  raw_preds,\r\n                                                                  'def_preds',\r\n                                                                  def_preds)\r\n        self._num_samples = self._raw_preds.shape[0]\r\n        self._raw_query_counts, _ = check_equal_length('raw_query_counts',\r\n                                                       raw_query_counts,\r\n                                                       'number of sample',\r\n                                                       self._raw_preds)\r\n        self._def_query_counts, _ = check_equal_length('def_query_counts',\r\n                                                       def_query_counts,\r\n                                                       'number of sample',\r\n                                                       self._raw_preds)\r\n        self._raw_query_time, _ = check_equal_length('raw_query_time',\r\n                                                     raw_query_time,\r\n                                                     'number of sample',\r\n                                                     self._raw_preds)\r\n        self._def_query_time, _ = check_equal_length('def_query_time',\r\n                                                     def_query_time,\r\n                                                     'number of sample',\r\n                                                     self._raw_preds)\r\n\r\n        self._num_adv_samples = self._raw_query_counts[\r\n            self._raw_query_counts > 0].shape[0]\r\n\r\n        self._num_adv_samples = check_int_positive(\r\n            'the number of adversarial samples',\r\n            self._num_adv_samples)\r\n\r\n        self._num_ben_samples = self._num_samples - self._num_adv_samples\r\n        self._max_queries = check_int_positive('max_queries', max_queries)\r\n\r\n        self._def_detection_counts = check_numpy_param('def_detection_counts',\r\n                                                       def_detection_counts)\r\n        self._true_labels = check_numpy_param('true_labels', true_labels)\r\n\r\n    def qcv(self):\r\n        \"\"\"\r\n        Calculate query count variance (QCV).\r\n\r\n        Returns:\r\n            float, the higher, the stronger the defense is. If num_adv_samples=0,\r\n            return -1.\r\n        \"\"\"\r\n        if self._num_adv_samples == 0:\r\n            return -1\r\n        avg_def_query_count = \\\r\n            np.sum(self._def_query_counts) / self._num_adv_samples\r\n        avg_raw_query_count = \\\r\n            np.sum(self._raw_query_counts) / self._num_adv_samples\r\n\r\n        if (avg_def_query_count == self._max_queries) \\\r\n                and (avg_raw_query_count < self._max_queries):\r\n            query_variance = 1\r\n        else:\r\n            query_variance = \\\r\n                min(avg_def_query_count - avg_raw_query_count,\r\n                    self._max_queries) / self._max_queries\r\n        return query_variance\r\n\r\n    def asv(self):\r\n        \"\"\"\r\n        Calculate attack success rate variance (ASV).\r\n\r\n        Returns:\r\n            float, the lower, the stronger the defense is. If num_adv_samples=0,\r\n            return -1.\r\n        \"\"\"\r\n        adv_def_preds = self._def_preds[self._def_query_counts > 0]\r\n        adv_raw_preds = self._raw_preds[self._raw_query_counts > 0]\r\n        adv_true_labels = self._true_labels[self._raw_query_counts > 0]\r\n\r\n        def_succ_num = np.sum(np.argmax(adv_def_preds, axis=1)\r\n                              != adv_true_labels)\r\n        raw_succ_num = np.sum(np.argmax(adv_raw_preds, axis=1)\r\n                              != adv_true_labels)\r\n        if self._num_adv_samples == 0:\r\n            return -1\r\n        return (raw_succ_num - def_succ_num) / self._num_adv_samples\r\n\r\n    def fpr(self):\r\n        \"\"\"\r\n        Calculate false positive rate (FPR) of the query-based detector.\r\n\r\n        Returns:\r\n            float, the lower, the higher usability the defense is. If\r\n            num_adv_samples=0, return -1.\r\n        \"\"\"\r\n\r\n        ben_detect_counts = \\\r\n            self._def_detection_counts[self._def_query_counts == 0]\r\n        num_fp = ben_detect_counts[ben_detect_counts > 0].shape[0]\r\n        if self._num_ben_samples == 0:\r\n            return -1\r\n        return num_fp / self._num_ben_samples\r\n\r\n    def qrv(self):\r\n        \"\"\"\r\n        Calculate the benign query response time variance (QRV).\r\n\r\n        Returns:\r\n            float, the lower, the higher usability the defense is. If\r\n            num_adv_samples=0, return -1.\r\n        \"\"\"\r\n        if self._num_ben_samples == 0:\r\n            return -1\r\n        raw_num_queries = self._num_ben_samples\r\n        def_num_queries = self._num_ben_samples\r\n\r\n        ben_raw_query_time = self._raw_query_time[self._raw_query_counts == 0]\r\n        ben_def_query_time = self._def_query_time[self._def_query_counts == 0]\r\n\r\n        avg_raw_query_time = np.sum(ben_raw_query_time) / raw_num_queries\r\n        avg_def_query_time = np.sum(ben_def_query_time) / def_num_queries\r\n\r\n        return (avg_def_query_time -\r\n                avg_raw_query_time) / (avg_raw_query_time + 1e-12)\r\n"
  },
  {
    "path": "mindarmour/adv_robustness/evaluations/defense_evaluation.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nDefense Evaluation.\n\"\"\"\nimport numpy as np\n\nimport scipy.stats as st\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_numpy_param\nfrom mindarmour.utils._check_param import check_pair_numpy_param\n\nLOGGER = LogUtil.get_instance()\nTAG = 'DefenseEvaluate'\n\n\nclass DefenseEvaluate:\n    \"\"\"\n    Evaluation metrics of defense methods.\n\n    Args:\n        raw_preds (numpy.ndarray): Prediction results of some certain samples\n            on raw model.\n        def_preds (numpy.ndarray): Prediction results of some certain samples on\n            defensed model.\n        true_labels (numpy.ndarray): Ground-truth labels of samples, a\n            one-dimension array whose size is raw_preds.shape[0].\n\n    Examples:\n        >>> from mindarmour.adv_robustness.evaluations import DefenseEvaluate\n        >>> raw_preds = np.array([[0.1, 0.1, 0.2, 0.6],\n        ...                       [0.1, 0.7, 0.0, 0.2],\n        ...                       [0.8, 0.1, 0.0, 0.1]])\n        >>> def_preds = np.array([[0.1, 0.1, 0.1, 0.7],\n        ...                       [0.1, 0.6, 0.2, 0.1],\n        ...                       [0.1, 0.2, 0.1, 0.6]])\n        >>> true_labels = np.array([3, 1, 0])\n        >>> def_eval = DefenseEvaluate(raw_preds,\n        ...                            def_preds,\n        ...                            true_labels)\n        >>> cav = def_eval.cav()\n        >>> crr = def_eval.crr()\n        >>> csr = def_eval.csr()\n        >>> ccv = def_eval.ccv()\n        >>> cos = def_eval.cos()\n    \"\"\"\n    def __init__(self, raw_preds, def_preds, true_labels):\n        self._raw_preds, self._def_preds = check_pair_numpy_param('raw_preds',\n                                                                  raw_preds,\n                                                                  'def_preds',\n                                                                  def_preds)\n        self._true_labels = check_numpy_param('true_labels', true_labels)\n        self._num_samples = len(true_labels)\n\n    def cav(self):\n        \"\"\"\n        Calculate classification accuracy variance (CAV).\n\n        Returns:\n            float, the higher, the more successful the defense is.\n        \"\"\"\n        def_succ_num = np.sum(np.argmax(self._def_preds, axis=1)\n                              == self._true_labels)\n        raw_succ_num = np.sum(np.argmax(self._raw_preds, axis=1)\n                              == self._true_labels)\n\n        return (def_succ_num - raw_succ_num) / self._num_samples\n\n    def crr(self):\n        \"\"\"\n        Calculate classification rectify ratio (CRR).\n\n        Returns:\n            float, the higher, the more successful the defense is.\n        \"\"\"\n        cond1 = np.argmax(self._def_preds, axis=1) == self._true_labels\n        cond2 = np.argmax(self._raw_preds, axis=1) != self._true_labels\n        rectify_num = np.sum(cond1*cond2)\n\n        return rectify_num*1.0 / self._num_samples\n\n    def csr(self):\n        \"\"\"\n        Calculate classification sacrifice ratio (CSR), the lower the better.\n\n        Returns:\n            float, the lower, the more successful the defense is.\n        \"\"\"\n        cond1 = np.argmax(self._def_preds, axis=1) != self._true_labels\n        cond2 = np.argmax(self._raw_preds, axis=1) == self._true_labels\n        sacrifice_num = np.sum(cond1*cond2)\n\n        return sacrifice_num*1.0 / self._num_samples\n\n    def ccv(self):\n        \"\"\"\n        Calculate classification confidence variance (CCV).\n\n        Returns:\n            - float, the lower, the more successful the defense is.\n\n              - If return value == -1, len(idxes) == 0.\n        \"\"\"\n        idxes = np.arange(self._num_samples)\n        cond1 = np.argmax(self._def_preds, axis=1) == self._true_labels\n        cond2 = np.argmax(self._raw_preds, axis=1) == self._true_labels\n        idxes = idxes[cond1*cond2]\n\n        def_max = np.max(self._def_preds, axis=1)\n        raw_max = np.max(self._raw_preds, axis=1)\n\n        if idxes.shape[0] == 0:\n            return -1\n        conf_variance = np.mean(np.abs(def_max[idxes] - raw_max[idxes]))\n\n        return conf_variance\n\n    def cos(self):\n        \"\"\"\n        References: `Calculate classification output stability (COS)\n        <https://en.wikipedia.org/wiki/Jensen%E2%80%93Shannon_divergence>`_\n\n        Returns:\n            float.\n\n            - If return value >= 0, is effective defense. The lower, the\n              more successful the defense.\n\n            - If return value == -1, idxes == 0.\n        \"\"\"\n        idxes = np.arange(self._num_samples)\n        cond1 = np.argmax(self._def_preds, axis=1) == self._true_labels\n        cond2 = np.argmax(self._raw_preds, axis=1) == self._true_labels\n        idxes = idxes[cond1*cond2]\n        if idxes.size == 0:\n            return -1\n        def_preds = self._def_preds[idxes]\n        raw_preds = self._raw_preds[idxes]\n\n        js_total = 0.0\n        mean_value = 0.5*(def_preds + raw_preds)\n        for i, value in enumerate(mean_value):\n            js_total += 0.5*st.entropy(def_preds[i], value) \\\n                        + 0.5*st.entropy(raw_preds[i], value)\n\n        return js_total / len(idxes)\n"
  },
  {
    "path": "mindarmour/adv_robustness/evaluations/neuron_metrics.py",
    "content": "# Copyright 2023 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nNeuron sensitivity metrics.\n\"\"\"\n\nimport mindspore as ms\nfrom mindspore import ops\n\nfrom mindarmour.utils.logger import LogUtil\n\n# pylint: disable=redefined-builtin, unused-argument\n\nLOGGER = LogUtil.get_instance()\nTAG = \"NeuronMetric\"\n\n\nclass NeuronMetric:\n    \"\"\"\n    Neuron sensitivity of models towards adversarial examples.\n\n    Args:\n        model (mindspore.nn.Cell): The victim model.\n        inputs (mindspore.Tensor): Original samples.\n        adv_inputs (mindspore.Tensor): Adversarial samples generated from original\n            samples.\n        hook_names (List[str]): The name of the evaluated layers.\n\n    Raises:\n        ValueError: If `output` is no more than 1 dimension.\n\n    Examples:\n        >>> from mindarmour.adv_robustness.evaluations import NeuronMetric\n        >>> from mindspore import ops\n        >>> # Refer to https://gitee.com/mindspore/docs/blob/master/docs/mindspore/code/lenet.py\n        >>> model = LeNet()\n        >>> x = ops.randn((10, 3, 32, 32))\n        >>> adv_x = ops.randn((10, 3, 32, 32))\n        >>> layers = [\"conv1\", \"conv2\", \"fc1\", \"fc2\"]\n        >>> neuron_metric = NeuronMetric(model, x, adv_x, layers)\n        >>> nsense = neuron_metric.neuron_sensitivity()\n    \"\"\"\n\n    def __init__(self, model, inputs, adv_inputs, hook_names):\n        self._model = model\n        self._inputs = inputs\n        self._adv_inputs = adv_inputs\n        self._hook_names = hook_names\n\n        hooks = []\n        self._features = []\n\n        def forward_hook(model, input, output):\n            if len(output.shape) <= 1:\n                msg = 'The output tensor should have more than 1 dimension, \\\n                    but got shape {}'.format(output.shape)\n                LOGGER.error(msg)\n                raise ValueError(msg)\n\n            self._features.append(\n                output.reshape(output.shape[0], output.shape[1], -1).mean(axis=-1)\n            )\n\n        for name in self._hook_names:\n            hook = self._model.__getattr__(name).register_forward_hook(forward_hook)\n            hooks.append(hook)\n\n        self._model(ms.Tensor(self._inputs))\n        self._model(ms.Tensor(self._adv_inputs))\n\n        for hook in hooks:\n            hook.remove()\n\n    def neuron_sensitivity(self):\n        \"\"\"\n        Calculate neuron sensitivity (NS).\n\n        Returns:\n            A dictionary, whose key is the layer name in hook_name,\n            and the value is a numpy.ndarray of neuron sensitivity of each neuron.\n        \"\"\"\n        nsense = {}\n        n = len(self._hook_names)\n        for i in range(n):\n            nsense[self._hook_names[i]] = ops.norm(\n                self._features[i] - self._features[i + n], axis=[0], p=1\n            ).asnumpy()\n\n        return nsense\n"
  },
  {
    "path": "mindarmour/adv_robustness/evaluations/visual_metrics.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n\"\"\"\r\nRadar map.\r\n\"\"\"\r\nfrom math import pi\r\n\r\nimport numpy as np\r\n\r\nimport matplotlib.pyplot as plt\r\n\r\nfrom mindarmour.utils.logger import LogUtil\r\nfrom mindarmour.utils._check_param import check_param_type, check_numpy_param, \\\r\n    check_param_multi_types, check_equal_length\r\n\r\nLOGGER = LogUtil.get_instance()\r\nTAG = 'RadarMetric'\r\n\r\n\r\nclass RadarMetric:\r\n    \"\"\"\r\n    Radar chart to show the robustness of a model by multiple metrics.\r\n\r\n    Args:\r\n        metrics_name (Union[tuple, list]): An array of names of metrics to show.\r\n        metrics_data (numpy.ndarray): The (normalized) values of each metrics of\r\n            multiple radar curves, like [[0.5, 0.8, ...], [0.2,0.6,...], ...].\r\n            Each set of values corresponds to one radar curve.\r\n        labels (Union[tuple, list]): Legends of all radar curves.\r\n        title (str): Title of the chart.\r\n        scale (str): Scalar to adjust axis ticks, such as ``'hide'``, ``'norm'``,\r\n            ``'sparse'`` or ``'dense'``. Default: ``'hide'``.\r\n\r\n    Raises:\r\n        ValueError: If `scale` is not ``'hide'``, ``'norm'``, ``'sparse'``, ``'dense'``.\r\n\r\n    Examples:\r\n        >>> from mindarmour.adv_robustness.evaluations import RadarMetric\r\n        >>> metrics_name = ['MR', 'ACAC', 'ASS', 'NTE', 'ACTC']\r\n        >>> def_metrics = [0.9, 0.85, 0.6, 0.7, 0.8]\r\n        >>> raw_metrics = [0.5, 0.3, 0.55, 0.65, 0.7]\r\n        >>> metrics_data = np.array([def_metrics, raw_metrics])\r\n        >>> metrics_labels = ['before', 'after']\r\n        >>> rm = RadarMetric(metrics_name,\r\n        ...                  metrics_data,\r\n        ...                  metrics_labels,\r\n        ...                  title='',\r\n        ...                  scale='sparse')\r\n        >>> #rm.show()\r\n    \"\"\"\r\n\r\n    def __init__(self, metrics_name, metrics_data, labels, title, scale='hide'):\r\n\r\n        self._metrics_name = check_param_multi_types('metrics_name',\r\n                                                     metrics_name,\r\n                                                     [tuple, list])\r\n        self._metrics_data = check_numpy_param('metrics_data', metrics_data)\r\n        self._labels = check_param_multi_types('labels', labels, (tuple, list))\r\n\r\n        _, _ = check_equal_length('metrics_name', metrics_name,\r\n                                  'metrics_data', self._metrics_data[0])\r\n        _, _ = check_equal_length('labels', labels, 'metrics_data', metrics_data)\r\n        self._title = check_param_type('title', title, str)\r\n        if scale in ['hide', 'norm', 'sparse', 'dense']:\r\n            self._scale = scale\r\n        else:\r\n            msg = \"scale must be in ['hide', 'norm', 'sparse', 'dense'], but \" \\\r\n                  \"got {}\".format(scale)\r\n            LOGGER.error(TAG, msg)\r\n            raise ValueError(msg)\r\n\r\n        self._nb_var = len(metrics_name)\r\n        # divide the plot / number of variable\r\n        self._angles = [n / self._nb_var*2.0*pi for n in\r\n                        range(self._nb_var)]\r\n        self._angles += self._angles[:1]\r\n\r\n        # add one more point\r\n        data = [self._metrics_data, self._metrics_data[:, [0]]]\r\n        self._metrics_data = np.concatenate(data, axis=1)\r\n\r\n    def show(self):\r\n        \"\"\"\r\n        Show the radar chart.\r\n        \"\"\"\r\n        # Initialise the spider plot\r\n        plt.clf()\r\n        axis_pic = plt.subplot(111, polar=True)\r\n        axis_pic.spines['polar'].set_visible(False)\r\n        axis_pic.set_yticklabels([])\r\n\r\n        # If you want the first axis to be on top:\r\n        axis_pic.set_theta_offset(pi / 2)\r\n        axis_pic.set_theta_direction(-1)\r\n\r\n        # Draw one axe per variable + add labels labels yet\r\n        plt.xticks(self._angles[:-1], self._metrics_name)\r\n\r\n        # Draw y labels\r\n        axis_pic.set_rlabel_position(0)\r\n        if self._scale == 'hide':\r\n            plt.yticks([0.0], color=\"grey\", size=7)\r\n        elif self._scale == 'norm':\r\n            plt.yticks([0.2, 0.4, 0.6, 0.8],\r\n                       [\"0.2\", \"0.4\", \"0.6\", \"0.8\"],\r\n                       color=\"grey\", size=7)\r\n        elif self._scale == 'sparse':\r\n            plt.yticks([0.5], [\"0.5\"], color=\"grey\", size=7)\r\n        elif self._scale == 'dense':\r\n            ticks = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]\r\n            labels = [\"0.1\", \"0.2\", \"0.3\", \"0.4\", \"0.5\", \"0.6\",\r\n                      \"0.7\", \"0.8\", \"0.9\"]\r\n            plt.yticks(ticks, labels, color=\"grey\", size=7)\r\n        else:\r\n            # default\r\n            plt.yticks([0.0], color=\"grey\", size=7)\r\n        plt.ylim(0, 1)\r\n\r\n        # plot border\r\n        axis_pic.plot(self._angles, [1]*(self._nb_var + 1), color='grey',\r\n                      linewidth=1, linestyle='solid')\r\n\r\n        for i in range(len(self._labels)):\r\n            axis_pic.plot(self._angles, self._metrics_data[i], linewidth=1,\r\n                          linestyle='solid', label=self._labels[i])\r\n            axis_pic.fill(self._angles, self._metrics_data[i], alpha=0.1)\r\n\r\n        # Add legend\r\n        plt.legend(loc='upper right', bbox_to_anchor=(0., 0.))\r\n        plt.title(self._title, y=1.1, color='g')\r\n        plt.show()\r\n"
  },
  {
    "path": "mindarmour/fuzz_testing/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis module provides a neuron coverage-gain based fuzz method to evaluate the\nrobustness of given model.\n\"\"\"\nfrom .fuzzing import Fuzzer, SensitivityMaximizingFuzzer\nfrom .model_coverage_metrics import CoverageMetrics, NeuronCoverage, TopKNeuronCoverage, NeuronBoundsCoverage, \\\n    SuperNeuronActivateCoverage, KMultisectionNeuronCoverage\nfrom .sensitivity_convergence_coverage import SensitivityConvergenceCoverage\n\n__all__ = ['Fuzzer',\n           'CoverageMetrics',\n           'NeuronCoverage',\n           'TopKNeuronCoverage',\n           'NeuronBoundsCoverage',\n           'SuperNeuronActivateCoverage',\n           'KMultisectionNeuronCoverage',\n           'SensitivityConvergenceCoverage',\n           'SensitivityMaximizingFuzzer']\n"
  },
  {
    "path": "mindarmour/fuzz_testing/fuzzing.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nFuzzing.\n\"\"\"\nfrom random import choice\nfrom copy import deepcopy\nimport numpy as np\nfrom mindspore import Model\nfrom mindspore import Tensor\nfrom mindspore import nn\n\nfrom mindarmour.utils._check_param import check_model, check_numpy_param, check_param_multi_types, check_norm_level, \\\n    check_param_in_range, check_param_type, check_int_positive, check_param_bounds\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.adv_robustness.attacks import FastGradientSignMethod, \\\n    MomentumDiverseInputIterativeMethod, ProjectedGradientDescent\nfrom mindarmour.natural_robustness.transform.image import GaussianBlur, MotionBlur, GradientBlur, UniformNoise,\\\n    GaussianNoise, SaltAndPepperNoise, NaturalNoise, Contrast, GradientLuminance, Translate, Scale, Shear, Rotate, \\\n    Perspective, Curve\nfrom .model_coverage_metrics import CoverageMetrics, KMultisectionNeuronCoverage\n\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Fuzzer'\n\n\ndef _select_next(initial_seeds):\n    \"\"\" Randomly select a seed from `initial_seeds`.\"\"\"\n    seed_num = choice(range(len(initial_seeds)))\n    seed = initial_seeds[seed_num]\n    del initial_seeds[seed_num]\n    return seed, initial_seeds\n\n\ndef _coverage_gains(pre_coverage, coverages):\n    \"\"\"\n    Calculate the coverage gains of mutated samples.\n\n    Args:\n        pre_coverage (float): Last value of coverages for previous mutated samples.\n        coverages (list): Coverage of mutated samples.\n\n    Returns:\n        - list, coverage gains for mutated samples.\n\n        - float, last value in parameter coverages.\n    \"\"\"\n    gains = [pre_coverage] + coverages[:-1]\n    gains = np.array(coverages) - np.array(gains)\n    return gains, coverages[-1]\n\n\ndef _is_trans_valid(seed, mutate_sample):\n    \"\"\"\n    Check a mutated sample is valid. If the number of changed pixels in\n    a seed is less than pixels_change_rate*size(seed), this mutate is valid.\n    Else check the infinite norm of seed changes, if the value of the\n    infinite norm less than pixel_value_change_rate*255, this mutate is\n    valid too. Otherwise the opposite.\n    \"\"\"\n    is_valid = False\n    pixels_change_rate = 0.02\n    pixel_value_change_rate = 0.2\n    diff = np.array(seed - mutate_sample).flatten()\n    size = np.shape(diff)[0]\n    l0_norm = np.linalg.norm(diff, ord=0)\n    linf = np.linalg.norm(diff, ord=np.inf)\n    if l0_norm > pixels_change_rate * size:\n        if linf < 256:\n            is_valid = True\n    else:\n        if linf < pixel_value_change_rate * 255:\n            is_valid = True\n    return is_valid\n\n\ndef _gain_threshold(coverage):\n    \"\"\"Get threshold for given neuron coverage class.\"\"\"\n    if coverage is isinstance(coverage, KMultisectionNeuronCoverage):\n        gain_threshold = 0.1 / coverage.segmented_num\n    else:\n        gain_threshold = 0\n    return gain_threshold\n\n\nclass Fuzzer:\n    \"\"\"\n    Fuzzing test framework for deep neural networks.\n\n    Reference: `DeepHunter: A Coverage-Guided Fuzz Testing Framework for Deep\n    Neural Networks <https://dl.acm.org/doi/10.1145/3293882.3330579>`_\n\n    Args:\n        target_model (Model): Target fuzz model.\n\n    Examples:\n        >>> from mindspore.common.initializer import TruncatedNormal\n        >>> from mindspore.ops import operations as P\n        >>> from mindspore.train import Model\n        >>> from mindspore.ops import TensorSummary\n        >>> from mindarmour.fuzz_testing import Fuzzer\n        >>> from mindarmour.fuzz_testing import KMultisectionNeuronCoverage\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self.conv1 = nn.Conv2d(1, 6, 5, padding=0, weight_init=TruncatedNormal(0.02), pad_mode=\"valid\")\n        ...         self.conv2 = nn.Conv2d(6, 16, 5, padding=0, weight_init=TruncatedNormal(0.02), pad_mode=\"valid\")\n        ...         self.fc1 = nn.Dense(16 * 5 * 5, 120, TruncatedNormal(0.02), TruncatedNormal(0.02))\n        ...         self.fc2 = nn.Dense(120, 84, TruncatedNormal(0.02), TruncatedNormal(0.02))\n        ...         self.fc3 = nn.Dense(84, 10, TruncatedNormal(0.02), TruncatedNormal(0.02))\n        ...         self.relu = nn.ReLU()\n        ...         self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)\n        ...         self.reshape = P.Reshape()\n        ...         self.summary = TensorSummary()\n        ...\n        ...     def construct(self, x):\n        ...         x = self.conv1(x)\n        ...         x = self.relu(x)\n        ...         self.summary('conv1', x)\n        ...         x = self.max_pool2d(x)\n        ...         x = self.conv2(x)\n        ...         x = self.relu(x)\n        ...         self.summary('conv2', x)\n        ...         x = self.max_pool2d(x)\n        ...         x = self.reshape(x, (-1, 16 * 5 * 5))\n        ...         x = self.fc1(x)\n        ...         x = self.relu(x)\n        ...         self.summary('fc1', x)\n        ...         x = self.fc2(x)\n        ...         x = self.relu(x)\n        ...         self.summary('fc2', x)\n        ...         x = self.fc3(x)\n        ...         self.summary('fc3', x)\n        ...         return x\n        >>> net = Net()\n        >>> model = Model(net)\n        >>> mutate_config = [{'method': 'GaussianBlur',\n        ...                   'params': {'ksize': [1, 2, 3, 5], 'auto_param': [True, False]}},\n        ...                  {'method': 'MotionBlur',\n        ...                   'params': {'degree': [1, 2, 5], 'angle': [45, 10, 100, 140, 210, 270, 300],\n        ...                   'auto_param': [True]}},\n        ...                  {'method': 'UniformNoise',\n        ...                   'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n        ...                  {'method': 'GaussianNoise',\n        ...                   'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n        ...                  {'method': 'Contrast',\n        ...                   'params': {'alpha': [0.5, 1, 1.5], 'beta': [-10, 0, 10], 'auto_param': [False, True]}},\n        ...                  {'method': 'Rotate',\n        ...                   'params': {'angle': [20, 90], 'auto_param': [False, True]}},\n        ...                  {'method': 'FGSM',\n        ...                   'params': {'eps': [0.3, 0.2, 0.4], 'alpha': [0.1], 'bounds': [(0, 1)]}}]\n        >>> batch_size = 8\n        >>> num_classe = 10\n        >>> train_images = np.random.rand(32, 1, 32, 32).astype(np.float32)\n        >>> test_images = np.random.rand(batch_size, 1, 32, 32).astype(np.float32)\n        >>> test_labels = np.random.randint(num_classe, size=batch_size).astype(np.int32)\n        >>> test_labels = (np.eye(num_classe)[test_labels]).astype(np.float32)\n        >>> initial_seeds = []\n        >>> # make initial seeds\n        >>> for img, label in zip(test_images, test_labels):\n        ...     initial_seeds.append([img, label])\n        >>> initial_seeds = initial_seeds[:10]\n        >>> nc = KMultisectionNeuronCoverage(model, train_images, segmented_num=100, incremental=True)\n        >>> model_fuzz_test = Fuzzer(model)\n        >>> samples, gt_labels, preds, strategies, metrics = model_fuzz_test.fuzzing(mutate_config, initial_seeds,\n        ...                                                                          nc, max_iters=100)\n    \"\"\"\n\n    def __init__(self, target_model):\n        self._target_model = check_model('model', target_model, Model)\n\n        # Allowed mutate strategies so far.\n        self._strategies = {'Contrast': Contrast,\n                            'GradientLuminance': GradientLuminance,\n                            'GaussianBlur': GaussianBlur,\n                            'MotionBlur': MotionBlur,\n                            'GradientBlur': GradientBlur,\n                            'UniformNoise': UniformNoise,\n                            'GaussianNoise': GaussianNoise,\n                            'SaltAndPepperNoise': SaltAndPepperNoise,\n                            'NaturalNoise': NaturalNoise,\n                            'Translate': Translate,\n                            'Scale': Scale,\n                            'Shear': Shear,\n                            'Rotate': Rotate,\n                            'Perspective': Perspective,\n                            'Curve': Curve,\n                            'FGSM': FastGradientSignMethod,\n                            'PGD': ProjectedGradientDescent,\n                            'MDIIM': MomentumDiverseInputIterativeMethod}\n        self._affine_trans_list = ['Translate', 'Scale', 'Shear', 'Rotate', 'Perspective', 'Curve']\n        self._pixel_value_trans_list = ['Contrast', 'GradientLuminance', 'GaussianBlur', 'MotionBlur', 'GradientBlur',\n                                        'UniformNoise', 'GaussianNoise', 'SaltAndPepperNoise', 'NaturalNoise']\n        self._attacks_list = ['FGSM', 'PGD', 'MDIIM']\n        self._attack_param_checklists = {\n            'FGSM': {'eps': {'dtype': [float], 'range': [0, 1]},\n                     'alpha': {'dtype': [float], 'range': [0, 1]},\n                     'bounds': {'dtype': [tuple, list]}},\n            'PGD': {'eps': {'dtype': [float], 'range': [0, 1]},\n                    'eps_iter': {'dtype': [float], 'range': [0, 1]},\n                    'nb_iter': {'dtype': [int]},\n                    'bounds': {'dtype': [tuple, list]}},\n            'MDIIM': {'eps': {'dtype': [float], 'range': [0, 1]},\n                      'norm_level': {'dtype': [str, int],\n                                     'range': [1, 2, '1', '2', 'l1', 'l2', 'inf', 'linf', 'np.inf']},\n                      'prob': {'dtype': [float], 'range': [0, 1]},\n                      'bounds': {'dtype': [tuple, list]}}}\n\n    def fuzzing(self, mutate_config, initial_seeds, coverage, evaluate=True, max_iters=10000, mutate_num_per_seed=20):\n        \"\"\"\n        Fuzzing tests for deep neural networks.\n\n        Args:\n            mutate_config (list): Mutate configs. The format is as follows:\n\n                .. code-block:: python\n\n                  mutate_config = [\n                      {'method': 'GaussianBlur',\n                       'params': {'ksize': [1, 2, 3, 5], 'auto_param': [True, False]}},\n                      {'method': 'UniformNoise',\n                       'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n                      {'method': 'GaussianNoise',\n                       'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n                      {'method': 'Contrast',\n                       'params': {'alpha': [0.5, 1, 1.5], 'beta': [-10, 0, 10], 'auto_param': [False, True]}},\n                      {'method': 'Rotate',\n                       'params': {'angle': [20, 90], 'auto_param': [False, True]}},\n                      {'method': 'FGSM',\n                       'params': {'eps': [0.3, 0.2, 0.4], 'alpha': [0.1], 'bounds': [(0, 1)]}}\n                      ...]\n\n                The supported methods list is in `self._strategies`, and the params of each method must within the\n                range of optional parameters. Supported methods are grouped in two types: Firstly, natural robustness\n                methods include: 'Translate', 'Scale', 'Shear', 'Rotate', 'Perspective', 'Curve', 'GaussianBlur',\n                'MotionBlur', 'GradientBlur', 'Contrast', 'GradientLuminance', 'UniformNoise', 'GaussianNoise',\n                'SaltAndPepperNoise', 'NaturalNoise'. Secondly, attack methods include: 'FGSM',\n                'PGD' and 'MDIIM'. 'FGSM', 'PGD' and 'MDIIM'. are abbreviations of FastGradientSignMethod,\n                ProjectedGradientDescent and MomentumDiverseInputIterativeMethod.\n                `mutate_config` must have method in ['Contrast', 'GradientLuminance', 'GaussianBlur', 'MotionBlur',\n                'GradientBlur', 'UniformNoise', 'GaussianNoise', 'SaltAndPepperNoise', 'NaturalNoise'].\n                The way of setting parameters for first and second type methods can be seen in\n                'mindarmour/natural_robustness/transform/image'. For third type methods, the optional parameters refer\n                to `self._attack_param_checklists`.\n            initial_seeds (list[list]): Initial seeds used to generate mutated samples. The format of initial seeds is\n                [[image_data, label], [...], ...] and the label must be one-hot.\n            coverage (CoverageMetrics): Class of neuron coverage metrics.\n            evaluate (bool): return evaluate report or not. Default: ``True``.\n            max_iters (int): Max number of select a seed to mutate. Default: ``10000``.\n            mutate_num_per_seed (int): The number of mutate times for a seed. Default: ``20``.\n\n        Returns:\n            - list, mutated samples in fuzz_testing.\n\n            - list, ground truth labels of mutated samples.\n\n            - list, preds of mutated samples.\n\n            - list, strategies of mutated samples.\n\n            - dict, metrics report of fuzzer.\n\n        Raises:\n            ValueError: Coverage must be subclass of CoverageMetrics.\n            ValueError: If initial seeds is empty.\n            ValueError: If element of seed is not two in initial seeds.\n        \"\"\"\n        # Check parameters.\n        if not isinstance(coverage, CoverageMetrics):\n            msg = 'coverage must be subclass of CoverageMetrics'\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        evaluate = check_param_type('evaluate', evaluate, bool)\n        max_iters = check_int_positive('max_iters', max_iters)\n        mutate_num_per_seed = check_int_positive('mutate_num_per_seed', mutate_num_per_seed)\n        mutate_config = self._check_mutate_config(mutate_config)\n        mutates = self._init_mutates(mutate_config)\n\n        initial_seeds = check_param_type('initial_seeds', initial_seeds, list)\n        init_seeds = deepcopy(initial_seeds)\n        if not init_seeds:\n            msg = 'initial_seeds must not be empty.'\n            raise ValueError(msg)\n        initial_samples = []\n        for seed in init_seeds:\n            check_param_type('seed', seed, list)\n            if len(seed) != 2:\n                msg = 'seed in initial seeds must have two element image and label, but got {} element.'.format(\n                    len(seed))\n                raise ValueError(msg)\n            check_numpy_param('seed[0]', seed[0])\n            check_numpy_param('seed[1]', seed[1])\n            initial_samples.append(seed[0])\n            seed.append(0)\n        initial_samples = np.array(initial_samples)\n        # calculate the coverage of initial seeds\n        pre_coverage = coverage.get_metrics(initial_samples)\n        gain_threshold = _gain_threshold(coverage)\n\n        seed, init_seeds = _select_next(init_seeds)\n        fuzz_samples = []\n        true_labels = []\n        fuzz_preds = []\n        fuzz_strategies = []\n        iter_num = 0\n        while init_seeds and iter_num < max_iters:\n            # Mutate a seed.\n            mutate_samples, mutate_strategies = self._metamorphic_mutate(seed, mutates, mutate_config,\n                                                                         mutate_num_per_seed)\n            # Calculate the coverages and predictions of generated samples.\n            coverages, predicts = self._get_coverages_and_predict(mutate_samples, coverage)\n            coverage_gains, pre_coverage = _coverage_gains(pre_coverage, coverages)\n            for mutate, cov, pred, strategy in zip(mutate_samples, coverage_gains, predicts, mutate_strategies):\n                fuzz_samples.append(mutate[0])\n                true_labels.append(mutate[1])\n                fuzz_preds.append(pred)\n                fuzz_strategies.append(strategy)\n                # if the mutate samples has coverage gains add this samples in the initial_seeds to guide new mutates.\n                if cov > gain_threshold:\n                    init_seeds.append(mutate)\n            seed, init_seeds = _select_next(init_seeds)\n            iter_num += 1\n        metrics_report = None\n        if evaluate:\n            metrics_report = self._evaluate(fuzz_samples, true_labels, fuzz_preds, fuzz_strategies, coverage)\n        return fuzz_samples, true_labels, fuzz_preds, fuzz_strategies, metrics_report\n\n    def _get_coverages_and_predict(self, mutate_samples, coverage):\n        \"\"\" Calculate the coverages and predictions of generated samples.\"\"\"\n        samples = [s[0] for s in mutate_samples]\n        samples = np.array(samples)\n        coverages = []\n        predictions = self._target_model.predict(Tensor(samples.astype(np.float32)))\n        predictions = predictions.asnumpy()\n        for index in range(len(samples)):\n            mutate = samples[:index + 1]\n            coverages.append(coverage.get_metrics(mutate))\n        return coverages, predictions\n\n    def _metamorphic_mutate(self, seed, mutates, mutate_config, mutate_num_per_seed):\n        \"\"\"Mutate a seed using strategies random selected from mutate_config.\"\"\"\n        mutate_samples = []\n        mutate_strategies = []\n        for _ in range(mutate_num_per_seed):\n            only_pixel_trans = seed[2]\n            strategy = choice(mutate_config)\n            # Choose a pixel value based transform method\n            if only_pixel_trans:\n                while strategy['method'] not in self._pixel_value_trans_list:\n                    strategy = choice(mutate_config)\n            params = strategy['params']\n            method = strategy['method']\n            selected_param = {}\n            for param in params:\n                selected_param[param] = choice(params[param])\n\n            if method in list(self._pixel_value_trans_list + self._affine_trans_list):\n                if method == 'Shear':\n                    shear_keys = selected_param.keys()\n                    if 'factor_x' in shear_keys and 'factor_y' in shear_keys:\n                        selected_param[choice(['factor_x', 'factor_y'])] = 0\n                transform = mutates[strategy['method']](**selected_param)\n                mutate_sample = transform(seed[0])\n            else:\n                transform = mutates[strategy['method']]\n                for param_name in selected_param:\n                    transform.__setattr__('_' + str(param_name), selected_param[param_name])\n                mutate_sample = transform.generate(np.array([seed[0].astype(np.float32)]), np.array([seed[1]]))[0]\n            if method not in self._pixel_value_trans_list:\n                only_pixel_trans = 1\n            mutate_sample = [mutate_sample, seed[1], only_pixel_trans]\n            if _is_trans_valid(seed[0], mutate_sample[0]):\n                mutate_samples.append(mutate_sample)\n                mutate_strategies.append(method)\n        if not mutate_samples:\n            mutate_samples.append(seed)\n            mutate_strategies.append(None)\n        return np.array(mutate_samples), mutate_strategies\n\n    def _check_mutate_config(self, mutate_config):\n        \"\"\"Check whether the mutate_config meet the specification.\"\"\"\n        mutate_config = check_param_type('mutate_config', mutate_config, list)\n        has_pixel_trans = False\n\n        for config in mutate_config:\n            check_param_type(\"config\", config, dict)\n            if set(config.keys()) != {'method', 'params'}:\n                msg = \"The key of each config must be in ('method', 'params'), but got {}.\".format(set(config.keys()))\n                LOGGER.error(TAG, msg)\n                raise KeyError(msg)\n\n            method = config['method']\n            params = config['params']\n\n            # Method must be in the optional range.\n            if method not in self._strategies.keys():\n                msg = \"Config methods must be in {}, but got {}.\".format(self._strategies.keys(), method)\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n\n            if config['method'] in self._pixel_value_trans_list:\n                has_pixel_trans = True\n\n            check_param_type('params', params, dict)\n            # Check parameters of attack methods. The parameters of transformed\n            # methods will be verified in transferred parameters.\n            if method in self._attacks_list:\n                self._check_attack_params(method, params)\n            else:\n                for key in params.keys():\n                    check_param_type(str(key), params[key], list)\n        # Methods in `metate_config` should at least have one in the type of pixel value based transform methods.\n        if not has_pixel_trans:\n            msg = \"mutate methods in mutate_config should at least have one in {}\".format(self._pixel_value_trans_list)\n            raise ValueError(msg)\n\n        return mutate_config\n\n    def _check_attack_params(self, method, params):\n        \"\"\"Check input parameters of attack methods.\"\"\"\n        allow_params = self._attack_param_checklists[method].keys()\n        for param_name in params:\n            if param_name not in allow_params:\n                msg = \"parameters of {} must in {}\".format(method, allow_params)\n                raise ValueError(msg)\n\n            check_param_type(param_name, params[param_name], list)\n            for param_value in params[param_name]:\n                if param_name == 'bounds':\n                    _ = check_param_bounds('bounds', param_value)\n                elif param_name == 'norm_level':\n                    _ = check_norm_level(param_value)\n                elif param_name == 'nb_iter':\n                    _ = check_int_positive(param_name, param_value)\n                else:\n                    try:\n                        allow_type = self._attack_param_checklists[method][param_name]['dtype']\n                    except KeyError:\n                        RuntimeError(\"The dtype of {} is not defined in attack_param_checklists\".format(param_name))\n                    try:\n                        allow_range = self._attack_param_checklists[method][param_name]['range']\n                    except KeyError:\n                        RuntimeError(\"The range of {} is not defined in attack_param_checklists\".format(param_name))\n                    _ = check_param_multi_types(str(param_name), param_value, allow_type)\n                    _ = check_param_in_range(str(param_name), param_value, allow_range[0], allow_range[1])\n\n    def _init_mutates(self, mutate_config):\n        \"\"\" Check whether the mutate_config meet the specification.\"\"\"\n        mutates = {}\n        for mutate in mutate_config:\n            method = mutate['method']\n            if method not in self._attacks_list:\n                try:\n                    mutates[method] = self._strategies[method]\n                except KeyError:\n                    RuntimeError(\"The method {} is not defined in strategies\".format(method))\n            else:\n                network = self._target_model._network\n                loss_fn = self._target_model._loss_fn\n                if loss_fn is None:\n                    loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=False)\n                mutates[method] = self._strategies[method](network, loss_fn=loss_fn)\n        return mutates\n\n    def _evaluate(self, fuzz_samples, true_labels, fuzz_preds, fuzz_strategies, coverage):\n        \"\"\"\n        Evaluate generated fuzz_testing samples in three dimensions: accuracy, attack success rate and neural coverage.\n\n        Args:\n            fuzz_samples ([numpy.ndarray, list]): Generated fuzz_testing samples according to seeds.\n            true_labels ([numpy.ndarray, list]): Ground truth labels of seeds.\n            fuzz_preds ([numpy.ndarray, list]): Predictions of generated fuzz samples.\n            fuzz_strategies ([numpy.ndarray, list]): Mutate strategies of fuzz samples.\n            coverage (CoverageMetrics): Neuron coverage metrics class.\n\n        Returns:\n            dict, evaluate metrics include accuracy, attack success rate and neural coverage.\n        \"\"\"\n        fuzz_samples = np.array(fuzz_samples)\n        true_labels = np.asarray(true_labels)\n        fuzz_preds = np.asarray(fuzz_preds)\n        temp = np.argmax(true_labels, axis=1) == np.argmax(fuzz_preds, axis=1)\n        metrics_report = {}\n\n        if temp.any():\n            acc = np.sum(temp) / np.size(temp)\n        else:\n            acc = 0\n        metrics_report['Accuracy'] = acc\n\n        cond = [elem in self._attacks_list for elem in fuzz_strategies]\n        temp = temp[cond]\n        if temp.any():\n            attack_success_rate = 1 - np.sum(temp) / np.size(temp)\n        else:\n            attack_success_rate = None\n        metrics_report['Attack_success_rate'] = attack_success_rate\n        metrics_report['Coverage_metrics'] = coverage.get_metrics(fuzz_samples)\n\n        return metrics_report\n\n\nclass SensitivityMaximizingFuzzer(Fuzzer):\n    \"\"\"\n    Fuzzing test framework for deep neural networks.\n\n    Reference:\n        `Themis_Sensitivity_Testing_for_Deep_Learning_System\n        <https://huangd1999.github.io/Themis__Sensitivity_Testing_for_Deep_Learning_System.pdf>`_\n\n    Args:\n        target_model (Model): Target fuzz model.\n\n    Examples:\n        >>> from mindspore.common.initializer import TruncatedNormal\n        >>> from mindspore.ops import operations as P\n        >>> from mindspore.train import Model\n        >>> from mindspore.ops import TensorSummary\n        >>> from mindarmour.fuzz_testing import Fuzzer, SensitivityMaximizingFuzzer\n        >>> from mindarmour.fuzz_testing import SensitivityConvergenceCoverage\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self.conv1 = nn.Conv2d(1, 6, 5, padding=0, weight_init=TruncatedNormal(0.02), pad_mode=\"valid\")\n        ...         self.conv2 = nn.Conv2d(6, 16, 5, padding=0, weight_init=TruncatedNormal(0.02), pad_mode=\"valid\")\n        ...         self.fc1 = nn.Dense(16 * 5 * 5, 120, TruncatedNormal(0.02), TruncatedNormal(0.02))\n        ...         self.fc2 = nn.Dense(120, 84, TruncatedNormal(0.02), TruncatedNormal(0.02))\n        ...         self.fc3 = nn.Dense(84, 10, TruncatedNormal(0.02), TruncatedNormal(0.02))\n        ...         self.relu = nn.ReLU()\n        ...         self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)\n        ...         self.reshape = P.Reshape()\n        ...         self.summary = TensorSummary()\n        ...\n        ...     def construct(self, x):\n        ...         x = self.conv1(x)\n        ...         x = self.relu(x)\n        ...         self.summary('conv1', x)\n        ...         x = self.max_pool2d(x)\n        ...         x = self.conv2(x)\n        ...         x = self.relu(x)\n        ...         self.summary('conv2', x)\n        ...         x = self.max_pool2d(x)\n        ...         x = self.reshape(x, (-1, 16 * 5 * 5))\n        ...         x = self.fc1(x)\n        ...         x = self.relu(x)\n        ...         self.summary('fc1', x)\n        ...         x = self.fc2(x)\n        ...         x = self.relu(x)\n        ...         self.summary('fc2', x)\n        ...         x = self.fc3(x)\n        ...         self.summary('fc3', x)\n        ...         return x\n        >>> net = Net()\n        >>> model = Model(net)\n        >>> mutate_config = [{'method': 'GaussianBlur',\n        ...                   'params': {'ksize': [1, 2, 3, 5], 'auto_param': [True, False]}},\n        ...                  {'method': 'MotionBlur',\n        ...                   'params': {'degree': [1, 2, 5], 'angle': [45, 10, 100, 140, 210, 270, 300],\n        ...                   'auto_param': [True]}},\n        ...                  {'method': 'UniformNoise',\n        ...                   'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n        ...                  {'method': 'GaussianNoise',\n        ...                   'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n        ...                  {'method': 'Contrast',\n        ...                   'params': {'alpha': [0.5, 1, 1.5], 'beta': [-10, 0, 10], 'auto_param': [False, True]}},\n        ...                  {'method': 'Rotate',\n        ...                   'params': {'angle': [20, 90], 'auto_param': [False, True]}},\n        ...                  {'method': 'FGSM',\n        ...                   'params': {'eps': [0.3, 0.2, 0.4], 'alpha': [0.1], 'bounds': [(0, 1)]}}]\n        >>> batch_size = 32\n        >>> num_classe = 10\n        >>> train_images = np.random.rand(32, 1, 32, 32).astype(np.float32)\n        >>> test_images = np.random.rand(batch_size, 1, 32, 32).astype(np.float32)\n        >>> test_labels = np.random.randint(num_classe, size=batch_size).astype(np.int32)\n        >>> test_labels = (np.eye(num_classe)[test_labels]).astype(np.float32)\n        >>> initial_seeds = []\n        >>> # make initial seeds\n        >>> for img, label in zip(test_images, test_labels):\n        ...     initial_seeds.append([img, label])\n        >>> initial_seeds = initial_seeds[:batch_size]\n        >>> SCC = SensitivityConvergenceCoverage(model,batch_size = batch_size)\n        >>> model_fuzz_test = SensitivityMaximizingFuzzer(model)\n        >>> samples, gt_labels, preds, strategies, metrics = model_fuzz_test.fuzzing(mutate_config, initial_seeds,\n        ...                                                                          SCC, max_iters=100)\n    \"\"\"\n\n    def __init__(self, target_model):\n        super(SensitivityMaximizingFuzzer, self).__init__(target_model)\n        self._target_model = target_model\n\n    def fuzzing(self, mutate_config, initial_seeds,\n                coverage, evaluate=True, max_iters=1000, mutate_num_per_seed=20):\n        \"\"\"\n        Fuzzing tests for deep neural networks.\n\n        Args:\n            mutate_config (list): Mutate configs. The format is as follows:\n\n                .. code-block:: python\n\n                  mutate_config = [\n                      {'method': 'GaussianBlur',\n                       'params': {'ksize': [1, 2, 3, 5], 'auto_param': [True, False]}},\n                      {'method': 'UniformNoise',\n                       'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n                      {'method': 'GaussianNoise',\n                       'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n                      {'method': 'Contrast',\n                       'params': {'alpha': [0.5, 1, 1.5], 'beta': [-10, 0, 10], 'auto_param': [False, True]}},\n                      {'method': 'Rotate',\n                       'params': {'angle': [20, 90], 'auto_param': [False, True]}},\n                      {'method': 'FGSM',\n                       'params': {'eps': [0.3, 0.2, 0.4], 'alpha': [0.1], 'bounds': [(0, 1)]}}\n                      ...]\n\n                The supported methods list is in `self._strategies`, and the params of each method must within the\n                range of optional parameters. Supported methods are grouped in two types: Firstly, natural robustness\n                methods include: 'Translate', 'Scale', 'Shear', 'Rotate', 'Perspective', 'Curve', 'GaussianBlur',\n                'MotionBlur', 'GradientBlur', 'Contrast', 'GradientLuminance', 'UniformNoise', 'GaussianNoise',\n                'SaltAndPepperNoise', 'NaturalNoise'. Secondly, attack methods include: 'FGSM',\n                'PGD' and 'MDIIM'. 'FGSM', 'PGD' and 'MDIIM'. are abbreviations of FastGradientSignMethod,\n                ProjectedGradientDescent and MomentumDiverseInputIterativeMethod.\n                `mutate_config` must have method in ['Contrast', 'GradientLuminance', 'GaussianBlur', 'MotionBlur',\n                'GradientBlur', 'UniformNoise', 'GaussianNoise', 'SaltAndPepperNoise', 'NaturalNoise'].\n                The way of setting parameters for first and second type methods can be seen in\n                'mindarmour/natural_robustness/transform/image'. For third type methods, the optional parameters refer\n                to `self._attack_param_checklists`.\n            initial_seeds (list[list]): Initial seeds used to generate mutated samples. The format of initial seeds is\n                [[image_data, label], [...], ...] and the label must be one-hot.\n            coverage (CoverageMetrics): Class of neuron coverage metrics.\n            evaluate (bool): return evaluate report or not. Default: ``True``.\n            max_iters (int): Max number of select a seed to mutate. Default: ``1000``.\n            mutate_num_per_seed (int): The number of mutate times for a seed. Default: ``20``.\n\n\n        Returns:\n            - list, mutated samples in fuzz_testing.\n\n            - list, ground truth labels of mutated samples.\n\n            - list, preds of mutated samples.\n\n            - list, strategies of mutated samples.\n\n            - dict, metrics report of fuzzer.\n\n        Raises:\n            ValueError: Coverage must be subclass of CoverageMetrics.\n            ValueError: If initial seeds is empty.\n            ValueError: If element of seed is not two in initial seeds.\n        \"\"\"\n\n        if not isinstance(coverage, CoverageMetrics):\n            msg = 'coverage must be subclass of CoverageMetrics'\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        evaluate = check_param_type('evaluate', evaluate, bool)\n        max_iters = check_int_positive('max_iters', max_iters)\n        mutate_num_per_seed = check_int_positive('mutate_num_per_seed', mutate_num_per_seed)\n        mutate_config = self._check_mutate_config(mutate_config)\n        mutates = self._init_mutates(mutate_config)\n\n        initial_seeds = check_param_type('initial_seeds', initial_seeds, list)\n        init_seeds = deepcopy(initial_seeds)\n        if not init_seeds:\n            msg = 'initial_seeds must not be empty.'\n            raise ValueError(msg)\n        initial_samples = []\n        initial_mutation_samples = []\n        best_mutate_strategies = []\n        best_mutate_labels = []\n        for seed in init_seeds:\n            check_param_type('seed', seed, list)\n            if len(seed) != 2:\n                msg = 'seed in initial seeds must have two element image and label, but got {} element.'.format(\n                    len(seed))\n                raise ValueError(msg)\n            check_numpy_param('seed[0]', seed[0])\n            check_numpy_param('seed[1]', seed[1])\n            initial_samples.append(seed[0])\n            best_mutate_labels.append(seed[1])\n            seed.append(0)\n            mutation_seed, mutate_strategy = self._metamorphic_mutate(seed, mutates, mutate_config,\n                                                                      mutate_num_per_seed=1)\n            initial_mutation_samples.append(mutation_seed[0][0])\n            best_mutate_strategies.append(mutate_strategy)\n\n        initial_samples = np.array(initial_samples)\n        best_mutate_labels = np.array(best_mutate_labels)\n        initial_mutation_samples = np.array(initial_mutation_samples)\n        # calculate the coverage of initial seeds\n\n        fuzz_samples = []\n        true_labels = []\n        fuzz_preds = []\n        fuzz_strategies = []\n        iter_num = 0\n\n        best_mutate_samples = deepcopy(initial_mutation_samples)\n        pre_coverage, predicts = self._get_coverages_and_predict(\n            np.concatenate((initial_samples, initial_mutation_samples), axis=0),\n            coverage\n        )\n        best_mutate_preds = deepcopy(predicts)\n        while iter_num < max_iters and pre_coverage < 1.0:\n            # Mutate a seed.\n            current_mutate_seeds = []\n            current_mutate_samples = []\n            mutate_strategies = []\n            for seed in init_seeds:\n                mutate_seed, mutate_strategy = self._metamorphic_mutate(seed, mutates, mutate_config,\n                                                                        mutate_num_per_seed=1)\n                current_mutate_seeds.append(mutate_seed)\n                current_mutate_samples.append(mutate_seed[0][0])\n                mutate_strategies.append(mutate_strategy)\n            current_mutate_samples = np.array(current_mutate_samples)\n            # Calculate the coverages and predictions of generated samples.\n            current_coverage, predicts = self._get_coverages_and_predict(np.concatenate((initial_samples,\n                                                                                         current_mutate_samples),\n                                                                                        axis=0), coverage)\n\n            # Add mutated samples to fuzz_samples.\n            for mutate, pred, strategy in zip(current_mutate_seeds, predicts, mutate_strategies):\n                fuzz_samples.append(mutate[0][0])\n                true_labels.append(mutate[0][1])\n                fuzz_preds.append(pred)\n                fuzz_strategies.append(strategy)\n                # if the mutate samples has coverage gains add this samples in the initial_seeds to guide new mutates.\n            if current_coverage > pre_coverage:\n                pre_coverage = current_coverage\n                best_mutate_samples = deepcopy(current_mutate_samples)\n                best_mutate_preds = deepcopy(predicts)\n                best_mutate_strategies = deepcopy(mutate_strategies)\n\n            iter_num += 1\n        metrics_report = None\n        if evaluate:\n            metrics_report = self._evaluate(best_mutate_samples, best_mutate_labels, best_mutate_preds,\n                                            best_mutate_strategies, coverage)\n        return [fuzz_samples, true_labels, fuzz_preds, fuzz_strategies, metrics_report]\n\n    def _get_coverages_and_predict(self, mutate_samples, coverage):\n        \"\"\" Calculate the coverages and predictions of generated samples.\"\"\"\n        samples = deepcopy(mutate_samples)\n        current_mutate_samples = samples[len(samples)//2:]\n        samples = np.array(samples)\n        predictions = self._target_model.predict(Tensor(current_mutate_samples.astype(np.float32)))\n        predictions = predictions.asnumpy()\n        current_coverage = coverage.get_metrics(samples)\n        return current_coverage, predictions\n\n    def _evaluate(self, fuzz_samples, true_labels, fuzz_preds, fuzz_strategies, coverage):\n        \"\"\"\n        Evaluate generated fuzz_testing samples in three dimensions: accuracy, attack success rate and neural coverage.\n\n        Args:\n            fuzz_samples ([numpy.ndarray, list]): Generated fuzz_testing samples according to seeds.\n            true_labels ([numpy.ndarray, list]): Ground truth labels of seeds.\n            fuzz_preds ([numpy.ndarray, list]): Predictions of generated fuzz samples.\n            fuzz_strategies ([numpy.ndarray, list]): Mutate strategies of fuzz samples.\n            coverage (CoverageMetrics): Neuron coverage metrics class.\n\n        Returns:\n            dict, evaluate metrics include accuracy, attack success rate and neural coverage.\n        \"\"\"\n\n        true_labels = np.asarray(true_labels)\n        fuzz_preds = np.asarray(fuzz_preds)\n        temp = np.argmax(true_labels, axis=1) == np.argmax(fuzz_preds, axis=1)\n        metrics_report = {}\n\n        if temp.any():\n            acc = np.sum(temp) / np.size(temp)\n            attack_success_rate = 1 - np.sum(temp) / np.size(temp)\n        else:\n            acc = 0\n            attack_success_rate = None\n        metrics_report['Accuracy'] = acc\n        metrics_report['Attack_success_rate'] = attack_success_rate\n        metrics_report['Coverage_metrics'] = coverage.get_metrics(fuzz_samples)\n        return metrics_report\n"
  },
  {
    "path": "mindarmour/fuzz_testing/model_coverage_metrics.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nModel-Test Coverage Metrics.\n\"\"\"\nfrom abc import abstractmethod\nfrom collections import defaultdict\nimport math\nimport time\nimport numpy as np\n\nfrom mindspore import Tensor\nfrom mindspore import Model\nfrom mindspore.train.summary.summary_record import _get_summary_tensor_data\n\nfrom mindarmour.utils._check_param import check_model, check_numpy_param, check_int_positive, \\\n    check_param_type, check_value_positive\nfrom mindarmour.utils.logger import LogUtil\n\nLOGGER = LogUtil.get_instance()\nTAG = 'CoverageMetrics'\n\n\nclass CoverageMetrics:\n    \"\"\"\n    The abstract base class for Neuron coverage classes calculating coverage metrics.\n\n    As we all known, each neuron output of a network will have a output range after training (we call it original\n    range), and test dataset is used to estimate the accuracy of the trained network. However, neurons' output\n    distribution would be different with different test datasets. Therefore, similar to function fuzz, model fuzz means\n    testing those neurons' outputs and estimating the proportion of original range that has emerged with test\n    datasets.\n\n    Reference: `DeepGauge: Multi-Granularity Testing Criteria for Deep Learning Systems\n    <https://arxiv.org/abs/1803.07519>`_\n\n    Args:\n        model (Model): The pre-trained model which waiting for testing.\n        incremental (bool): Metrics will be calculate in incremental way or not. Default: ``False``.\n        batch_size (int):  The number of samples in a fuzz test batch. Default: ``32``.\n    \"\"\"\n\n    def __init__(self, model, incremental=False, batch_size=32):\n        self._model = check_model('model', model, Model)\n        self.incremental = check_param_type('incremental', incremental, bool)\n        self.batch_size = check_int_positive('batch_size', batch_size)\n        self._activate_table = defaultdict(list)\n\n    @abstractmethod\n    def get_metrics(self, dataset):\n        \"\"\"\n        Calculate coverage metrics of given dataset.\n\n        Args:\n            dataset (numpy.ndarray): Dataset used to calculate coverage metrics.\n\n        Raises:\n            NotImplementedError: It is an abstract method.\n        \"\"\"\n        msg = 'The function get_metrics() is an abstract method in class `CoverageMetrics`, and should be' \\\n              ' implemented in child class.'\n        LOGGER.error(TAG, msg)\n        raise NotImplementedError(msg)\n\n    def _init_neuron_activate_table(self, data):\n        \"\"\"\n        Initialise the activate table of each neuron in the model with format:\n        {'layer1': [n1, n2, n3, ..., nn], 'layer2': [n1, n2, n3, ..., nn], ...}\n\n        Args:\n            data (numpy.ndarray): Data used for initialising the activate table.\n\n        Return:\n            dict, return a activate_table.\n        \"\"\"\n        self._model.predict(Tensor(data))\n        time.sleep(0.01)\n        layer_out = _get_summary_tensor_data()\n        if not layer_out:\n            msg = 'User must use TensorSummary() operation to specify the middle layer of the model participating in ' \\\n                  'the coverage calculation.'\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        activate_table = defaultdict()\n        for layer, value in layer_out.items():\n            activate_table[layer] = np.zeros(value.shape[1], np.bool)\n        return activate_table\n\n    def _get_bounds(self, train_dataset):\n        \"\"\"\n        Update the lower and upper boundaries of neurons' outputs.\n\n        Args:\n            train_dataset (numpy.ndarray): Training dataset used for determine the neurons' output boundaries.\n\n        Return:\n            - numpy.ndarray, upper bounds of neuron' outputs.\n\n            - numpy.ndarray, lower bounds of neuron' outputs.\n        \"\"\"\n        upper_bounds = defaultdict(list)\n        lower_bounds = defaultdict(list)\n        batches = math.ceil(train_dataset.shape[0] / self.batch_size)\n        for i in range(batches):\n            inputs = train_dataset[i * self.batch_size: (i + 1) * self.batch_size]\n            self._model.predict(Tensor(inputs))\n            time.sleep(0.01)\n            layer_out = _get_summary_tensor_data()\n            for layer, tensor in layer_out.items():\n                value = tensor.asnumpy()\n                value = np.mean(value, axis=tuple([i for i in range(2, len(value.shape))]))\n                min_value = np.min(value, axis=0)\n                max_value = np.max(value, axis=0)\n                if np.any(upper_bounds[layer]):\n                    max_flag = upper_bounds[layer] > max_value\n                    min_flag = lower_bounds[layer] < min_value\n                    upper_bounds[layer] = upper_bounds[layer] * max_flag + max_value * (1 - max_flag)\n                    lower_bounds[layer] = lower_bounds[layer] * min_flag + min_value * (1 - min_flag)\n                else:\n                    upper_bounds[layer] = max_value\n                    lower_bounds[layer] = min_value\n        return upper_bounds, lower_bounds\n\n    def _activate_rate(self):\n        \"\"\"\n        Calculate the activate rate of neurons.\n        \"\"\"\n        total_neurons = 0\n        activated_neurons = 0\n        for _, value in self._activate_table.items():\n            activated_neurons += np.sum(value)\n            total_neurons += len(value)\n        activate_rate = activated_neurons / total_neurons\n\n        return activate_rate\n\n\nclass NeuronCoverage(CoverageMetrics):\n    \"\"\"\n    Calculate the neurons activated coverage. Neuron is activated when its output is greater than the threshold.\n    Neuron coverage equals the proportion of activated neurons to total neurons in the network.\n\n    Args:\n        model (Model): The pre-trained model which waiting for testing.\n        threshold (float): Threshold used to determined neurons is activated or not. Default: ``0.1``.\n        incremental (bool): Metrics will be calculate in incremental way or not. Default: ``False``.\n        batch_size (int):  The number of samples in a fuzz test batch. Default: ``32``.\n\n    \"\"\"\n    def __init__(self, model, threshold=0.1, incremental=False, batch_size=32):\n        super(NeuronCoverage, self).__init__(model, incremental, batch_size)\n        threshold = check_param_type('threshold', threshold, float)\n        self.threshold = check_value_positive('threshold', threshold)\n\n\n    def get_metrics(self, dataset):\n        \"\"\"\n        Get the metric of neuron coverage: the proportion of activated neurons to total neurons in the network.\n\n        Args:\n            dataset (numpy.ndarray): Dataset used to calculate coverage metrics.\n\n        Returns:\n            float, the metric of 'neuron coverage'.\n\n        Examples:\n            >>> from mindspore.common.initializer import TruncatedNormal\n            >>> from mindspore.ops import operations as P\n            >>> from mindspore.train import Model\n            >>> from mindspore.ops import TensorSummary\n            >>> from mindarmour.fuzz_testing import NeuronCoverage\n            >>> class Net(nn.Cell):\n            ...     def __init__(self):\n            ...         super(Net, self).__init__()\n            ...         self.conv1 = nn.Conv2d(1, 6, 5, padding=0, weight_init=TruncatedNormal(0.02), pad_mode=\"valid\")\n            ...         self.conv2 = nn.Conv2d(6, 16, 5, padding=0, weight_init=TruncatedNormal(0.02), pad_mode=\"valid\")\n            ...         self.fc1 = nn.Dense(16 * 5 * 5, 120, TruncatedNormal(0.02), TruncatedNormal(0.02))\n            ...         self.fc2 = nn.Dense(120, 84, TruncatedNormal(0.02), TruncatedNormal(0.02))\n            ...         self.fc3 = nn.Dense(84, 10, TruncatedNormal(0.02), TruncatedNormal(0.02))\n            ...         self.relu = nn.ReLU()\n            ...         self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)\n            ...         self.reshape = P.Reshape()\n            ...         self.summary = TensorSummary()\n            ...     def construct(self, x):\n            ...         x = self.conv1(x)\n            ...         x = self.relu(x)\n            ...         self.summary('conv1', x)\n            ...         x = self.max_pool2d(x)\n            ...         x = self.conv2(x)\n            ...         x = self.relu(x)\n            ...         self.summary('conv2', x)\n            ...         x = self.max_pool2d(x)\n            ...         x = self.reshape(x, (-1, 16 * 5 * 5))\n            ...         x = self.fc1(x)\n            ...         x = self.relu(x)\n            ...         self.summary('fc1', x)\n            ...         x = self.fc2(x)\n            ...         x = self.relu(x)\n            ...         self.summary('fc2', x)\n            ...         x = self.fc3(x)\n            ...         self.summary('fc3', x)\n            ...         return x\n            >>> net = Net()\n            >>> model = Model(net)\n            >>> batch_size = 8\n            >>> num_classe = 10\n            >>> train_images = np.random.rand(32, 1, 32, 32).astype(np.float32)\n            >>> test_images = np.random.rand(batch_size, 1, 32, 32).astype(np.float32)\n            >>> nc = NeuronCoverage(model, threshold=0.1)\n            >>> nc_metrics = nc.get_metrics(test_images)\n        \"\"\"\n        dataset = check_numpy_param('dataset', dataset)\n        batches = math.ceil(dataset.shape[0] / self.batch_size)\n        if not self.incremental or not self._activate_table:\n            self._activate_table = self._init_neuron_activate_table(dataset[0:1])\n        for i in range(batches):\n            inputs = dataset[i * self.batch_size: (i + 1) * self.batch_size]\n            self._model.predict(Tensor(inputs))\n            time.sleep(0.01)\n            layer_out = _get_summary_tensor_data()\n            for layer, tensor in layer_out.items():\n                value = tensor.asnumpy()\n                value = np.mean(value, axis=tuple([i for i in range(2, len(value.shape))]))\n                activate = np.sum(value > self.threshold, axis=0) > 0\n                self._activate_table[layer] = np.logical_or(self._activate_table[layer], activate)\n        neuron_coverage = self._activate_rate()\n        return neuron_coverage\n\n\nclass TopKNeuronCoverage(CoverageMetrics):\n    \"\"\"\n    Calculate the top k activated neurons coverage. Neuron is activated when its output has the top k largest value in\n    that hidden layers. Top k neurons coverage equals the proportion of activated neurons to total neurons in the\n    network.\n\n    Args:\n        model (Model): The pre-trained model which waiting for testing.\n        top_k (int): Neuron is activated when its output has the top k largest value in that hidden layers.\n            Default: ``3``.\n        incremental (bool): Metrics will be calculate in incremental way or not. Default: ``False``.\n        batch_size (int):  The number of samples in a fuzz test batch. Default: ``32``.\n    \"\"\"\n    def __init__(self, model, top_k=3, incremental=False, batch_size=32):\n        super(TopKNeuronCoverage, self).__init__(model, incremental=incremental, batch_size=batch_size)\n        self.top_k = check_int_positive('top_k', top_k)\n\n    def get_metrics(self, dataset):\n        \"\"\"\n        Get the metric of Top K activated neuron coverage.\n\n        Args:\n            dataset (numpy.ndarray): Dataset used to calculate coverage metrics.\n\n        Returns:\n            float, the metrics of 'top k neuron coverage'.\n\n        Examples:\n            >>> from mindspore.common.initializer import TruncatedNormal\n            >>> from mindspore.ops import operations as P\n            >>> from mindspore.train import Model\n            >>> from mindspore.ops import TensorSummary\n            >>> from mindarmour.fuzz_testing import TopKNeuronCoverage\n            >>> class Net(nn.Cell):\n            ...     def __init__(self):\n            ...         super(Net, self).__init__()\n            ...         self.conv1 = nn.Conv2d(1, 6, 5, padding=0, weight_init=TruncatedNormal(0.02), pad_mode=\"valid\")\n            ...         self.conv2 = nn.Conv2d(6, 16, 5, padding=0, weight_init=TruncatedNormal(0.02), pad_mode=\"valid\")\n            ...         self.fc1 = nn.Dense(16 * 5 * 5, 120, TruncatedNormal(0.02), TruncatedNormal(0.02))\n            ...         self.fc2 = nn.Dense(120, 84, TruncatedNormal(0.02), TruncatedNormal(0.02))\n            ...         self.fc3 = nn.Dense(84, 10, TruncatedNormal(0.02), TruncatedNormal(0.02))\n            ...         self.relu = nn.ReLU()\n            ...         self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)\n            ...         self.reshape = P.Reshape()\n            ...         self.summary = TensorSummary()\n            ...     def construct(self, x):\n            ...         x = self.conv1(x)\n            ...         x = self.relu(x)\n            ...         self.summary('conv1', x)\n            ...         x = self.max_pool2d(x)\n            ...         x = self.conv2(x)\n            ...         x = self.relu(x)\n            ...         self.summary('conv2', x)\n            ...         x = self.max_pool2d(x)\n            ...         x = self.reshape(x, (-1, 16 * 5 * 5))\n            ...         x = self.fc1(x)\n            ...         x = self.relu(x)\n            ...         self.summary('fc1', x)\n            ...         x = self.fc2(x)\n            ...         x = self.relu(x)\n            ...         self.summary('fc2', x)\n            ...         x = self.fc3(x)\n            ...         self.summary('fc3', x)\n            ...         return x\n            >>> net = Net()\n            >>> model = Model(net)\n            >>> batch_size = 8\n            >>> num_classe = 10\n            >>> train_images = np.random.rand(32, 1, 32, 32).astype(np.float32)\n            >>> test_images = np.random.rand(batch_size, 1, 32, 32).astype(np.float32)\n            >>> tknc = TopKNeuronCoverage(model, top_k=3)\n            >>> metrics = tknc.get_metrics(test_images)\n        \"\"\"\n        dataset = check_numpy_param('dataset', dataset)\n        batches = math.ceil(dataset.shape[0] / self.batch_size)\n        if not self.incremental or not self._activate_table:\n            self._activate_table = self._init_neuron_activate_table(dataset[0:1])\n        for i in range(batches):\n            inputs = dataset[i * self.batch_size: (i + 1) * self.batch_size]\n            self._model.predict(Tensor(inputs))\n            time.sleep(0.01)\n            layer_out = _get_summary_tensor_data()\n            for layer, tensor in layer_out.items():\n                value = tensor.asnumpy()\n                if len(value.shape) > 2:\n                    value = np.mean(value, axis=tuple([i for i in range(2, len(value.shape))]))\n                top_k_value = np.sort(value)[:, -self.top_k].reshape(value.shape[0], 1)\n                top_k_value = np.sum((value - top_k_value) >= 0, axis=0) > 0\n                self._activate_table[layer] = np.logical_or(self._activate_table[layer], top_k_value)\n        top_k_neuron_coverage = self._activate_rate()\n        return top_k_neuron_coverage\n\n\nclass SuperNeuronActivateCoverage(CoverageMetrics):\n    \"\"\"\n    Get the metric of 'super neuron activation coverage'. :math:`SNAC = |UpperCornerNeuron|/|N|`. SNAC refers to the\n    proportion of neurons whose neurons output value in the test set exceeds the upper bounds of the corresponding\n    neurons output value in the training set.\n\n    Args:\n        model (Model): The pre-trained model which waiting for testing.\n        train_dataset (numpy.ndarray): Training dataset used for determine the neurons' output boundaries.\n        incremental (bool): Metrics will be calculate in incremental way or not. Default: ``False``.\n        batch_size (int):  The number of samples in a fuzz test batch. Default: ``32``.\n    \"\"\"\n    def __init__(self, model, train_dataset, incremental=False, batch_size=32):\n        super(SuperNeuronActivateCoverage, self).__init__(model, incremental=incremental, batch_size=batch_size)\n        train_dataset = check_numpy_param('train_dataset', train_dataset)\n        self.upper_bounds, self.lower_bounds = self._get_bounds(train_dataset=train_dataset)\n\n    def get_metrics(self, dataset):\n        \"\"\"\n        Get the metric of 'super neuron activation coverage'.\n\n        Args:\n            dataset (numpy.ndarray): Dataset used to calculate coverage metrics.\n\n        Returns:\n            float, the metric of 'super neuron activation coverage'.\n\n        Examples:\n            >>> from mindspore.common.initializer import TruncatedNormal\n            >>> from mindspore.ops import operations as P\n            >>> from mindspore.train import Model\n            >>> from mindspore.ops import TensorSummary\n            >>> from mindarmour.fuzz_testing import SuperNeuronActivateCoverage\n            >>> class Net(nn.Cell):\n            ...     def __init__(self):\n            ...         super(Net, self).__init__()\n            ...         self.conv1 = nn.Conv2d(1, 6, 5, padding=0, weight_init=TruncatedNormal(0.02), pad_mode=\"valid\")\n            ...         self.conv2 = nn.Conv2d(6, 16, 5, padding=0, weight_init=TruncatedNormal(0.02), pad_mode=\"valid\")\n            ...         self.fc1 = nn.Dense(16 * 5 * 5, 120, TruncatedNormal(0.02), TruncatedNormal(0.02))\n            ...         self.fc2 = nn.Dense(120, 84, TruncatedNormal(0.02), TruncatedNormal(0.02))\n            ...         self.fc3 = nn.Dense(84, 10, TruncatedNormal(0.02), TruncatedNormal(0.02))\n            ...         self.relu = nn.ReLU()\n            ...         self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)\n            ...         self.reshape = P.Reshape()\n            ...         self.summary = TensorSummary()\n            ...     def construct(self, x):\n            ...         x = self.conv1(x)\n            ...         x = self.relu(x)\n            ...         self.summary('conv1', x)\n            ...         x = self.max_pool2d(x)\n            ...         x = self.conv2(x)\n            ...         x = self.relu(x)\n            ...         self.summary('conv2', x)\n            ...         x = self.max_pool2d(x)\n            ...         x = self.reshape(x, (-1, 16 * 5 * 5))\n            ...         x = self.fc1(x)\n            ...         x = self.relu(x)\n            ...         self.summary('fc1', x)\n            ...         x = self.fc2(x)\n            ...         x = self.relu(x)\n            ...         self.summary('fc2', x)\n            ...         x = self.fc3(x)\n            ...         self.summary('fc3', x)\n            ...         return x\n            >>> net = Net()\n            >>> model = Model(net)\n            >>> batch_size = 8\n            >>> num_classe = 10\n            >>> train_images = np.random.rand(32, 1, 32, 32).astype(np.float32)\n            >>> test_images = np.random.rand(batch_size, 1, 32, 32).astype(np.float32)\n            >>> snac = SuperNeuronActivateCoverage(model, train_images)\n            >>> metrics = snac.get_metrics(test_images)\n        \"\"\"\n        dataset = check_numpy_param('dataset', dataset)\n        if not self.incremental or not self._activate_table:\n            self._activate_table = self._init_neuron_activate_table(dataset[0:1])\n        batches = math.ceil(dataset.shape[0] / self.batch_size)\n\n        for i in range(batches):\n            inputs = dataset[i * self.batch_size: (i + 1) * self.batch_size]\n            self._model.predict(Tensor(inputs))\n            time.sleep(0.01)\n            layer_out = _get_summary_tensor_data()\n            for layer, tensor in layer_out.items():\n                value = tensor.asnumpy()\n                if len(value.shape) > 2:\n                    value = np.mean(value, axis=tuple([i for i in range(2, len(value.shape))]))\n                activate = np.sum(value > self.upper_bounds[layer], axis=0) > 0\n                self._activate_table[layer] = np.logical_or(self._activate_table[layer], activate)\n        snac = self._activate_rate()\n        return snac\n\n\nclass NeuronBoundsCoverage(SuperNeuronActivateCoverage):\n    \"\"\"\n    Get the metric of 'neuron boundary coverage' :math:`NBC = (|UpperCornerNeuron| + |LowerCornerNeuron|)/(2*|N|)`,\n    where :math:`|N|` is the number of neurons, NBC refers to the proportion of neurons whose neurons output value in\n    the test dataset exceeds the upper and lower bounds of the corresponding neurons output value in the training\n    dataset.\n\n    Args:\n        model (Model): The pre-trained model which waiting for testing.\n        train_dataset (numpy.ndarray): Training dataset used for determine the neurons' output boundaries.\n        incremental (bool): Metrics will be calculate in incremental way or not. Default: ``False``.\n        batch_size (int):  The number of samples in a fuzz test batch. Default: ``32``.\n    \"\"\"\n\n    def __init__(self, model, train_dataset, incremental=False, batch_size=32):\n        super(NeuronBoundsCoverage, self).__init__(model, train_dataset, incremental=incremental, batch_size=batch_size)\n\n    def get_metrics(self, dataset):\n        \"\"\"\n        Get the metric of 'neuron boundary coverage'.\n\n        Args:\n            dataset (numpy.ndarray): Dataset used to calculate coverage metrics.\n\n        Returns:\n            float, the metric of 'neuron boundary coverage'.\n\n        Examples:\n            >>> from mindspore.common.initializer import TruncatedNormal\n            >>> from mindspore.ops import operations as P\n            >>> from mindspore.train import Model\n            >>> from mindspore.ops import TensorSummary\n            >>> from mindarmour.fuzz_testing import NeuronBoundsCoverage\n            >>> class Net(nn.Cell):\n            ...     def __init__(self):\n            ...         super(Net, self).__init__()\n            ...         self.conv1 = nn.Conv2d(1, 6, 5, padding=0, weight_init=TruncatedNormal(0.02), pad_mode=\"valid\")\n            ...         self.conv2 = nn.Conv2d(6, 16, 5, padding=0, weight_init=TruncatedNormal(0.02), pad_mode=\"valid\")\n            ...         self.fc1 = nn.Dense(16 * 5 * 5, 120, TruncatedNormal(0.02), TruncatedNormal(0.02))\n            ...         self.fc2 = nn.Dense(120, 84, TruncatedNormal(0.02), TruncatedNormal(0.02))\n            ...         self.fc3 = nn.Dense(84, 10, TruncatedNormal(0.02), TruncatedNormal(0.02))\n            ...         self.relu = nn.ReLU()\n            ...         self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)\n            ...         self.reshape = P.Reshape()\n            ...         self.summary = TensorSummary()\n            ...     def construct(self, x):\n            ...         x = self.conv1(x)\n            ...         x = self.relu(x)\n            ...         self.summary('conv1', x)\n            ...         x = self.max_pool2d(x)\n            ...         x = self.conv2(x)\n            ...         x = self.relu(x)\n            ...         self.summary('conv2', x)\n            ...         x = self.max_pool2d(x)\n            ...         x = self.reshape(x, (-1, 16 * 5 * 5))\n            ...         x = self.fc1(x)\n            ...         x = self.relu(x)\n            ...         self.summary('fc1', x)\n            ...         x = self.fc2(x)\n            ...         x = self.relu(x)\n            ...         self.summary('fc2', x)\n            ...         x = self.fc3(x)\n            ...         self.summary('fc3', x)\n            ...         return x\n            >>> net = Net()\n            >>> model = Model(net)\n            >>> batch_size = 8\n            >>> num_classe = 10\n            >>> train_images = np.random.rand(32, 1, 32, 32).astype(np.float32)\n            >>> test_images = np.random.rand(batch_size, 1, 32, 32).astype(np.float32)\n            >>> nbc = NeuronBoundsCoverage(model, train_images)\n            >>> metrics = nbc.get_metrics(test_images)\n        \"\"\"\n        dataset = check_numpy_param('dataset', dataset)\n        if not self.incremental or not self._activate_table:\n            self._activate_table = self._init_neuron_activate_table(dataset[0:1])\n\n        batches = math.ceil(dataset.shape[0] / self.batch_size)\n        for i in range(batches):\n            inputs = dataset[i * self.batch_size: (i + 1) * self.batch_size]\n            self._model.predict(Tensor(inputs))\n            time.sleep(0.01)\n            layer_out = _get_summary_tensor_data()\n            for layer, tensor in layer_out.items():\n                value = tensor.asnumpy()\n                if len(value.shape) > 2:\n                    value = np.mean(value, axis=tuple([i for i in range(2, len(value.shape))]))\n                outer = np.logical_or(value > self.upper_bounds[layer], value < self.lower_bounds[layer])\n                activate = np.sum(outer, axis=0) > 0\n                self._activate_table[layer] = np.logical_or(self._activate_table[layer], activate)\n        nbc = self._activate_rate()\n        return nbc\n\n\nclass KMultisectionNeuronCoverage(SuperNeuronActivateCoverage):\n    \"\"\"\n    Get the metric of 'k-multisection neuron coverage'. KMNC measures how thoroughly the given set of test inputs\n    covers the range of neurons output values derived from training dataset.\n\n    Args:\n        model (Model): The pre-trained model which waiting for testing.\n        train_dataset (numpy.ndarray): Training dataset used for determine the neurons' output boundaries.\n        segmented_num (int): The number of segmented sections of neurons' output intervals. Default: ``100``.\n        incremental (bool): Metrics will be calculate in incremental way or not. Default: ``False``.\n        batch_size (int):  The number of samples in a fuzz test batch. Default: ``32``.\n    \"\"\"\n\n    def __init__(self, model, train_dataset, segmented_num=100, incremental=False, batch_size=32):\n        super(KMultisectionNeuronCoverage, self).__init__(model, train_dataset, incremental=incremental,\n                                                          batch_size=batch_size)\n        self.segmented_num = check_int_positive('segmented_num', segmented_num)\n        self.intervals = defaultdict(list)\n        for keys in self.upper_bounds.keys():\n            self.intervals[keys] = (self.upper_bounds[keys] - self.lower_bounds[keys]) / self.segmented_num\n\n    def _init_k_multisection_table(self, data):\n        \"\"\" Initial the activate table.\"\"\"\n        self._model.predict(Tensor(data))\n        time.sleep(0.01)\n        layer_out = _get_summary_tensor_data()\n        activate_section_table = defaultdict()\n        for layer, value in layer_out.items():\n            activate_section_table[layer] = np.zeros((value.shape[1], self.segmented_num), np.bool)\n        return activate_section_table\n\n    def get_metrics(self, dataset):\n        \"\"\"\n        Get the metric of 'k-multisection neuron coverage'.\n\n        Args:\n            dataset (numpy.ndarray): Dataset used to calculate coverage metrics.\n\n        Returns:\n            float, the metric of 'k-multisection neuron coverage'.\n\n        Examples:\n            >>> from mindspore.common.initializer import TruncatedNormal\n            >>> from mindspore.ops import operations as P\n            >>> from mindspore.train import Model\n            >>> from mindspore.ops import TensorSummary\n            >>> from mindarmour.fuzz_testing import KMultisectionNeuronCoverage\n            >>> class Net(nn.Cell):\n            ...     def __init__(self):\n            ...         super(Net, self).__init__()\n            ...         self.conv1 = nn.Conv2d(1, 6, 5, padding=0, weight_init=TruncatedNormal(0.02), pad_mode=\"valid\")\n            ...         self.conv2 = nn.Conv2d(6, 16, 5, padding=0, weight_init=TruncatedNormal(0.02), pad_mode=\"valid\")\n            ...         self.fc1 = nn.Dense(16 * 5 * 5, 120, TruncatedNormal(0.02), TruncatedNormal(0.02))\n            ...         self.fc2 = nn.Dense(120, 84, TruncatedNormal(0.02), TruncatedNormal(0.02))\n            ...         self.fc3 = nn.Dense(84, 10, TruncatedNormal(0.02), TruncatedNormal(0.02))\n            ...         self.relu = nn.ReLU()\n            ...         self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)\n            ...         self.reshape = P.Reshape()\n            ...         self.summary = TensorSummary()\n            ...     def construct(self, x):\n            ...         x = self.conv1(x)\n            ...         x = self.relu(x)\n            ...         self.summary('conv1', x)\n            ...         x = self.max_pool2d(x)\n            ...         x = self.conv2(x)\n            ...         x = self.relu(x)\n            ...         self.summary('conv2', x)\n            ...         x = self.max_pool2d(x)\n            ...         x = self.reshape(x, (-1, 16 * 5 * 5))\n            ...         x = self.fc1(x)\n            ...         x = self.relu(x)\n            ...         self.summary('fc1', x)\n            ...         x = self.fc2(x)\n            ...         x = self.relu(x)\n            ...         self.summary('fc2', x)\n            ...         x = self.fc3(x)\n            ...         self.summary('fc3', x)\n            ...         return x\n            >>> net = Net()\n            >>> model = Model(net)\n            >>> batch_size = 8\n            >>> num_classe = 10\n            >>> train_images = np.random.rand(32, 1, 32, 32).astype(np.float32)\n            >>> test_images = np.random.rand(batch_size, 1, 32, 32).astype(np.float32)\n            >>> kmnc = KMultisectionNeuronCoverage(model, train_images, segmented_num=100)\n            >>> metrics = kmnc.get_metrics(test_images)\n        \"\"\"\n\n        dataset = check_numpy_param('dataset', dataset)\n        if not self.incremental or not self._activate_table:\n            self._activate_table = self._init_k_multisection_table(dataset[0:1])\n\n        batches = math.ceil(dataset.shape[0] / self.batch_size)\n        for i in range(batches):\n            inputs = dataset[i * self.batch_size: (i + 1) * self.batch_size]\n            self._model.predict(Tensor(inputs))\n            time.sleep(0.01)\n            layer_out = _get_summary_tensor_data()\n            for layer, tensor in layer_out.items():\n                value = tensor.asnumpy()\n                value = np.mean(value, axis=tuple([i for i in range(2, len(value.shape))]))\n                hits = np.floor((value - self.lower_bounds[layer]) / self.intervals[layer]).astype(int)\n                hits = np.transpose(hits, [1, 0])\n                for n in range(len(hits)):\n                    for sec in hits[n]:\n                        if sec >= self.segmented_num or sec < 0:\n                            continue\n                        self._activate_table[layer][n][sec] = True\n\n        kmnc = self._activate_rate() / self.segmented_num\n        return kmnc\n"
  },
  {
    "path": "mindarmour/fuzz_testing/scc_readme.md",
    "content": "# 使用Sensitivity Convergence Coverage测试深度学习模型\n\n## 概述\n\n传统软件的决策逻辑由代码逻辑决定，传统软件通过代码行覆盖率来判断当前测试是否充分，理想情况下覆盖率越高，代码测试越充分。然而，对于深度神经网络而言，程序的决策逻辑由训练数据、网络模型结构和参数通过某种黑盒机制决定，代码行覆盖率已不足以评估测试的充分性。需要根据深度网络的特点选择更为适合的测试评价准则，指导神经网络进行更为充分的测试，发现更多的边缘错误用例，从而确保模型的通用性、鲁棒性。\n\nSensitivity Convergence Coverage (SCC) 是一种基于神经元输出差异的深度学习模型测试方法。与神经元覆盖率（Neuron Coverage）关注神经元输出激活情况不同，SCC关注的是神经元输出之间的差异。具体来说，SCC关注的是神经元i在输入x和输入x'（x的噪声版本）下的输出差异，即$Neuron_{i}(x) - Neuron_{i}(x')$。\n\n根据偏微分理论，任意神经元n的扰动分布$Neuron_{i}(x) - Neuron_{i}(x')$，其中x是输入，x'是噪声扰动输入，呈正态分布。这意味着大部分的噪声对神经元造成的扰动较小，只有少部分噪声对神经元造成较大的扰动。因此，我们可以通过抽样方法使扰动分布收敛，从而以较高概率发现所有的扰动和深度学习模型错误。\n\n这里以LeNet模型，MNIST数据集为例，说明如何使用SCC测试深度学习模型。\n\n## 实现阶段\n\n### 需要导入的库文件\n\n下列是我们需要的公共模块、MindSpore相关模块和fuzz_testing特性模块，以及配置日志标签和日志等级。\n\n```python\nimport math\nimport numpy as np\n\nfrom mindspore import Tensor\nfrom mindarmour.fuzz_testing import CoverageMetrics\nfrom mindspore.train.summary.summary_record import _get_summary_tensor_data\n\nfrom mindarmour.utils._check_param import check_model, check_numpy_param, check_int_positive, \\\n    check_param_type, check_value_positive\nfrom mindarmour.utils.logger import LogUtil\n\nLOGGER = LogUtil.get_instance()\nTAG = 'SensitivityConvergenceCoverage'\n```\n\n### 参数配置\n\n配置必要的信息，包括环境信息、执行的模式。\n\n```python\nms.set_context(mode=ms.GRAPH_MODE, device_target=\"Ascend\")\n```\n\n详细的接口配置信息，请参见`set_context`接口说明。\n\n### 计算Sensitivity Convergence Coverage 并使用SensitivityMaximizingFuzzer增大模型的SCC。\n\n1. 建立LeNet模型，加载MNIST数据集，操作同[模型安全]()\n\n```python\n# Lenet model\nmodel = Model(net)\n# get training data\nmnist_path = \"../common/dataset/MNIST/\"\nbatch_size = 32\nds = generate_mnist_dataset(os.path.join(mnist_path, \"train\"), batch_size, sparse=False)\ntrain_images = []\nfor data in ds.create_tuple_iterator():\n    images = data[0].asnumpy().astype(np.float32)\n    train_images.append(images)\ntrain_images = np.concatenate(train_images, axis=0)\n\n# get test data\nbatch_size = 32\nds = generate_mnist_dataset(os.path.join(mnist_path, \"test\"), batch_size, sparse=False)\ntest_images = []\ntest_labels = []\nfor data in ds.create_tuple_iterator():\n    images = data[0].asnumpy().astype(np.float32)\n    labels = data[1].asnumpy()\n    test_images.append(images)\n    test_labels.append(labels)\ntest_images = np.concatenate(test_images, axis=0)\ntest_labels = np.concatenate(test_labels, axis=0)\n\n```\n\n2. Coverage参数设置。\n\nSensitivity Convergence Coverage包含Model, threshold, batch_size, selected_neurons_num和n_iter。\n\nModel：用户指定需要测试的模型。\n\nthreshold：神经元覆盖阈值，当覆盖率大于threshold时神经元覆盖率测试完成。\n\nbatch_size：测试过程中同时利用batch_size数量大小的输入计算Coverage。\n\nselected_neurons_num：测试神经元数量，数量越大，测试越准确，但时间开销也越大。\n\nn_iter：最大测试次数，避免模型长时间测试。\n\n以下是Coverage参数配置例子：\n\n```python\nSCC = SensitivityConvergenceCoverage(model, t = 0.5, batch_size = 32)\n```\n\n3. Fuzzer参数设置。\n\n设置数据变异方法及参数。支持同时配置多种方法，目前支持的数据变异方法包含两类：\n\n自然扰动样本生成方法：\n\n仿射变换类方法：Translate、Scale、Shear、Rotate、Perspective、Curve；\n\n模糊类方法：GaussianBlur、MotionBlur、GradientBlur；\n\n亮度调整类方法：Contrast、GradientLuminance;\n\n加噪类方法：UniformNoise、GaussianNoise、SaltAndPepperNoise、NaturalNoise。\n\n基于对抗攻击的白盒、黑盒对抗样本生成方法：FGSM（FastGradientSignMethod）、PGD（ProjectedGradientDescent）、MDIIM（MomentumDiverseInputIterativeMethod）。\n\n数据变异方法中一定要包含基于图像像素值变化的方法。\n\n前两种类型的图像变化方法，支持用户自定义配置参数，也支持算法随机选择参数。用户自定义参数配置范围请参考:https://gitee.com/mindspore/mindarmour/tree/master/mindarmour/natural_robustness/transform/image 中对应的类方法。算法随机选择参数，则params设置为'auto_param': [True]，参数将在推荐范围内随机生成。\n\n基于对抗攻击方法的参数配置请参考对应的攻击方法类。\n\n下面是变异方法及其参数配置的一个例子：\n\n```python\nmutate_config = [{'method': 'GaussianBlur',\n                  'params': {'ksize': [1, 2, 3, 5], 'auto_param': [True, False]}},\n                 {'method': 'MotionBlur',\n                  'params': {'degree': [1, 2, 5], 'angle': [45, 10, 100, 140, 210, 270, 300],\n                  'auto_param': [True]}},\n                 {'method': 'UniformNoise',\n                  'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n                 {'method': 'GaussianNoise',\n                  'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n                 {'method': 'Contrast',\n                  'params': {'alpha': [0.5, 1, 1.5], 'beta': [-10, 0, 10], 'auto_param': [False, True]}},\n                 {'method': 'Rotate',\n                  'params': {'angle': [20, 90], 'auto_param': [False, True]}},\n                 {'method': 'FGSM',\n                  'params': {'eps': [0.3, 0.2, 0.4], 'alpha': [0.1], 'bounds': [(0, 1)]}}]\n```\n\n初始化种子队列，种子队列中的每个种子，包含2个值：原始图片、图片标签。这里取100个样本作为初始种子队列。\n\n```python\n# make initial seeds\ninitial_seeds = []\nfor img, label in zip(test_images, test_labels):\n    initial_seeds.append([img, label])\ninitial_seeds = initial_seeds[:100]\n```\n\n3. 实例化Sensitivity Convergence Coverage类，并计算初始覆盖率。\n\n```python\nSCC = SensitivityConvergenceCoverage(model, t = 0.5, batch_size = 32)\nscc_value = SensitivityConvergenceCoverage.metrics(initial_seeds)\nprint('SCC of initial seeds is: ', scc_value)\n```\n\n结果：\n\n```python\nSCC of initial seeds is: 0.2969543147208122\n```\n\n4. 实例化SensitivityMaximizingFuzzer类, Fuzz生成test case提升覆盖率指标。\n\n```python\nmodel_fuzz_test = SensitivityMaximizingFuzzer(model)\nfuzz_samples, gt_labels, preds, strategies, metrics = model_fuzz_test.fuzzing(mutate_config, initial_seeds, SCC, max_iters=10)\n```\n\n5. 实验结果。\n\nfuzzing的返回结果中包含了5个数据：fuzz生成的样本fuzz_samples、生成样本的真实标签true_labels、被测模型对于生成样本的预测值fuzz_preds、 生成样本使用的变异方法fuzz_strategies、fuzz testing生成的test cases的metrics。用户可使用这些返回结果进一步的分析模型的鲁棒性。这里只展开metrics，查看fuzz testing后的各个评估指标。\n\n```python\nif metrics:\n    for key in metrics:\n        LOGGER.info(TAG, key + ': %s', metrics[key])\n```\n\nFuzz测试后结果如下:\n\n```python\nAccuracy:  0.80\nAttack_success_rate:  0.20\ncoverage_metrics:  0.35971389017074296\n```"
  },
  {
    "path": "mindarmour/fuzz_testing/sensitivity_convergence_coverage.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nSource code of SensitivityConvergenceCoverage class.\n\"\"\"\nimport time\nimport numpy as np\n\nfrom mindspore import Tensor\nfrom mindspore.train.summary.summary_record import _get_summary_tensor_data\nfrom mindarmour.fuzz_testing import CoverageMetrics\nfrom mindarmour.utils._check_param import check_numpy_param\nfrom mindarmour.utils.logger import LogUtil\n\n\n\nLOGGER = LogUtil.get_instance()\nTAG = 'CoverageMetrics'\n\n\nclass SensitivityConvergenceCoverage(CoverageMetrics):\n    '''\n    Get the metric of sensitivity convergence coverage: the proportion of neurons that have converged to the threshold.\n    Sensitivity convergence coverage is a metric that can be used to evaluate the convergence of the neuron sensitivity\n    to the threshold.\n\n    Args:\n        model (Model): Model to be evaluated.\n        threshold (float): Threshold of sensitivity convergence coverage. Default: ``0.5``.\n        incremental (bool): Whether to use incremental mode. Default: ``False``.\n        batch_size (int): Batch size. Default: ``32``.\n        selected_neurons_num (int): Number of neurons selected for sensitivity convergence coverage. Default: ``100``.\n        n_iter (int): Number of iterations. Default: ``1000``.\n\n    '''\n\n    def __init__(self, model, threshold=0.5, incremental=False, batch_size=32, selected_neurons_num=100, n_iter=1000):\n        super().__init__(model, incremental, batch_size)\n        self.threshold = threshold\n        self.total_converged = 0\n        self.total_size = 0\n        self.n_iter = n_iter\n        self.selected_neurons_num = selected_neurons_num\n        self.sensitive_neuron_idx = {}\n        self.initial_samples = []\n\n    def get_metrics(self, dataset):\n        '''\n        Obtain indicators of neuron convergence coverage.\n        SCC measures the proportion of neuron output changes converging to Normal distribution.\n\n        Args:\n            dataset (numpy.ndarray): Dataset for evaluation.\n\n        Returns:\n            SCC_value(float), the proportion of neurons that have converged to the threshold.\n\n        Examples:\n            >>> from mindspore.common.initializer import TruncatedNormal\n            >>> from mindspore.ops import operations as P\n            >>> from mindspore.train import Model\n            >>> from mindspore.ops import TensorSummary\n            >>> from mindarmour.fuzz_testing import SensitivityConvergenceCoverage\n            >>> class Net(nn.Cell):\n            ...     def __init__(self):\n            ...         super(Net, self).__init__()\n            ...         self.conv1 = nn.Conv2d(1, 6, 5, padding=0, weight_init=TruncatedNormal(0.02), pad_mode=\"valid\")\n            ...         self.conv2 = nn.Conv2d(6, 16, 5, padding=0, weight_init=TruncatedNormal(0.02), pad_mode=\"valid\")\n            ...         self.fc1 = nn.Dense(16 * 5 * 5, 120, TruncatedNormal(0.02), TruncatedNormal(0.02))\n            ...         self.fc2 = nn.Dense(120, 84, TruncatedNormal(0.02), TruncatedNormal(0.02))\n            ...         self.fc3 = nn.Dense(84, 10, TruncatedNormal(0.02), TruncatedNormal(0.02))\n            ...         self.relu = nn.ReLU()\n            ...         self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)\n            ...         self.reshape = P.Reshape()\n            ...         self.summary = TensorSummary()\n            ...     def construct(self, x):\n            ...         x = self.conv1(x)\n            ...         x = self.relu(x)\n            ...         self.summary('conv1', x)\n            ...         x = self.max_pool2d(x)\n            ...         x = self.conv2(x)\n            ...         x = self.relu(x)\n            ...         self.summary('conv2', x)\n            ...         x = self.max_pool2d(x)\n            ...         x = self.reshape(x, (-1, 16 * 5 * 5))\n            ...         x = self.fc1(x)\n            ...         x = self.relu(x)\n            ...         self.summary('fc1', x)\n            ...         x = self.fc2(x)\n            ...         x = self.relu(x)\n            ...         self.summary('fc2', x)\n            ...         x = self.fc3(x)\n            ...         self.summary('fc3', x)\n            ...         return x\n            >>> batch_size = 32\n            >>> num_classe = 10\n            >>> train_images = np.random.rand(32, 1, 32, 32).astype(np.float32)\n            >>> test_images = np.random.rand(batch_size, 1, 32, 32).astype(np.float32)\n            >>> test_labels = np.random.randint(num_classe, size=batch_size).astype(np.int32)\n            >>> test_labels = (np.eye(num_classe)[test_labels]).astype(np.float32)\n            >>> initial_seeds = []\n            >>> # make initial seeds\n            >>> for img, label in zip(test_images, test_labels):\n            ...     initial_seeds.append([img, label])\n            >>> initial_seeds = initial_seeds[:batch_size]\n            >>> SCC = SensitivityConvergenceCoverage(model,batch_size = batch_size)\n            >>> metrics = SCC.get_metrics(test_images)\n        '''\n        inputs = check_numpy_param('dataset', dataset)\n        if not self.sensitive_neuron_idx:\n            self._get_sensitive_neruon_idx(dataset)\n        self._model.predict(Tensor(inputs))\n        time.sleep(0.01)\n        layer_out = _get_summary_tensor_data()\n\n        for layer, tensor in layer_out.items():\n            tensor = tensor.asnumpy().reshape(tensor.shape[0], -1)\n            clean, benign = tensor[:tensor.shape[0] // 2], tensor[tensor.shape[0] // 2:]\n            sensitivity = abs(clean-benign)\n            try:\n                sensitivity = sensitivity[:, self.sensitive_neuron_idx[layer]]\n            except KeyError:\n                raise RuntimeError('The layer {} is not in the sensitive_neuron_idx'.format(layer))\n            converged, size = self._scc(sensitivity, sensitivity.shape[1], self.threshold)\n            self.total_converged += converged\n            self.total_size += size\n        scc_value = self.total_converged/self.total_size\n        return scc_value\n\n    def _get_sensitive_neruon_idx(self, dataset):\n        '''\n        Args:\n            dataset (numpy.ndarray): Dataset for evaluation.\n        '''\n\n        inputs = check_numpy_param('dataset', dataset)\n        self._model.predict(Tensor(inputs))\n        time.sleep(0.01)\n        layer_out = _get_summary_tensor_data()\n        for layer, tensor in layer_out.items():\n            tensor = tensor.asnumpy().reshape(tensor.shape[0], -1)\n            clean, benign = tensor[:tensor.shape[0] // 2], tensor[tensor.shape[0] // 2:]\n            sensitivity = abs(clean-benign)\n            self.sensitive_neuron_idx[layer] = np.argsort(np.sum(sensitivity,\n                                                                 axis=0))[-min(self.selected_neurons_num,\\\n                                                                len(np.sum(sensitivity, axis=0))):]\n\n    def _scc(self, sensitivity_list, size, threshold=0):\n        '''\n        Args:\n            sensitivity_list(numpy.ndarray): The sensitivity of each neuron.\n            size(int): The number of neurons.\n            threshold(float): The threshold of sensitivity convergence coverage.\n\n        Returns:\n            - int, The number of neurons that have converged to the threshold.\n            - int, The number of neurons.\n\n        '''\n\n        converged = 0\n        for i in range(sensitivity_list.shape[1]):\n            _, acceptance_rate = self._build_mh_chain(sensitivity_list[:, i],\n                                                      np.mean(sensitivity_list[:, i]), self.n_iter, self._log_prob)\n\n            if acceptance_rate > threshold:\n                converged += 1\n\n        return converged, size\n\n    def _proposal(self, x, stepsize):\n        '''\n        Args:\n            x(numpy.ndarray): The input of the proposal function.\n            stepsize(float): The stepsize of the proposal function.\n\n        Returns:\n            numpy.ndarray, The output of the proposal function.\n        '''\n        return np.random.uniform(low=x - 0.5 * stepsize,\n                                 high=x + 0.5 * stepsize,\n                                 size=x.shape)\n\n    def _p_acc_mh(self, x_new, x_old, log_prob):\n        '''\n        Args:\n            x_new(numpy.ndarray): The new state.\n            x_old(numpy.ndarray): The old state.\n            log_prob(function): The log probability function.\n\n        Returns:\n            float, The acceptance probability.\n        '''\n        return min(1, np.exp(log_prob(x_new) - log_prob(x_old)))\n\n    def _log_prob(self, x):\n        '''\n        Args:\n            x(numpy.ndarray): The input of the log probability function.\n\n        Returns:\n            float, The output of the log probability function.\n        '''\n        return -0.5 * np.sum(x ** 2)\n\n    def _sample_mh(self, x_old, log_prob, stepsize):\n        '''\n        here we determine whether we accept the new state or not:\n        we draw a random number uniformly from [0,1] and compare\n        it with the acceptance probability.\n\n        Args:\n            x_old(numpy.ndarray): The old state.\n            log_prob(function): The log probability function.\n            stepsize(float): The stepsize of the proposal function.\n\n        Returns:\n            - bool, Whether to accept the new state.\n            - numpy.ndarray, if bool=True: return new state, else: return old state.\n        '''\n        x_new = self._proposal(x_old, stepsize)\n        accept = np.random.random() < self._p_acc_mh(x_new, x_old, log_prob)\n        if accept:\n            return accept, x_new\n        return accept, x_old\n\n    def _build_mh_chain(self, init, stepsize, n_total, log_prob):\n        '''\n        Args:\n            init(numpy.ndarray): The initial state.\n            stepsize(float): The stepsize of the proposal function.\n            n_total(int): The total number of samples.\n            log_prob(function): The log probability function.\n\n        Returns:\n            - list, The chain of samples.\n            - float, The acceptance rate of the chain.\n        '''\n        n_accepted = 0\n        chain = [init]\n\n        for _ in range(n_total):\n            accept, state = self._sample_mh(chain[-1], log_prob, stepsize)\n            chain.append(state)\n            n_accepted += accept\n        acceptance_rate = n_accepted / float(n_total)\n\n        return chain, acceptance_rate\n"
  },
  {
    "path": "mindarmour/model_protection/__init__.py",
    "content": "from .obfuscation import ModelObfuscator\n\n__all__ = ['ModelObfuscator']"
  },
  {
    "path": "mindarmour/model_protection/obfuscation.py",
    "content": "# Copyright 2025 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport os\nimport re\nimport json\nfrom pathlib import Path\nfrom string import Template\nimport numpy as np\nimport ml_dtypes\nfrom safetensors import safe_open\nfrom safetensors.numpy import save_file\n\nfrom mindarmour.utils.logger import LogUtil\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Model Protection'\n\n_supported_config_type = [\n    'obf_metadata_config',\n    'weight_obf_config',\n    'network_obf_config'\n]\n\n_supported_metadata_type = [\n    'random',\n    'rearrange'\n]\n\n_supported_model_format = [\n    'safetensors'\n]\n\ndef _check_dir_path(name, dir_path):\n    \"\"\"check directory path\"\"\"\n    if not isinstance(dir_path, str):\n        raise TypeError(\"{} must be string, but got {}.\".format(name, type(dir_path)))\n    if not os.path.exists(dir_path):\n        raise ValueError(\"{} is not exist, please check the input {}.\".format(dir_path, name))\n    if not Path(dir_path).is_dir():\n        raise TypeError(\"{} must be a directory path, but got {}.\".format(name, dir_path))\n\ndef _check_ops_info(ops_info):\n    \"\"\"check ops info config\"\"\"\n    for op in ops_info:\n        op_name = op.get('name')\n        if not isinstance(op_name, str):\n            raise TypeError(\"op_name type should be str, but got {}.\".format(type(op_name)))\n        input_x_name = op.get('input_x')\n        if not isinstance(input_x_name, str):\n            raise TypeError(\"input_x_name type should be str, but got {}.\".format(type(input_x_name)))\n        input_y_name = op.get('input_y')\n        if not isinstance(input_y_name, str):\n            raise TypeError(\"input_y_name type should be str, but got {}.\".format(type(input_y_name)))\n        if not isinstance(op.get('transpose_a', False), bool):\n            raise TypeError(\"transpose_a type should be bool, but got {}.\".format(type(op.get('transpose_a'))))\n        if not isinstance(op.get('transpose_b', False), bool):\n            raise TypeError(\"transpose_b type should be bool, but got {}.\".format(type(op.get('transpose_b'))))\n\ndef _check_new_input_info(insert_new_input):\n    \"\"\"check new input config\"\"\"\n    if not isinstance(insert_new_input, list):\n        raise TypeError(\"obf_config[][]['insert_new_input'] type should be list, but got {}.\"\n                        .format(type(insert_new_input)))\n    for new_input in insert_new_input:\n        input_name = new_input.get('name')\n        if not isinstance(input_name, str):\n            raise TypeError(\"obf_config[][]['insert_new_input'][]['name'] type should be str, but got {}.\"\n                            .format(type(input_name)))\n\n\ndef _check_obf_metadata_config(config):\n    \"\"\"check obf metadata config\"\"\"\n    name = config.get('name')\n    if not name or not isinstance(name, str):\n        raise TypeError(\"obf_config[][]['name'] type should be str, but got {}.\".format(type(name)))\n    shape = config.get('shape')\n    if not shape or not isinstance(shape, list):\n        raise TypeError(\"obf_config[][]['shape'] type should be list, but got {}.\".format(type(shape)))\n    for item in shape:\n        if not isinstance(item, int):\n            raise TypeError(\"shape[] type should be int, but got {}.\".format(type(item)))\n    save_metadata = config.get('save_metadata', True)\n    if not isinstance(save_metadata, bool):\n        raise TypeError(\"obf_config[][]['save_metadata'] type should be bool, but got {}.\"\n                        .format(type(save_metadata)))\n    metadata_type = config.get('type')\n    if metadata_type is not None:\n        if not isinstance(metadata_type, str) or metadata_type not in _supported_metadata_type:\n            raise TypeError(\"obf_config[][]['type'] should be str and must in {}, but got {}.\"\n                            .format(str(_supported_metadata_type), type(metadata_type)))\n\n\ndef _check_weight_obf_config(config):\n    \"\"\"check weight obfuscation config\"\"\"\n    target = config.get('target')\n    if not target or not isinstance(target, str):\n        raise TypeError(\"obf_config[][]['target'] type should be str, but got {}.\".format(type(target)))\n    weight_obf_ops = config.get('weight_obf_ops', [])\n    if not isinstance(weight_obf_ops, list):\n        raise TypeError(\"obf_config[][]['weight_obf_ops'] type should be list, but got {}.\"\n                        .format(type(weight_obf_ops)))\n    _check_ops_info(weight_obf_ops)\n\n\ndef _check_network_obf_config(config):\n    \"\"\"check network obfuscation config\"\"\"\n    target = config.get('target')\n    if not target or not isinstance(target, str):\n        raise TypeError(\"obf_config[][]['target'] type should be str, but got {}.\".format(type(target)))\n    module = config.get('module')\n    if not module or not isinstance(module, str):\n        raise TypeError(\"obf_config[][]['module'] type should be str, but got {}.\".format(type(module)))\n    insert_new_input = config.get('insert_new_input', [])\n    _check_new_input_info(insert_new_input)\n    insert_ops = config.get('insert_ops', [])\n    if not isinstance(insert_ops, list):\n        raise TypeError(\"obf_config[][]['insert_ops'] type should be list, but got {}.\".format(type(insert_ops)))\n    _check_ops_info(insert_ops)\n\n\ndef _check_valid_obf_config(obf_config, config_type):\n    \"\"\"check obfuscation config\"\"\"\n    if not isinstance(config_type, str) or config_type not in _supported_config_type:\n        raise TypeError(\"config_type must be str, and in {}, but got {}.\"\n                        .format(str(_supported_config_type), config_type))\n    for config_type_item in obf_config.keys():\n        if not isinstance(config_type_item, str) or config_type_item not in _supported_config_type:\n            raise TypeError(\"config_type must be str, and in {}, but got {}.\"\n                            .format(str(_supported_config_type), config_type_item))\n    config_list = obf_config.get(config_type)\n    if not isinstance(config_list, list):\n        raise TypeError(\"obf_config[] type of should be list, but got {}.\".format(type(config_list)))\n\n    for config in config_list:\n        if not isinstance(config, dict):\n            raise TypeError(\"obf_config[][] type should be dict, but got {}.\".format(type(config)))\n        if config_type == 'obf_metadata_config':\n            _check_obf_metadata_config(config)\n        elif config_type == 'weight_obf_config':\n            _check_weight_obf_config(config)\n        elif config_type == 'network_obf_config':\n            _check_network_obf_config(config)\n        layers = config.get('layers')\n        if layers is not None:\n            if not isinstance(layers, list):\n                raise TypeError(\"obf_config[][]['layers'] type should be list, but got {}.\".format(type(layers)))\n            for layer in layers:\n                if not isinstance(layer, int):\n                    raise TypeError(\"obf_config[][]['layers'][] type should be int, but got {}.\".format(type(layer)))\n    return True\n\ndef _check_valid_obf_config(obf_config):\n    \"\"\"check obfuscation config\"\"\"\n    if isinstance(obf_config, dict):\n        for config_type in obf_config.keys():\n            if not isinstance(config_type, str) or config_type not in _supported_config_type:\n                raise TypeError(\"config_type must be str, and in {}, but got {}.\"\n                                .format(str(_supported_config_type), config_type))\n            config_list = obf_config.get(config_type)\n            if not isinstance(config_list, list):\n                raise TypeError(\"obf_config[] type of should be list, but got {}.\".format(type(config_list)))\n            for config in config_list:\n                if not isinstance(config, dict):\n                    raise TypeError(\"obf_config[][] type should be dict, but got {}.\".format(type(config)))\n                if config_type == 'obf_metadata_config':\n                    _check_obf_metadata_config(config)\n                elif config_type == 'weight_obf_config':\n                    _check_weight_obf_config(config)\n                elif config_type == 'network_obf_config':\n                    _check_network_obf_config(config)\n                layers = config.get('layers')\n                if layers is not None:\n                    if not isinstance(layers, list):\n                        raise TypeError(\"obf_config[][]['layers'] type should be list, but got {}.\".format(type(layers)))\n                    for layer in layers:\n                        if not isinstance(layer, int):\n                            raise TypeError(\"obf_config[][]['layers'][] type should be int, but got {}.\".format(type(layer)))\n    return obf_config\n\nclass ModelObfuscator:\n    \"\"\"\n        Obfuscate the plaintext model weight files according to the obfuscation config.\n\n        Args:\n            obf_config (dict, optional): The configuration of model obfuscation polices. Default: ``None``.\n            obfuscate_scale (Union[float, int], optional): Obfuscate scale of weights.\n                The generated random obf_ratios will be in\n                range of (1 / obfuscate_scale, obfuscate_scale). Default: ``100``.\n\n\n        Examples:\n            >>> from mindarmour import ModelObfuscator\n            >>> obf_config_str = \"\"\n            >>> src_path = \"\"\n            >>> saved_path = \"\"\n            >>> obf_config = yaml.safe_load(obf_config_str)\n            >>> obf = ModelObfuscator(obf_config, obfuscate_scale=100)\n            >>> obf.obfuscate_weight_files(src_path, saved_path=saved_path)\n        \"\"\"\n\n    def __init__(self, obf_config, obfuscate_scale):\n        self.obf_config = _check_valid_obf_config(obf_config)\n        self.obf_metadata_config = self.obf_config.get('obf_metadata_config', [])\n        self.obfuscate_scale = obfuscate_scale\n        self.obf_metadata, self.saved_metadata = self._gen_obf_metadata(self.obf_metadata_config)\n        self.saved_metadata_mapping = {}\n\n    def _gen_obfuscate_tensor(self, tensor_shape, tensor_type='rearrange'):\n        obf_tensor = None\n        if tensor_type == 'rearrange':\n            if len(tensor_shape) == 1:\n                obf_tensor = np.random.permutation(tensor_shape[0])\n            if len(tensor_shape) == 2:\n                tensor = np.identity(tensor_shape[0])\n                p = np.random.permutation(tensor_shape[1])\n                obf_tensor = tensor[:, p]\n        if tensor_type == 'random':\n            obf_tensor = np.random.randint(1, self.obfuscate_scale, size=tensor_shape).astype(np.float16)\n        return obf_tensor\n    \n    def _get_real_name(self, src_name, tag, substitute):\n        dst_names = []\n        for sub in substitute:\n            strTemplate = Template(src_name)\n            dst_name = strTemplate.safe_substitute({tag: str(sub)})\n            dst_names.append(dst_name)\n        return dst_names\n\n    def _gen_obf_metadata(self, obf_metadata_config):\n        obf_metadata = {}\n        saved_metadata = {}\n        for config in obf_metadata_config:\n            name = config.get('name')\n            if name is None:\n                return\n            save_metadata = config.get('save_metadata', False)\n            metadata_op_name = config.get('metadata_op')\n            layers = config.get('layers')  \n            \n            if not layers:\n                if not obf_metadata.get(name):\n                    obf_tensor = self._gen_obfuscate_tensor(config.get('shape'), config.get('type'))\n                    obf_metadata[name] = obf_tensor\n                    if save_metadata:\n                        saved_metadata[name] = obf_tensor\n            else:\n                for layer in layers:\n                    strTemplate = Template(name)\n                    obf_name = strTemplate.safe_substitute({\"layer\": str(layer)})\n                    obf_tensor = self._gen_obfuscate_tensor(config.get('shape'), config.get('type'))\n                    obf_metadata[obf_name] = obf_tensor\n                    if save_metadata:\n                        saved_metadata[name] = obf_tensor\n        return obf_metadata, saved_metadata\n    \n    def set_metadata(self, new_metadata):\n        if not isinstance(new_metadata, dict):\n            raise ValueError(\"xxx\")\n        self.obf_metadata = {k: new_metadata[k] if k in new_metadata else self.obf_metadata[k] for k in self.obf_metadata}\n        self.saved_metadata = {k: new_metadata[k] if k in new_metadata else self.saved_metadata[k] for k in self.saved_metadata}\n    \n    def set_save_metadata_mapping(self, new_mapping):\n        self.saved_metadata_mapping.update(new_mapping)\n\n    def _obfuscate_params(self, params, obf_metadata, obf_config, not_obfuscated_params):\n        \"\"\"Obfuscate params\"\"\"\n        def _get_op_input_name(obf_op, name_key='input_x', layer=0):\n            op_name = obf_op.get('name')\n            input_name = obf_op.get(name_key)\n            if input_name is None:\n                LOGGER.error(TAG, \"can not find input: {} for op: {}.\".format(name_key, op_name))\n                return None\n            strTemplate = Template(input_name)\n            input_name = strTemplate.safe_substitute({\"layer\": str(layer)})\n            return input_name\n\n        def _get_op_input(input_name, obf_param):\n            op_input = obf_metadata.get(input_name, None) if input_name.startswith('obf_metadata') else obf_param\n            return op_input\n\n        def _obfuscate_param(param, obf_metadata, obf_ops, layer=0):\n            param_dtype = param.dtype\n            obf_param = param\n            for obf_op in obf_ops:\n                op_name = obf_op.get('name')\n                if not isinstance(op_name, str):\n                    raise TypeError('{} should be str type, but got {}'.format(op_name, type(op_name)))\n                if op_name == 'mul':\n                    input_x = obf_param\n                    input_y_name = _get_op_input_name(obf_op, 'input_y', layer)\n                    input_y = obf_metadata.get(input_y_name)\n                    if input_x is None or input_y is None:\n                        LOGGER.error(TAG, \"input_x or input_y is None\")\n                        return None\n                    input_y = input_y.astype(param_dtype)\n                    obf_param = np.multiply(input_x, input_y)\n                elif op_name == 'permuate':\n                    index_name = _get_op_input_name(obf_op, 'input_y', layer)\n                    p = obf_metadata.get(index_name, None)\n                    axis = obf_op.get('axis')\n                    if p is None or obf_param is None or axis is None:\n                        LOGGER.error(TAG, \"input_x or param or axis is None\")\n                        return None\n                    if axis == 0:\n                        obf_param = obf_param[p]\n                    elif axis == 1:\n                        obf_param = obf_param[:, p]\n                    else:\n                        raise ValueError('axis should be 0 or 1, but got {}'.format(axis))\n                elif op_name == 'matmul':\n                    input_x_name = _get_op_input_name(obf_op, 'input_x', layer)\n                    input_y_name = _get_op_input_name(obf_op, 'input_y', layer)\n                    input_x = _get_op_input(input_x_name, obf_param)\n                    input_y = _get_op_input(input_y_name, obf_param)\n                    if input_x is None or input_y is None:\n                        LOGGER.error(TAG, \"the input_x or input_y of op: {} is None.\".format(op_name))\n                        return None\n                    input_x = np.transpose(input_x, (1, 0)) if obf_op.get('transpose_a', False) else input_x\n                    input_y = np.transpose(input_y, (1, 0)) if obf_op.get('transpose_b', False) else input_y\n                    obf_param = np.matmul(input_x.astype(param_dtype), input_y.astype(param_dtype))\n                else:\n                    LOGGER.error(TAG, \"unsupported op, op must be matmul or permuate or mul, but got {}.\"\n                                .format(op_name))\n                    return None\n            return obf_param\n\n\n        weight_obf_config = obf_config.get('weight_obf_config', [])\n        for item, param in params.items():\n            item_split = item.split('.')\n            param_path = '/'.join(item_split[:len(item_split)])\n            for obf_target in weight_obf_config:\n                if not isinstance(obf_target, dict):\n                    raise TypeError('{} should be dict type, but got {}'.format(obf_target, type(obf_target)))\n                target = obf_target.get('target', None)\n                layers = obf_target.get('layers', [])\n                obf_ops = obf_target.get('weight_obf_ops', None)\n                if not target or not obf_ops:\n                    raise KeyError(\"target or obf_ops is None.\")\n                if not layers:\n                    if target == param_path:\n                        obf_param = _obfuscate_param(param, obf_metadata, obf_ops)\n                        if obf_param is None:\n                            LOGGER.error(TAG, \"obfuscate weight {} failed.\".format(item))\n                            return False\n                        params[item] = obf_param\n                        LOGGER.info(TAG, \"obfuscate weight: {} success.\".format(item))\n                        not_obfuscated_params.remove(item)\n                for layer in layers:\n                    strTemplate = Template(target)\n                    target_path = strTemplate.safe_substitute({\"layer\": str(layer)})\n                    if target_path == param_path:\n                        obf_param = _obfuscate_param(param, obf_metadata, obf_ops, layer)\n                        if obf_param is None:\n                            LOGGER.error(TAG, \"obfuscate weight {} failed.\".format(item))\n                            return False\n                        params[item] = obf_param\n                        LOGGER.info(TAG, \"obfuscate weight: {} success.\".format(item))\n                        not_obfuscated_params.remove(item)\n        return True\n\n    def _obfuscate_safetensor_files(self, src_path, saved_path='./'):\n        params_not_obfuscated = []\n        file_names = os.listdir(src_path)\n        index = {\n            \"metadata\": {\"total_size\": 0},\n            \"weight_map\": {}\n        }\n        add_obf_metadata = True\n        for file_name in file_names:\n            if not file_name.endswith('.safetensors'):\n                continue\n            not_obfuscated = self._obfuscate_single_file(os.path.join(os.path.realpath(src_path), file_name),\n                                                         self.obf_metadata, self.obf_config, saved_path, index, add_obf_metadata)\n            params_not_obfuscated += not_obfuscated\n            add_obf_metadata = False\n        \n        LOGGER.info(TAG, \"params not obfuscated: {}.\".format(params_not_obfuscated))\n        param_json_path = os.path.join(saved_path, \"model.safetensors.index.json\")\n        with open(param_json_path, \"w\") as f:\n            json.dump(index, f, indent=2)\n\n    def obfuscate_weight_files(self, src_path, saved_path='./', file_format=\"safetensors\"):\n        \"\"\"\n        Obfuscate the plaintext model weight files according to the obfuscation config.\n\n        Args:\n            src_path (str): The directory path of original model weight files.\n            saved_path (str, optional): The directory path for saving obfuscated model files. Default: ``'./'``.\n\n        Returns:\n            dict[str], obf_metadata, which is the necessary data that needs to be load when running obfuscated network.\n\n        Raises:\n            TypeError: If `src_path` is not string or `saved_path` is not string.\n            ValueError: If `src_path` is not exist or `saved_path` is not exist.\n        \"\"\"\n\n        _check_dir_path('src_path', src_path)\n        _check_dir_path('saved_path', saved_path)\n        \n        if file_format == \"safetensors\":\n            self._obfuscate_safetensor_files(src_path, saved_path)\n        else:\n            LOGGER.error(TAG, \"got unsupported model format: {}. Currently supported model formats include {}.\"\n                        .format(file_format, _supported_model_format))\n\n    def _obfuscate_single_file(self, src_file, obf_metadata, obf_config, saved_path, index, add_obf_metadata):\n        \"\"\"Obfuscate single model file\"\"\"\n        \n        params = {}\n        not_obfuscated_params = []\n        file_name = src_file.split('/')[-1]\n        try:\n            with safe_open(src_file, framework=\"np\") as f:\n                for param_name in f.keys():\n                    #print(hf_param_name)\n                    params[param_name] = f.get_tensor(param_name)\n                    index[\"weight_map\"][param_name] = file_name\n                    not_obfuscated_params.append(param_name)\n        except (ValueError, TypeError, OSError):\n            LOGGER.error(TAG, \"Load params failed for file {}.\".format(src_file))\n            return not_obfuscated_params\n        \n        LOGGER.info(TAG, \"Load params success for file {}.\".format(src_file))\n        self._obfuscate_params(params, obf_metadata, obf_config, not_obfuscated_params)\n\n        # save the obfuscated hg to saved_path\n        if add_obf_metadata:\n            for param_name in self.saved_metadata_mapping:\n                metadata_name = self.saved_metadata_mapping[param_name]\n                params[param_name] = self.saved_metadata[metadata_name]\n                index[\"weight_map\"][param_name] = file_name\n        obf_file_name = os.path.join(saved_path, file_name)\n        LOGGER.info(TAG, \"Saving obfuscated params to file: {}.\".format(obf_file_name))\n        save_file(params, obf_file_name)\n        index[\"metadata\"][\"total_size\"] += os.path.getsize(obf_file_name)\n        return not_obfuscated_params\n"
  },
  {
    "path": "mindarmour/natural_robustness/__init__.py",
    "content": "# Copyright 2022 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nNatural Robustness.\n\nThis module is a tool box to enhance model security and against natural perturb examples.\n\"\"\"\n"
  },
  {
    "path": "mindarmour/natural_robustness/transform/__init__.py",
    "content": "# Copyright 2022 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nImage Transform Method for Natural Robustness.\n\"\"\"\n"
  },
  {
    "path": "mindarmour/natural_robustness/transform/image/__init__.py",
    "content": "# Copyright 2022 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis package include methods to generate natural perturbation samples.\n\"\"\"\n\nfrom .transformation import Translate, Scale, Shear, Rotate, Perspective, Curve\nfrom .blur import GaussianBlur, MotionBlur, GradientBlur\nfrom .luminance import Contrast, GradientLuminance\nfrom .corruption import UniformNoise, GaussianNoise, SaltAndPepperNoise, NaturalNoise\n\n__all__ = ['Translate',\n           'Scale',\n           'Shear',\n           'Rotate',\n           'Perspective',\n           'Curve',\n           'GaussianBlur',\n           'MotionBlur',\n           'GradientBlur',\n           'Contrast',\n           'GradientLuminance',\n           'UniformNoise',\n           'GaussianNoise',\n           'SaltAndPepperNoise',\n           'NaturalNoise']\n"
  },
  {
    "path": "mindarmour/natural_robustness/transform/image/blur.py",
    "content": "# Copyright 2022 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nImage Blur\n\"\"\"\n\nimport numpy as np\nimport cv2\n\nfrom mindarmour.natural_robustness.transform.image.natural_perturb import _NaturalPerturb\nfrom mindarmour.utils._check_param import check_param_multi_types, check_int_positive, check_param_type\nfrom mindarmour.utils.logger import LogUtil\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Image Blur'\n\n\nclass GaussianBlur(_NaturalPerturb):\n    \"\"\"\n    Blurs the image using Gaussian blur filter.\n\n    Args:\n        ksize (int): Size of gaussian kernel, this value must be non-negnative. Default: ``2``.\n        auto_param (bool): Auto selected parameters. Selected parameters will preserve semantics of image.\n            Default: ``False``.\n\n    Examples:\n        >>> import cv2\n        >>> img = cv2.imread('1.png')\n        >>> img = np.array(img)\n        >>> ksize = 5\n        >>> trans = GaussianBlur(ksize)\n        >>> dst = trans(img)\n    \"\"\"\n\n    def __init__(self, ksize=2, auto_param=False):\n        super(GaussianBlur, self).__init__()\n        ksize = check_int_positive('ksize', ksize)\n        if auto_param:\n            ksize = 2 * np.random.randint(0, 5) + 1\n        else:\n            ksize = 2 * ksize + 1\n        self.ksize = (ksize, ksize)\n\n    def __call__(self, image):\n        \"\"\"\n        Transform the image.\n\n        Args:\n            image (numpy.ndarray): Original image to be transformed.\n\n        Returns:\n            numpy.ndarray, transformed image.\n        \"\"\"\n        ori_dtype = image.dtype\n        _, chw, normalized, gray3dim, image = self._check(image)\n        new_img = cv2.GaussianBlur(image, self.ksize, 0)\n        new_img = self._original_format(new_img, chw, normalized, gray3dim)\n        return new_img.astype(ori_dtype)\n\n\nclass MotionBlur(_NaturalPerturb):\n    \"\"\"\n    Motion blur for a given image.\n\n    Args:\n        degree (int): Degree of blur. This value must be positive. Suggested value range in [1, 15].\n            Default: ``5``.\n        angle (union[float, int]): Direction of motion blur. Angle=0 means up and down motion blur. Angle is\n            counterclockwise. Default: ``45``.\n        auto_param (bool): Auto selected parameters. Selected parameters will preserve semantics of image.\n            Default: ``False``.\n\n    Examples:\n        >>> import cv2\n        >>> img = cv2.imread('1.png')\n        >>> img = np.array(img)\n        >>> angle = 0\n        >>> degree = 5\n        >>> trans = MotionBlur(degree=degree, angle=angle)\n        >>> new_img = trans(img)\n    \"\"\"\n\n    def __init__(self, degree=5, angle=45, auto_param=False):\n        super(MotionBlur, self).__init__()\n        self.degree = check_int_positive('degree', degree)\n        self.degree = check_param_multi_types('degree', degree, [float, int])\n        auto_param = check_param_type('auto_param', auto_param, bool)\n        if auto_param:\n            self.degree = np.random.randint(1, 5)\n            self.angle = np.random.uniform(0, 360)\n        else:\n            self.angle = angle - 45\n\n    def __call__(self, image):\n        \"\"\"\n        Motion blur for a given image.\n\n        Args:\n            image (numpy.ndarray): Original image.\n\n        Returns:\n            numpy.ndarray, image after motion blur.\n        \"\"\"\n        ori_dtype = image.dtype\n        _, chw, normalized, gray3dim, image = self._check(image)\n        matrix = cv2.getRotationMatrix2D((self.degree / 2, self.degree / 2), self.angle, 1)\n        motion_blur_kernel = np.diag(np.ones(self.degree))\n        motion_blur_kernel = cv2.warpAffine(motion_blur_kernel, matrix, (self.degree, self.degree))\n        motion_blur_kernel = motion_blur_kernel / self.degree\n        blurred = cv2.filter2D(image, -1, motion_blur_kernel)\n        # convert to uint8\n        cv2.normalize(blurred, blurred, 0, 255, cv2.NORM_MINMAX)\n        blurred = self._original_format(blurred, chw, normalized, gray3dim)\n\n        return blurred.astype(ori_dtype)\n\n\nclass GradientBlur(_NaturalPerturb):\n    \"\"\"\n    Gradient blur.\n\n    Args:\n        point (union[tuple, list]): 2D coordinate of the Blur center point.\n        kernel_num (int): Number of blur kernels. Suggested value range in [1, 8]. Default: ``3``.\n        center (bool): Blurred or clear at the center of a specified point.\n        auto_param (bool): Auto selected parameters. Selected parameters will preserve semantics of image.\n            Default: ``False``.\n\n    Examples:\n        >>> import cv2\n        >>> img = cv2.imread('xx.png')\n        >>> img = np.array(img)\n        >>> number = 5\n        >>> h, w = img.shape[:2]\n        >>> point = (int(h / 5), int(w / 5))\n        >>> center = True\n        >>> trans = GradientBlur(point, number,  center)\n        >>> new_img = trans(img)\n    \"\"\"\n\n    def __init__(self, point, kernel_num=3, center=True, auto_param=False):\n        super(GradientBlur).__init__()\n        point = check_param_multi_types('point', point, [list, tuple])\n        self.auto_param = check_param_type('auto_param', auto_param, bool)\n        self.point = tuple(point)\n        self.kernel_num = check_int_positive('kernel_num', kernel_num)\n        self.center = check_param_type('center', center, bool)\n\n    def _auto_param(self, h, w):\n        self.point = (int(np.random.uniform(0, h)), int(np.random.uniform(0, w)))\n        self.kernel_num = np.random.randint(1, 6)\n        self.center = np.random.choice([True, False])\n\n    def __call__(self, image):\n        \"\"\"\n        Args:\n            image (numpy.ndarray): Original image.\n\n        Returns:\n            numpy.ndarray, gradient blurred image.\n        \"\"\"\n        ori_dtype = image.dtype\n        _, chw, normalized, gray3dim, image = self._check(image)\n        w, h = image.shape[:2]\n        if self.auto_param:\n            self._auto_param(h, w)\n        mask = np.zeros(image.shape, dtype=np.uint8)\n        masks = []\n        radius = max(w - self.point[0], self.point[0], h - self.point[1], self.point[1])\n        radius = int(radius / self.kernel_num)\n        for i in range(self.kernel_num):\n            circle = cv2.circle(mask.copy(), self.point, radius * (1 + i), (1, 1, 1), -1)\n            masks.append(circle)\n        blurs = []\n        for i in range(3, 3 + 2 * self.kernel_num, 2):\n            ksize = (i, i)\n            blur = cv2.GaussianBlur(image, ksize, 0)\n            blurs.append(blur)\n\n        dst = image.copy()\n        if self.center:\n            for i in range(self.kernel_num):\n                dst = masks[i] * dst + (1 - masks[i]) * blurs[i]\n        else:\n            for i in range(self.kernel_num - 1, -1, -1):\n                dst = masks[i] * blurs[self.kernel_num - 1 - i] + (1 - masks[i]) * dst\n        dst = self._original_format(dst, chw, normalized, gray3dim)\n        return dst.astype(ori_dtype)\n"
  },
  {
    "path": "mindarmour/natural_robustness/transform/image/corruption.py",
    "content": "# Copyright 2022 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nImage corruption.\n\"\"\"\nimport math\nimport numpy as np\nimport cv2\n\nfrom mindarmour.natural_robustness.transform.image.natural_perturb import _NaturalPerturb\nfrom mindarmour.utils._check_param import check_param_multi_types, check_param_type\nfrom mindarmour.utils.logger import LogUtil\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Image corruption'\n\n\nclass UniformNoise(_NaturalPerturb):\n    \"\"\"\n    Add uniform noise of an image.\n\n    Args:\n        factor (float): Noise density, the proportion of noise points per unit pixel area. Suggested value range in\n            [0.001, 0.15]. Default: ``0.1``.\n        auto_param (bool): Auto selected parameters. Selected parameters will preserve semantics of image.\n            Default: ``False``.\n\n    Examples:\n        >>> import cv2\n        >>> img = cv2.imread('1.png')\n        >>> img = np.array(img)\n        >>> factor = 0.1\n        >>> trans = UniformNoise(factor)\n        >>> dst = trans(img)\n    \"\"\"\n\n    def __init__(self, factor=0.1, auto_param=False):\n        super(UniformNoise, self).__init__()\n        self.factor = check_param_multi_types('factor', factor, [int, float])\n        check_param_type('auto_param', auto_param, bool)\n        if auto_param:\n            self.factor = np.random.uniform(0, 0.15)\n\n    def __call__(self, image):\n        \"\"\"\n        Transform the image.\n\n        Args:\n            image (numpy.ndarray): Original image to be transformed.\n\n        Returns:\n            numpy.ndarray, transformed image.\n        \"\"\"\n        ori_dtype = image.dtype\n        _, chw, normalized, gray3dim, image = self._check(image)\n        low, high = (0, 255)\n        weight = self.factor * (high - low)\n        noise = np.random.uniform(-weight, weight, size=image.shape)\n        trans_image = np.clip(image + noise, low, high)\n        trans_image = self._original_format(trans_image, chw, normalized, gray3dim)\n\n        return trans_image.astype(ori_dtype)\n\n\nclass GaussianNoise(_NaturalPerturb):\n    \"\"\"\n    Add gaussian noise of an image.\n\n    Args:\n        factor (float): Noise density, the proportion of noise points per unit pixel area. Suggested value range in\n            [0.001, 0.15]. Default: ``0.1``.\n        auto_param (bool): Auto selected parameters. Selected parameters will preserve semantics of image.\n            Default: ``False``.\n\n    Examples:\n        >>> import cv2\n        >>> img = cv2.imread('1.png')\n        >>> img = np.array(img)\n        >>> factor = 0.1\n        >>> trans = GaussianNoise(factor)\n        >>> dst = trans(img)\n    \"\"\"\n\n    def __init__(self, factor=0.1, auto_param=False):\n        super(GaussianNoise, self).__init__()\n        self.factor = check_param_multi_types('factor', factor, [int, float])\n        check_param_type('auto_param', auto_param, bool)\n        if auto_param:\n            self.factor = np.random.uniform(0, 0.15)\n\n    def __call__(self, image):\n        \"\"\"\n        Transform the image.\n\n        Args:\n            image (numpy.ndarray): Original image to be transformed.\n\n        Returns:\n            numpy.ndarray, transformed image.\n        \"\"\"\n        ori_dtype = image.dtype\n        low, high = (0, 255)\n        _, chw, normalized, gray3dim, image = self._check(image)\n        std = self.factor / math.sqrt(3) * (high - low)\n        noise = np.random.normal(scale=std, size=image.shape)\n        trans_image = np.clip(image + noise, low, high)\n        trans_image = self._original_format(trans_image, chw, normalized, gray3dim)\n        return trans_image.astype(ori_dtype)\n\n\nclass SaltAndPepperNoise(_NaturalPerturb):\n    \"\"\"\n    Add salt and pepper noise of an image.\n\n    Args:\n        factor (float): Noise density, the proportion of noise points per unit pixel area. Suggested value range in\n            [0.001, 0.15]. Default: ``0``.\n        auto_param (bool): Auto selected parameters. Selected parameters will preserve semantics of image.\n            Default: ``False``.\n\n    Examples:\n        >>> import cv2\n        >>> img = cv2.imread('1.png')\n        >>> img = np.array(img)\n        >>> factor = 0.1\n        >>> trans = SaltAndPepperNoise(factor)\n        >>> dst = trans(img)\n    \"\"\"\n\n    def __init__(self, factor=0, auto_param=False):\n        super(SaltAndPepperNoise, self).__init__()\n        self.factor = check_param_multi_types('factor', factor, [int, float])\n        check_param_type('auto_param', auto_param, bool)\n        if auto_param:\n            self.factor = np.random.uniform(0, 0.15)\n\n    def __call__(self, image):\n        \"\"\"\n        Transform the image.\n\n        Args:\n            image (numpy.ndarray): Original image to be transformed.\n\n        Returns:\n            numpy.ndarray, transformed image.\n        \"\"\"\n        ori_dtype = image.dtype\n        _, chw, normalized, gray3dim, image = self._check(image)\n        low, high = (0, 255)\n        noise = np.random.uniform(low=-1, high=1, size=(image.shape[0], image.shape[1]))\n        trans_image = np.copy(image)\n        threshold = 1 - self.factor\n        trans_image[noise < -threshold] = low\n        trans_image[noise > threshold] = high\n        trans_image = self._original_format(trans_image, chw, normalized, gray3dim)\n        return trans_image.astype(ori_dtype)\n\n\nclass NaturalNoise(_NaturalPerturb):\n    \"\"\"\n    Add natural noise to an image.\n\n    Args:\n        ratio (float): Noise density, the proportion of noise blocks per unit pixel area. Suggested value range in\n            [0.00001, 0.001].\n        k_x_range (union[list, tuple]): Value range of the noise block length. Default: ``(1, 5)``.\n        k_y_range (union[list, tuple]): Value range of the noise block width. Default: ``(3, 25)``.\n        auto_param (bool): Auto selected parameters. Selected parameters will preserve semantics of image.\n            Default: ``False``.\n\n    Examples:\n        >>> import cv2\n        >>> img = cv2.imread('xx.png')\n        >>> img = np.array(img)\n        >>> ratio = 0.0002\n        >>> k_x_range = (1, 5)\n        >>> k_y_range = (3, 25)\n        >>> trans = NaturalNoise(ratio, k_x_range, k_y_range)\n        >>> new_img = trans(img)\n    \"\"\"\n\n    def __init__(self, ratio=0.0002, k_x_range=(1, 5), k_y_range=(3, 25), auto_param=False):\n        super(NaturalNoise).__init__()\n        self.ratio = check_param_type('ratio', ratio, float)\n        k_x_range = check_param_multi_types('k_x_range', k_x_range, [list, tuple])\n        k_y_range = check_param_multi_types('k_y_range', k_y_range, [list, tuple])\n        self.k_x_range = tuple(k_x_range)\n        self.k_y_range = tuple(k_y_range)\n        self.auto_param = check_param_type('auto_param', auto_param, bool)\n\n    def __call__(self, image):\n        \"\"\"\n        Add natural noise to given image.\n\n        Args:\n            image (numpy.ndarray): Original image.\n\n        Returns:\n            numpy.ndarray, image with natural noise.\n        \"\"\"\n        ori_dtype = image.dtype\n        _, chw, normalized, gray3dim, image = self._check(image)\n        randon_range = 100\n        w, h = image.shape[:2]\n        channel = len(np.shape(image))\n\n        if self.auto_param:\n            self.ratio = np.random.uniform(0, 0.001)\n            self.k_x_range = (1, 0.1 * w)\n            self.k_y_range = (1, 0.1 * h)\n\n        for _ in range(5):\n            if channel == 3:\n                noise = np.ones((w, h, 3), dtype=np.uint8) * 255\n                dst = np.ones((w, h, 3), dtype=np.uint8) * 255\n            else:\n                noise = np.ones((w, h), dtype=np.uint8) * 255\n                dst = np.ones((w, h), dtype=np.uint8) * 255\n\n            rate = self.ratio / 5\n            mask = np.random.uniform(size=(w, h)) < rate\n            noise[mask] = np.random.randint(0, randon_range)\n\n            k_x, k_y = np.random.randint(*self.k_x_range), np.random.randint(*self.k_y_range)\n            kernel = np.ones((k_x, k_y), np.uint8)\n            erode = cv2.erode(noise, kernel, iterations=1)\n            dst = erode * (erode < randon_range) + dst * (1 - erode < randon_range)\n            # Add black point\n            for _ in range(np.random.randint(math.ceil(k_x * k_y / 2))):\n                x = np.random.randint(-k_x, k_x)\n                y = np.random.randint(-k_y, k_y)\n                matrix = np.array([[1, 0, y], [0, 1, x]], dtype=np.float)\n                affine = cv2.warpAffine(noise, matrix, (h, w))\n                dst = affine * (affine < randon_range) + dst * (1 - affine < randon_range)\n            # Add white point\n            for _ in range(int(k_x * k_y / 2)):\n                x = np.random.randint(-k_x / 2 - 1, k_x / 2 + 1)\n                y = np.random.randint(-k_y / 2 - 1, k_y / 2 + 1)\n                matrix = np.array([[1, 0, y], [0, 1, x]], dtype=np.float)\n                affine = cv2.warpAffine(noise, matrix, (h, w))\n                white = affine < randon_range\n                dst[white] = 255\n\n        mask = dst < randon_range\n        dst = image * (1 - mask) + dst * mask\n        dst = self._original_format(dst, chw, normalized, gray3dim)\n\n        return dst.astype(ori_dtype)\n"
  },
  {
    "path": "mindarmour/natural_robustness/transform/image/luminance.py",
    "content": "# Copyright 2022 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nImage luminance.\n\"\"\"\nimport math\nimport numpy as np\nimport cv2\n\nfrom mindarmour.natural_robustness.transform.image.natural_perturb import _NaturalPerturb\nfrom mindarmour.utils._check_param import check_param_multi_types, check_param_in_range, check_param_type, \\\n    check_value_non_negative\nfrom mindarmour.utils.logger import LogUtil\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Image Luminance'\n\n\nclass Contrast(_NaturalPerturb):\n    r\"\"\"\n    Contrast of an image.\n\n    Args:\n        alpha (Union[float, int]): Control the contrast of an image. :math:`out\\_image = in\\_image \\times alpha+beta`.\n            Suggested value range in [0.2, 2]. Default: ``1``.\n        beta (Union[float, int]): Delta added to alpha. Default: ``0``.\n        auto_param (bool): Auto selected parameters. Selected parameters will preserve semantics of image.\n            Default: ``False``.\n\n    Examples:\n        >>> import cv2\n        >>> img = cv2.imread('1.png')\n        >>> img = np.array(img)\n        >>> alpha = 0.1\n        >>> beta = 1\n        >>> trans = Contrast(alpha, beta)\n        >>> dst = trans(img)\n    \"\"\"\n\n    def __init__(self, alpha=1, beta=0, auto_param=False):\n        super(Contrast, self).__init__()\n        self.alpha = check_param_multi_types('factor', alpha, [int, float])\n        self.beta = check_param_multi_types('factor', beta, [int, float])\n        auto_param = check_param_type('auto_param', auto_param, bool)\n        if auto_param:\n            self.alpha = np.random.uniform(0.2, 2)\n            self.beta = np.random.uniform(-20, 20)\n\n    def __call__(self, image):\n        \"\"\"\n        Transform the image.\n\n        Args:\n            image (numpy.ndarray): Original image to be transformed.\n\n        Returns:\n            numpy.ndarray, transformed image.\n        \"\"\"\n        ori_dtype = image.dtype\n        _, chw, normalized, gray3dim, image = self._check(image)\n        dst = cv2.convertScaleAbs(image, alpha=self.alpha, beta=self.beta)\n        dst = self._original_format(dst, chw, normalized, gray3dim)\n        return dst.astype(ori_dtype)\n\n\ndef _circle_gradient_mask(img_src, color_start, color_end, scope=0.5, point=None):\n    \"\"\"\n    Generate circle gradient mask.\n\n    Args:\n        img_src (numpy.ndarray): Source image.\n        color_start (union([tuple, list])): Color of circle gradient center.\n        color_end (union([tuple, list])): Color of circle gradient edge.\n        scope (float): Range of the gradient. A larger value indicates a larger gradient range.\n        point (union([tuple, list]): Gradient center point.\n\n    Returns:\n        numpy.ndarray, gradients mask.\n    \"\"\"\n    if not isinstance(img_src, np.ndarray):\n        raise TypeError('`src` must be numpy.ndarray type, but got {0}.'.format(type(img_src)))\n\n    shape = img_src.shape\n    height, width = shape[:2]\n    rgb = False\n    if len(shape) == 3:\n        rgb = True\n    if point is None:\n        point = (height // 2, width // 2)\n    x, y = point\n\n    # upper left\n    bound_upper_left = math.ceil(math.sqrt(x ** 2 + y ** 2))\n    # upper right\n    bound_upper_right = math.ceil(math.sqrt(height ** 2 + (width - y) ** 2))\n    # lower left\n    bound_lower_left = math.ceil(math.sqrt((height - x) ** 2 + y ** 2))\n    # lower right\n    bound_lower_right = math.ceil(math.sqrt((height - x) ** 2 + (width - y) ** 2))\n\n    radius = max(bound_lower_left, bound_lower_right, bound_upper_left, bound_upper_right) * scope\n\n    img_grad = np.ones_like(img_src, dtype=np.uint8) * max(color_end)\n    # opencv use BGR format\n    grad_b = float(color_end[0] - color_start[0]) / radius\n    grad_g = float(color_end[1] - color_start[1]) / radius\n    grad_r = float(color_end[2] - color_start[2]) / radius\n\n    for i in range(height):\n        for j in range(width):\n            distance = math.ceil(math.sqrt((x - i) ** 2 + (y - j) ** 2))\n            if distance >= radius:\n                continue\n            if rgb:\n                img_grad[i, j, 0] = color_start[0] + distance * grad_b\n                img_grad[i, j, 1] = color_start[1] + distance * grad_g\n                img_grad[i, j, 2] = color_start[2] + distance * grad_r\n            else:\n                img_grad[i, j] = color_start[0] + distance * grad_b\n\n    return img_grad.astype(np.uint8)\n\n\ndef _line_gradient_mask(image, start_pos=None, start_color=(0, 0, 0), end_color=(255, 255, 255), mode='horizontal'):\n    \"\"\"\n    Generate liner gradient mask.\n\n    Args:\n        image (numpy.ndarray): Original image.\n        start_pos (union[tuple, list]): 2D coordinate of gradient center.\n        start_color (union([tuple, list])): Color of circle gradient center.\n        end_color (union([tuple, list])): Color of circle gradient edge.\n        mode　(str): Direction of gradient. Optional value is ``'vertical'`` or ``'horizontal'``.\n\n    Returns:\n        numpy.ndarray, gradients mask.\n    \"\"\"\n    shape = image.shape\n    h, w = shape[:2]\n    rgb = False\n    if len(shape) == 3:\n        rgb = True\n    if start_pos is None:\n        start_pos = 0.5\n    else:\n        if mode == 'horizontal':\n            if start_pos[0] > h:\n                start_pos = 1\n            else:\n                start_pos = start_pos[0] / h\n        else:\n            if start_pos[1] > w:\n                start_pos = 1\n            else:\n                start_pos = start_pos[1] / w\n    start_color = np.array(start_color)\n    end_color = np.array(end_color)\n    if mode == 'horizontal':\n        w_l = int(w * start_pos)\n        w_r = w - w_l\n        if w_l > w_r:\n            r_end_color = (end_color - start_color) / start_pos * (1 - start_pos) + start_color\n            left = np.linspace(end_color, start_color, w_l)\n            right = np.linspace(start_color, r_end_color, w_r)\n        else:\n            l_end_color = (end_color - start_color) / (1 - start_pos) * start_pos + start_color\n            left = np.linspace(l_end_color, start_color, w_l)\n            right = np.linspace(start_color, end_color, w_r)\n        line = np.concatenate((left, right), axis=0)\n        mask = np.reshape(np.tile(line, (h, 1)), (h, w, 3))\n    else:\n        # 'vertical'\n        h_t = int(h * start_pos)\n        h_b = h - h_t\n        if h_t > h_b:\n            b_end_color = (end_color - start_color) / start_pos * (1 - start_pos) + start_color\n            top = np.linspace(end_color, start_color, h_t)\n            bottom = np.linspace(start_color, b_end_color, h_b)\n        else:\n            t_end_color = (end_color - start_color) / (1 - start_pos) * start_pos + start_color\n            top = np.linspace(t_end_color, start_color, h_t)\n            bottom = np.linspace(start_color, end_color, h_b)\n        line = np.concatenate((top, bottom), axis=0)\n        mask = np.reshape(np.tile(line, (w, 1)), (w, h, 3))\n        mask = np.transpose(mask, [1, 0, 2])\n    if not rgb:\n        mask = mask[:, :, 0]\n    return mask.astype(np.uint8)\n\n\nclass GradientLuminance(_NaturalPerturb):\n    \"\"\"\n    Gradient adjusts the luminance of picture.\n\n    Args:\n        color_start (union[tuple, list]): Color of gradient center. Default: ``(0, 0, 0)``.\n        color_end (union[tuple, list]):  Color of gradient edge. Default: ``(255, 255, 255)``.\n        start_point (union[tuple, list]): 2D coordinate of gradient center.\n        scope (float): Range of the gradient. A larger value indicates a larger gradient range. Default: ``0.5``.\n        pattern (str): Dark or light, this value must be ``'light'`` or ``'dark'``. Default: ``'light'``.\n        bright_rate (float): Control brightness. A larger value indicates a larger gradient range. If parameter\n            `pattern` is ``'light'``, Suggested value range in [0.1, 0.7], if parameter `pattern` is ``'dark'``,\n            suggested value range in [0.1, 0.9]. Default: ``0.3``.\n        mode (str): Gradient mode, value must be ``'circle'``, ``'horizontal'`` or ``'vertical'``.\n            Default: ``'circle'``.\n        auto_param (bool): Auto selected parameters. Selected parameters will preserve semantics of image.\n            Default: ``False``.\n\n    Examples:\n        >>> import cv2\n        >>> img = cv2.imread('x.png')\n        >>> height, width = img.shape[:2]\n        >>> point = (height // 4, width // 2)\n        >>> start = (255, 255, 255)\n        >>> end = (0, 0, 0)\n        >>> scope = 0.3\n        >>> pattern='light'\n        >>> bright_rate = 0.3\n        >>> trans = GradientLuminance(start, end, point, scope, pattern, bright_rate, mode='circle')\n        >>> img_new = trans(img)\n    \"\"\"\n\n    def __init__(self, color_start=(0, 0, 0), color_end=(255, 255, 255), start_point=(10, 10), scope=0.5,\n                 pattern='light', bright_rate=0.3, mode='circle', auto_param=False):\n        super(GradientLuminance, self).__init__()\n        self.color_start = check_param_multi_types('color_start', color_start, [list, tuple])\n        self.color_end = check_param_multi_types('color_end', color_end, [list, tuple])\n        self.start_point = check_param_multi_types('start_point', start_point, [list, tuple])\n        self.scope = check_value_non_negative('scope', scope)\n        self.bright_rate = check_param_type('bright_rate', bright_rate, float)\n        self.bright_rate = check_param_in_range('bright_rate', bright_rate, 0, 1)\n        self.auto_param = check_param_type('auto_param', auto_param, bool)\n\n        if pattern in ['light', 'dark']:\n            self.pattern = pattern\n        else:\n            msg = \"Value of param pattern must be in ['light', 'dark']\"\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        if mode in ['circle', 'horizontal', 'vertical']:\n            self.mode = mode\n        else:\n            msg = \"Value of param mode must be in ['circle', 'horizontal', 'vertical']\"\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n    def _set_auto_param(self, w, h):\n        self.color_start = (np.random.uniform(0, 255),) * 3\n        self.color_end = (np.random.uniform(0, 255),) * 3\n        self.start_point = (np.random.uniform(0, w), np.random.uniform(0, h))\n        self.scope = np.random.uniform(0, 1)\n        self.bright_rate = np.random.uniform(0.1, 0.9)\n        self.pattern = np.random.choice(['light', 'dark'])\n        self.mode = np.random.choice(['circle', 'horizontal', 'vertical'])\n\n    def __call__(self, image):\n        \"\"\"\n        Gradient adjusts the luminance of picture.\n\n        Args:\n            image (numpy.ndarray): Original image.\n\n        Returns:\n            numpy.ndarray, image with perlin noise.\n        \"\"\"\n        ori_dtype = image.dtype\n        _, chw, normalized, gray3dim, image = self._check(image)\n        w, h = image.shape[:2]\n        if self.auto_param:\n            self._set_auto_param(w, h)\n        if self.mode == 'circle':\n            mask = _circle_gradient_mask(image, self.color_start, self.color_end, self.scope, self.start_point)\n        else:\n            mask = _line_gradient_mask(image, self.start_point, self.color_start, self.color_end, mode=self.mode)\n\n        if self.pattern == 'light':\n            img_new = cv2.addWeighted(image, 1, mask, self.bright_rate, 0.0)\n        else:\n            img_new = cv2.addWeighted(image, self.bright_rate, mask, 1 - self.bright_rate, 0.0)\n        img_new = self._original_format(img_new, chw, normalized, gray3dim)\n        return img_new.astype(ori_dtype)\n"
  },
  {
    "path": "mindarmour/natural_robustness/transform/image/natural_perturb.py",
    "content": "# Copyright 2022 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nBase class for image natural perturbation.\n\"\"\"\nimport numpy as np\n\nfrom mindspore.dataset.vision.py_transforms_util import is_numpy, hwc_to_chw\nfrom mindarmour.utils.logger import LogUtil\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Image Transformation'\n\n\ndef _chw_to_hwc(img):\n    \"\"\"\n    Transpose the input image; shape (C, H, W) to shape (H, W, C).\n\n    Args:\n        img (numpy.ndarray): Image to be converted.\n\n    Returns:\n        img (numpy.ndarray), Converted image.\n    \"\"\"\n    if is_numpy(img):\n        return img.transpose(1, 2, 0).copy()\n    raise TypeError('img should be numpy.ndarray. Got {}'.format(type(img)))\n\n\ndef _is_hwc(img):\n    \"\"\"\n    Check if the input image is shape (H, W, C).\n\n    Args:\n        img (numpy.ndarray): Image to be checked.\n\n    Returns:\n        Bool, True if input is shape (H, W, C).\n    \"\"\"\n    if is_numpy(img):\n        img_shape = np.shape(img)\n        if img_shape[2] == 3 and img_shape[1] > 3 and img_shape[0] > 3:\n            return True\n        return False\n    raise TypeError('img should be numpy.ndarray. Got {}'.format(type(img)))\n\n\ndef _is_chw(img):\n    \"\"\"\n    Check if the input image is shape (H, W, C).\n\n    Args:\n        img (numpy.ndarray): Image to be checked.\n\n    Returns:\n        Bool, True if input is shape (H, W, C).\n    \"\"\"\n    if is_numpy(img):\n        img_shape = np.shape(img)\n        if img_shape[0] == 3 and img_shape[1] > 3 and img_shape[2] > 3:\n            return True\n        return False\n    raise TypeError('img should be numpy.ndarray. Got {}'.format(type(img)))\n\n\ndef _is_rgb(img):\n    \"\"\"\n    Check if the input image is RGB.\n\n    Args:\n        img (numpy.ndarray): Image to be checked.\n\n    Returns:\n        Bool, True if input is RGB.\n    \"\"\"\n    if is_numpy(img):\n        img_shape = np.shape(img)\n        if len(np.shape(img)) == 3 and (img_shape[0] == 3 or img_shape[2] == 3):\n            return True\n        return False\n    raise TypeError('img should be numpy.ndarray. Got {}'.format(type(img)))\n\n\ndef _is_normalized(img):\n    \"\"\"\n    Check if the input image is normalized between 0 to 1.\n\n    Args:\n        img (numpy.ndarray): Image to be checked.\n\n    Returns:\n        Bool, True if input is normalized between 0 to 1.\n    \"\"\"\n    if is_numpy(img):\n        minimal = np.min(img)\n        maximum = np.max(img)\n        if minimal >= 0 and maximum <= 1:\n            return True\n        return False\n    raise TypeError('img should be Numpy array. Got {}'.format(type(img)))\n\n\nclass _NaturalPerturb:\n    \"\"\"\n    The abstract base class for all image natural perturbation classes.\n    \"\"\"\n\n    def __init__(self):\n        pass\n\n    def _check(self, image):\n        \"\"\"\n        Check image format. If input image is RGB and its shape\n        is (C, H, W), it will be transposed to (H, W, C). If the value\n        of the image is not normalized , it will be rescaled between 0 to 255.\n        \"\"\"\n        rgb = _is_rgb(image)\n        chw = False\n        gray3dim = False\n        normalized = _is_normalized(image)\n        if rgb:\n            chw = _is_chw(image)\n            if chw:\n                image = _chw_to_hwc(image)\n        else:\n            if len(np.shape(image)) == 3:\n                gray3dim = True\n                image = image[0]\n        if normalized:\n            image = image * 255\n        return rgb, chw, normalized, gray3dim, np.uint8(image)\n\n    def _original_format(self, image, chw, normalized, gray3dim):\n        \"\"\" Return image with original format. \"\"\"\n        if not is_numpy(image):\n            image = np.array(image)\n        if chw:\n            image = hwc_to_chw(image)\n        if normalized:\n            image = image / 255\n        if gray3dim:\n            image = np.expand_dims(image, 0)\n        return image\n\n    def __call__(self, image):\n        pass\n"
  },
  {
    "path": "mindarmour/natural_robustness/transform/image/transformation.py",
    "content": "# Copyright 2022 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nImage transformation.\n\"\"\"\nimport math\nimport numpy as np\nimport cv2\n\nfrom mindarmour.natural_robustness.transform.image.natural_perturb import _NaturalPerturb\nfrom mindarmour.utils._check_param import check_param_multi_types, check_param_type, check_value_non_negative\nfrom mindarmour.utils.logger import LogUtil\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Image Transformation'\n\n\nclass Translate(_NaturalPerturb):\n    r\"\"\"\n    Translate an image.\n\n    Args:\n        x_bias (Union[int, float]): X-direction translation, :math:`x = x + x\\_bias*image\\_width`.\n            Suggested value range in [-0.1, 0.1]. Default: ``0``.\n        y_bias (Union[int, float]): Y-direction translation, :math:`y = y + y\\_bias*image\\_length`.\n            Suggested value range in [-0.1, 0.1]. Default: ``0``.\n        auto_param (bool): Auto selected parameters. Selected parameters will preserve semantics of image.\n            Default: ``False``.\n\n    Examples:\n        >>> import cv2\n        >>> img = cv2.imread('1.png')\n        >>> img = np.array(img)\n        >>> x_bias = 0.1\n        >>> y_bias = 0.1\n        >>> trans = Translate(x_bias, y_bias)\n        >>> dst = trans(img)\n    \"\"\"\n\n    def __init__(self, x_bias=0, y_bias=0, auto_param=False):\n        super(Translate, self).__init__()\n        self.x_bias = check_param_multi_types('x_bias', x_bias, [int, float])\n        self.y_bias = check_param_multi_types('y_bias', y_bias, [int, float])\n        if auto_param:\n            self.x_bias = np.random.uniform(-0.1, 0.1)\n            self.y_bias = np.random.uniform(-0.1, 0.1)\n\n    def __call__(self, image):\n        \"\"\"\n        Transform the image.\n\n        Args:\n            image (numpy.ndarray): Original image to be transformed.\n\n        Returns:\n            numpy.ndarray, transformed image.\n        \"\"\"\n        ori_dtype = image.dtype\n        _, chw, normalized, gray3dim, image = self._check(image)\n        h, w = image.shape[:2]\n        matrix = np.array([[1, 0, self.x_bias * w], [0, 1, self.y_bias * h]], dtype=np.float)\n        new_img = cv2.warpAffine(image, matrix, (w, h))\n        new_img = self._original_format(new_img, chw, normalized, gray3dim)\n        return new_img.astype(ori_dtype)\n\n\nclass Scale(_NaturalPerturb):\n    \"\"\"\n    Scale an image in the middle.\n\n    Args:\n        factor_x (Union[float, int]): Rescale in X-direction, x=factor_x*x. Suggested value range in [0.5, 1] and\n            abs(factor_y - factor_x) < 0.5. Default: ``1``.\n        factor_y (Union[float, int]): Rescale in Y-direction, y=factor_y*y. Suggested value range in [0.5, 1] and\n            abs(factor_y - factor_x) < 0.5. Default: ``1``.\n        auto_param (bool): Auto selected parameters. Selected parameters will preserve semantics of image.\n            Default: ``False``.\n\n    Examples:\n        >>> import cv2\n        >>> img = cv2.imread('1.png')\n        >>> img = np.array(img)\n        >>> factor_x = 0.7\n        >>> factor_y = 0.6\n        >>> trans = Scale(factor_x, factor_y)\n        >>> dst = trans(img)\n    \"\"\"\n\n    def __init__(self, factor_x=1, factor_y=1, auto_param=False):\n        super(Scale, self).__init__()\n        self.factor_x = check_param_multi_types('factor_x', factor_x, [int, float])\n        self.factor_y = check_param_multi_types('factor_y', factor_y, [int, float])\n        auto_param = check_param_type('auto_param', auto_param, bool)\n        if auto_param:\n            self.factor_x = np.random.uniform(0.5, 1)\n            self.factor_y = np.random.uniform(0.5, 1)\n\n    def __call__(self, image):\n        \"\"\"\n        Transform the image.\n\n        Args:\n            image (numpy.ndarray): Original image to be transformed.\n\n        Returns:\n            numpy.ndarray, transformed image.\n        \"\"\"\n        ori_dtype = image.dtype\n        _, chw, normalized, gray3dim, image = self._check(image)\n        h, w = image.shape[:2]\n        matrix = np.array([[self.factor_x, 0, 0], [0, self.factor_y, 0]], dtype=np.float)\n        new_img = cv2.warpAffine(image, matrix, (w, h))\n        new_img = self._original_format(new_img, chw, normalized, gray3dim)\n        return new_img.astype(ori_dtype)\n\n\nclass Shear(_NaturalPerturb):\n    \"\"\"\n    Shear an image, the mapping between sheared image and origin image is\n    :math:`(new_x, new_y) = (x+factor_x \\times y, factor_y \\times x+y)`.\n    Then the sheared image will be rescaled to fit original size.\n\n    Args:\n        factor (Union[float, int]): Shear rate in shear direction. Suggested value range in [0.05, 0.5].\n            Default: ``0.2``.\n        direction (str): Direction of deformation. Optional value is ``'vertical'`` or ``'horizontal'``.\n            Default: 'horizontal'.\n        auto_param (bool): Auto selected parameters. Selected parameters will preserve semantics of image.\n            Default: ``False``.\n\n    Examples:\n        >>> import cv2\n        >>> img = cv2.imread('1.png')\n        >>> img = np.array(img)\n        >>> factor = 0.2\n        >>> trans = Shear(factor, direction='horizontal')\n        >>> dst = trans(img)\n    \"\"\"\n\n    def __init__(self, factor=0.2, direction='horizontal', auto_param=False):\n        super(Shear, self).__init__()\n        self.factor = check_param_multi_types('factor', factor, [int, float])\n        if direction not in ['horizontal', 'vertical']:\n            msg = \"'direction must be in ['horizontal', 'vertical'], but got {}\".format(direction)\n            raise ValueError(msg)\n        self.direction = direction\n        auto_param = check_param_type('auto_params', auto_param, bool)\n        if auto_param:\n            self.factor = np.random.uniform(0.05, 0.5)\n            self.direction = np.random.choice(['horizontal', 'vertical'])\n\n    def __call__(self, image):\n        \"\"\"\n        Transform the image.\n\n        Args:\n            image (numpy.ndarray): Original image to be transformed.\n\n        Returns:\n            numpy.ndarray, transformed image.\n        \"\"\"\n        ori_dtype = image.dtype\n        _, chw, normalized, gray3dim, image = self._check(image)\n        h, w = image.shape[:2]\n        if self.direction == 'horizontal':\n            matrix = np.array([[1, self.factor, 0], [0, 1, 0]], dtype=np.float)\n            nw = int(w + self.factor * h)\n            nh = h\n        else:\n            matrix = np.array([[1, 0, 0], [self.factor, 1, 0]], dtype=np.float)\n            nw = w\n            nh = int(h + self.factor * w)\n        new_img = cv2.warpAffine(image, matrix, (nw, nh))\n        new_img = cv2.resize(new_img, (w, h))\n        new_img = self._original_format(new_img, chw, normalized, gray3dim)\n        return new_img.astype(ori_dtype)\n\n\nclass Rotate(_NaturalPerturb):\n    \"\"\"\n    Rotate an image of counter clockwise around its center.\n\n    Args:\n        angle (Union[float, int]): Degrees of counter clockwise. Suggested value range in [-60, 60].\n            Default: ``20``.\n        auto_param (bool): Auto selected parameters. Selected parameters will preserve semantics of image.\n            Default: ``False``.\n\n    Examples:\n        >>> import cv2\n        >>> img = cv2.imread('1.png')\n        >>> img = np.array(img)\n        >>> angle = 20\n        >>> trans = Rotate(angle)\n        >>> dst = trans(img)\n    \"\"\"\n\n    def __init__(self, angle=20, auto_param=False):\n        super(Rotate, self).__init__()\n        self.angle = check_param_multi_types('angle', angle, [int, float])\n        auto_param = check_param_type('auto_param', auto_param, bool)\n        if auto_param:\n            self.angle = np.random.uniform(0, 360)\n\n    def __call__(self, image):\n        \"\"\"\n        Transform the image.\n\n        Args:\n            image (numpy.ndarray): Original image to be transformed.\n\n        Returns:\n            numpy.ndarray, rotated image.\n        \"\"\"\n        ori_dtype = image.dtype\n        _, chw, normalized, gray3dim, image = self._check(image)\n        h, w = image.shape[:2]\n        center = (w // 2, h // 2)\n        matrix = cv2.getRotationMatrix2D(center, -self.angle, 1.0)\n        cos = np.abs(matrix[0, 0])\n        sin = np.abs(matrix[0, 1])\n\n        # Calculate new edge after rotated\n        nw = int((h * sin) + (w * cos))\n        nh = int((h * cos) + (w * sin))\n        # Adjust move distance of rotate matrix.\n        matrix[0, 2] += (nw / 2) - center[0]\n        matrix[1, 2] += (nh / 2) - center[1]\n        rotate = cv2.warpAffine(image, matrix, (nw, nh))\n        rotate = cv2.resize(rotate, (w, h))\n        new_img = self._original_format(rotate, chw, normalized, gray3dim)\n        return new_img.astype(ori_dtype)\n\n\nclass Perspective(_NaturalPerturb):\n    \"\"\"\n    Perform perspective transformation on a given picture.\n\n    Args:\n        ori_pos (list[list[int]]): Four points in original image.\n        dst_pos (list[list[int]]): The point coordinates of the 4 points in `ori_pos` after perspective transformation.\n        auto_param (bool): Auto selected parameters. Selected parameters will preserve semantics of image.\n            Default: ``False``.\n\n    Examples:\n        >>> import cv2\n        >>> img = cv2.imread('1.png')\n        >>> img = np.array(img)\n        >>> ori_pos = [[0, 0], [0, 800], [800, 0], [800, 800]]\n        >>> dst_pos = [[50, 0], [0, 800], [780, 0], [800, 800]]\n        >>> trans = Perspective(ori_pos, dst_pos)\n        >>> dst = trans(img)\n    \"\"\"\n\n    def __init__(self, ori_pos, dst_pos, auto_param=False):\n        super(Perspective, self).__init__()\n        ori_pos = check_param_type('ori_pos', ori_pos, list)\n        dst_pos = check_param_type('dst_pos', dst_pos, list)\n        self.ori_pos = np.float32(ori_pos)\n        self.dst_pos = np.float32(dst_pos)\n        self.auto_param = check_param_type('auto_param', auto_param, bool)\n\n    def _set_auto_param(self, w, h):\n        self.ori_pos = [[h * 0.25, w * 0.25], [h * 0.25, w * 0.75], [h * 0.75, w * 0.25], [h * 0.75, w * 0.75]]\n        self.dst_pos = [[np.random.uniform(0, h * 0.5), np.random.uniform(0, w * 0.5)],\n                        [np.random.uniform(0, h * 0.5), np.random.uniform(w * 0.5, w)],\n                        [np.random.uniform(h * 0.5, h), np.random.uniform(0, w * 0.5)],\n                        [np.random.uniform(h * 0.5, h), np.random.uniform(w * 0.5, w)]]\n        self.ori_pos = np.float32(self.ori_pos)\n        self.dst_pos = np.float32(self.dst_pos)\n\n    def __call__(self, image):\n        \"\"\"\n        Transform the image.\n\n        Args:\n            image (numpy.ndarray): Original image to be transformed.\n\n        Returns:\n            numpy.ndarray, transformed image.\n        \"\"\"\n        ori_dtype = image.dtype\n        _, chw, normalized, gray3dim, image = self._check(image)\n        h, w = image.shape[:2]\n        if self.auto_param:\n            self._set_auto_param(w, h)\n        matrix = cv2.getPerspectiveTransform(self.ori_pos, self.dst_pos)\n        new_img = cv2.warpPerspective(image, matrix, (w, h))\n        new_img = self._original_format(new_img, chw, normalized, gray3dim)\n        return new_img.astype(ori_dtype)\n\n\nclass Curve(_NaturalPerturb):\n    \"\"\"\n    Curve picture using sin method.\n\n    Args:\n        curves (union[float, int]): Number of curve cycles. Suggested value range in [0.1, 5]. Default: ``3``.\n        depth (union[float, int]): Amplitude of sin method. Suggested value not exceed 1/10 of the length of the\n            picture. Default: ``10``.\n        mode (str): Direction of deformation. Optional value is ``'vertical'`` or ``'horizontal'``.\n            Default: ``'vertical'``.\n        auto_param (bool): Auto selected parameters. Selected parameters will preserve semantics of image.\n            Default: ``False``.\n\n    Examples:\n        >>> import cv2\n        >>> img = cv2.imread('x.png')\n        >>> curves =1\n        >>> depth = 10\n        >>> trans = Curve(curves, depth, mode='vertical')\n        >>> img_new = trans(img)\n    \"\"\"\n\n    def __init__(self, curves=3, depth=10, mode='vertical', auto_param=False):\n        super(Curve).__init__()\n        self.curves = check_value_non_negative('curves', curves)\n        self.depth = check_value_non_negative('depth', depth)\n        if mode in ['vertical', 'horizontal']:\n            self.mode = mode\n        else:\n            msg = \"Value of param mode must be in ['vertical', 'horizontal']\"\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        self.auto_param = check_param_type('auto_param', auto_param, bool)\n\n    def _set_auto_params(self, height, width):\n        if self.auto_param:\n            self.curves = np.random.uniform(1, 5)\n            self.mode = np.random.choice(['vertical', 'horizontal'])\n            if self.mode == 'vertical':\n                self.depth = np.random.uniform(1, 0.1 * width)\n            else:\n                self.depth = np.random.uniform(1, 0.1 * height)\n\n    def __call__(self, image):\n        \"\"\"\n        Curve picture using sin method.\n\n        Args:\n            image (numpy.ndarray): Original image.\n\n        Returns:\n            numpy.ndarray, curved image.\n        \"\"\"\n        ori_dtype = image.dtype\n        _, chw, normalized, gray3dim, image = self._check(image)\n        shape = image.shape\n        height, width = shape[:2]\n        if self.mode == 'vertical':\n            if len(shape) == 3:\n                image = np.transpose(image, [1, 0, 2])\n            else:\n                image = np.transpose(image, [1, 0])\n        src_x = np.zeros((height, width), np.float32)\n        src_y = np.zeros((height, width), np.float32)\n\n        for y in range(height):\n            for x in range(width):\n                src_x[y, x] = x\n                src_y[y, x] = y + self.depth * math.sin(x / (width / self.curves / 2 / math.pi))\n        img_new = cv2.remap(image, src_x, src_y, cv2.INTER_LINEAR)\n\n        if self.mode == 'vertical':\n            if len(shape) == 3:\n                img_new = np.transpose(img_new, [1, 0, 2])\n            else:\n                img_new = np.transpose(image, [1, 0])\n        new_img = self._original_format(img_new, chw, normalized, gray3dim)\n        return new_img.astype(ori_dtype)\n"
  },
  {
    "path": "mindarmour/privacy/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis module provides various methods to protect the privacy of given model, and\nalso provides some methods to evaluate the risk of privacy leakage of given\nmodel.\n\"\"\"\n"
  },
  {
    "path": "mindarmour/privacy/diff_privacy/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis module provides Differential Privacy feature to protect user privacy.\n\"\"\"\nfrom .mechanisms.mechanisms import NoiseGaussianRandom\nfrom .mechanisms.mechanisms import NoiseAdaGaussianRandom\nfrom .mechanisms.mechanisms import AdaClippingWithGaussianRandom\nfrom .mechanisms.mechanisms import NoiseMechanismsFactory\nfrom .mechanisms.mechanisms import ClipMechanismsFactory\nfrom .monitor.monitor import PrivacyMonitorFactory\nfrom .monitor.monitor import RDPMonitor\nfrom .monitor.monitor import ZCDPMonitor\nfrom .optimizer.optimizer import DPOptimizerClassFactory\nfrom .train.model import DPModel\n\n__all__ = ['NoiseGaussianRandom',\n           'NoiseAdaGaussianRandom',\n           'AdaClippingWithGaussianRandom',\n           'NoiseMechanismsFactory',\n           'ClipMechanismsFactory',\n           'PrivacyMonitorFactory',\n           'RDPMonitor',\n           'ZCDPMonitor',\n           'DPOptimizerClassFactory',\n           'DPModel']\n"
  },
  {
    "path": "mindarmour/privacy/diff_privacy/mechanisms/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\ninit mechanisms.\n\"\"\"\n"
  },
  {
    "path": "mindarmour/privacy/diff_privacy/mechanisms/mechanisms.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nNoise Mechanisms.\n\"\"\"\nfrom abc import abstractmethod\n\nfrom mindspore import Tensor\nfrom mindspore.nn import Cell\nfrom mindspore.ops import operations as P\nfrom mindspore.ops.composite import normal\nfrom mindspore.common.parameter import Parameter\nfrom mindspore.common import dtype as mstype\n\nfrom mindarmour.utils._check_param import check_param_type\nfrom mindarmour.utils._check_param import check_value_positive\nfrom mindarmour.utils._check_param import check_param_in_range\nfrom mindarmour.utils._check_param import check_value_non_negative\nfrom mindarmour.utils.logger import LogUtil\n\nLOGGER = LogUtil.get_instance()\nTAG = 'NoiseMechanism'\n\n\nclass ClipMechanismsFactory:\n    \"\"\"\n    Factory class of clip mechanisms\n    Wrapper of clip noise generating mechanisms. It supports Adaptive Clipping with\n    Gaussian Random Noise for now.\n\n    For details, please check `Tutorial <https://mindspore.cn/mindarmour/docs/zh-CN/master/protect_user_privacy_with_differential_privacy.html#%E5%B7%AE%E5%88%86%E9%9A%90%E7%A7%81>`_.\n\n    \"\"\"\n\n    def __init__(self):\n        pass\n\n    @staticmethod\n    def create(mech_name, decay_policy='Linear', learning_rate=0.001,\n               target_unclipped_quantile=0.9, fraction_stddev=0.01, seed=0):\n        r\"\"\"\n        Args:\n            mech_name(str): Clip noise generated strategy, support 'Gaussian' now.\n            decay_policy(str): Decay policy of adaptive clipping, decay_policy must\n                be ``'Linear'`` or ``'Geometric'``. Default: ``'Linear'``.\n            learning_rate(float): Learning rate of update norm clip. Default: ``0.001``.\n            target_unclipped_quantile(float): Target quantile of norm clip. Default: ``0.9``.\n            fraction_stddev(float): The stddev of Gaussian normal which used in\n                empirical_fraction, the formula is :math:`empirical\\_fraction + N(0, fraction\\_stddev)`.\n                Default: ``0.01``.\n            seed(int): Original random seed, if `seed` is ``0`` random normal will use secure\n                random number. IF `seed` is not ``0`` random normal will generate values using\n                given seed. Default: ``0``.\n\n        Returns:\n            Mechanisms, class of noise generated Mechanism.\n\n        Raises:\n            NameError: `mech_name` must be in ['Gaussian'].\n\n        Examples:\n            >>> from mindspore import Tensor\n            >>> from mindspore.common import dtype as mstype\n            >>> from mindarmour.privacy.diff_privacy import ClipMechanismsFactory\n            >>> decay_policy = 'Linear'\n            >>> beta = Tensor(0.5, mstype.float32)\n            >>> norm_bound = Tensor(1.0, mstype.float32)\n            >>> beta_stddev = 0.01\n            >>> learning_rate = 0.001\n            >>> target_unclipped_quantile = 0.9\n            >>> clip_mechanism = ClipMechanismsFactory()\n            >>> ada_clip = clip_mechanism.create('Gaussian',\n            ...                                  decay_policy=decay_policy,\n            ...                                  learning_rate=learning_rate,\n            ...                                  target_unclipped_quantile=target_unclipped_quantile,\n            ...                                  fraction_stddev=beta_stddev)\n            >>> next_norm_bound = ada_clip(beta, norm_bound)\n\n        \"\"\"\n        if mech_name == 'Gaussian':\n            return AdaClippingWithGaussianRandom(decay_policy, learning_rate,\n                                                 target_unclipped_quantile, fraction_stddev, seed)\n        raise NameError(\"The {} is not implement, please choose \"\n                        \"['Gaussian']\".format(mech_name))\n\n\nclass NoiseMechanismsFactory:\n    \"\"\" Factory class of noise mechanisms\n    Wrapper of noise generating mechanisms. It supports Gaussian Random Noise and\n    Adaptive Gaussian Random Noise for now.\n\n    For details, please check `Tutorial <https://mindspore.cn/mindarmour/docs/zh-CN/master/protect_user_privacy_with_differential_privacy.html#%E5%B7%AE%E5%88%86%E9%9A%90%E7%A7%81>`_.\n\n    \"\"\"\n    def __init__(self):\n        pass\n\n    @staticmethod\n    def create(mech_name, norm_bound=1.0, initial_noise_multiplier=1.0, seed=0, noise_decay_rate=6e-6,\n               decay_policy=None):\n        \"\"\"\n        Args:\n            mech_name(str): Noise generated strategy, could be ``'Gaussian'`` or\n                ``'AdaGaussian'``. Noise would be decayed with ``'AdaGaussian'`` mechanism\n                while be constant with ``'Gaussian'`` mechanism.\n            norm_bound(float): Clipping bound for the l2 norm of the gradients. Default: ``1.0``.\n            initial_noise_multiplier(float): Ratio of the standard deviation of\n                Gaussian noise divided by the `norm_bound`, which will be used to\n                calculate privacy spent. Default: ``1.0``.\n            seed(int): Original random seed, if `seed` is ``0`` random normal will use secure\n                random number. IF `seed` is not ``0`` random normal will generate values using\n                given seed. Default: ``0``.\n            noise_decay_rate(float): Hyper parameter for controlling the noise decay. Default: ``6e-6``.\n            decay_policy(str): Mechanisms parameters update policy. If `decay_policy` is ``None``, no\n                parameters need update. Default: ``None``.\n\n        Returns:\n            Mechanisms, class of noise generated Mechanism.\n\n        Raises:\n            NameError: `mech_name` must be in ['Gaussian', 'AdaGaussian'].\n\n        Examples:\n            >>> from mindarmour.privacy.diff_privacy import NoiseMechanismsFactory\n            >>> norm_bound = 1.0\n            >>> initial_noise_multiplier = 1.0\n            >>> noise_mechanism = NoiseMechanismsFactory()\n            >>> clip = noise_mechanism.create('Gaussian',\n            ...                               norm_bound=norm_bound,\n            ...                               initial_noise_multiplier=initial_noise_multiplier)\n        \"\"\"\n        if mech_name == 'Gaussian':\n            return NoiseGaussianRandom(norm_bound=norm_bound,\n                                       initial_noise_multiplier=initial_noise_multiplier,\n                                       seed=seed,\n                                       decay_policy=decay_policy)\n        if mech_name == 'AdaGaussian':\n            return NoiseAdaGaussianRandom(norm_bound=norm_bound,\n                                          initial_noise_multiplier=initial_noise_multiplier,\n                                          seed=seed,\n                                          noise_decay_rate=noise_decay_rate,\n                                          decay_policy=decay_policy)\n        raise NameError(\"The {} is not implement, please choose \"\n                        \"['Gaussian', 'AdaGaussian']\".format(mech_name))\n\n\nclass _Mechanisms(Cell):\n    \"\"\"\n    Basic class of noise generated mechanism.\n    \"\"\"\n\n    @abstractmethod\n    def construct(self, gradients):\n        \"\"\"\n        Construct function.\n        \"\"\"\n\n\nclass NoiseGaussianRandom(_Mechanisms):\n    r\"\"\"\n    Generate noise in Gaussian Distribution with :math:`mean=0` and\n    :math:`standard\\_deviation = norm\\_bound * initial\\_noise\\_multiplier`.\n\n    Args:\n        norm_bound(float): Clipping bound for the l2 norm of the gradients.\n            Default: ``1.0``.\n        initial_noise_multiplier(float): Ratio of the standard deviation of\n            Gaussian noise divided by the `norm_bound`, which will be used to\n            calculate privacy spent. Default: ``1.0``.\n        seed(int): Original random seed, if `seed` is ``0``, random normal will use secure\n            random number. If `seed` is not ``0``, random normal will generate values using\n            given seed. Default: ``0``.\n        decay_policy(str): Mechanisms parameters update policy. Default: ``None``.\n\n    Examples:\n        >>> from mindspore import Tensor\n        >>> from mindspore.common import dtype as mstype\n        >>> from mindarmour.privacy.diff_privacy import NoiseGaussianRandom\n        >>> gradients = Tensor([0.2, 0.9], mstype.float32)\n        >>> norm_bound = 0.1\n        >>> initial_noise_multiplier = 1.0\n        >>> seed = 0\n        >>> decay_policy = None\n        >>> net = NoiseGaussianRandom(norm_bound, initial_noise_multiplier, seed, decay_policy)\n        >>> res = net(gradients)\n    \"\"\"\n\n    def __init__(self, norm_bound=1.0, initial_noise_multiplier=1.0, seed=0, decay_policy=None):\n        super(NoiseGaussianRandom, self).__init__()\n        norm_bound = check_param_type('norm_bound', norm_bound, float)\n        self._norm_bound = check_value_positive('norm_bound', norm_bound)\n        self._norm_bound = Tensor(norm_bound, mstype.float32)\n        initial_noise_multiplier = check_param_type('initial_noise_multiplier', initial_noise_multiplier, float)\n        self._initial_noise_multiplier = check_value_positive('initial_noise_multiplier',\n                                                              initial_noise_multiplier)\n        self._initial_noise_multiplier = Tensor(initial_noise_multiplier, mstype.float32)\n        self._mean = Tensor(0, mstype.float32)\n        if decay_policy is not None:\n            raise ValueError('decay_policy must be None in GaussianRandom class, but got {}.'.format(decay_policy))\n        self._decay_policy = decay_policy\n        seed = check_param_type('seed', seed, int)\n        self._seed = check_value_non_negative('seed', seed)\n\n    def construct(self, gradients):\n        \"\"\"\n        Generated Gaussian noise.\n\n        Args:\n            gradients(Tensor): The gradients.\n\n        Returns:\n            Tensor, generated noise with shape like given gradients.\n        \"\"\"\n        shape = P.Shape()(gradients)\n        stddev = P.Mul()(self._norm_bound, self._initial_noise_multiplier)\n        noise = normal(shape, self._mean, stddev, self._seed)\n        return noise\n\n\nclass NoiseAdaGaussianRandom(NoiseGaussianRandom):\n    \"\"\"\n    Adaptive Gaussian noise generated mechanism. Noise would be decayed with\n    training. Decay mode could be 'Time' mode, 'Step' mode, 'Exp' mode.\n    `self._noise_multiplier` will be update during model training process.\n\n    Args:\n        norm_bound(float): Clipping bound for the l2 norm of the gradients.\n             Default: ``1.0``.\n        initial_noise_multiplier(float): Ratio of the standard deviation of\n            Gaussian noise divided by the norm_bound, which will be used to\n            calculate privacy spent. Default: ``1.0``.\n        seed(int): Original random seed, if `seed` is ``0`` random normal will use secure\n            random number. IF `seed` is not ``0`` random normal will generate values using\n            given seed. Default: ``0``.\n        noise_decay_rate(float): Hyper parameter for controlling the noise decay.\n            Default: ``6e-6``.\n        decay_policy(str): Noise decay strategy include ``'Step'``, ``'Time'``, ``'Exp'``.\n            Default: ``'Exp'``.\n\n    Examples:\n        >>> from mindspore import Tensor\n        >>> from mindspore.common import dtype as mstype\n        >>> from mindarmour.privacy.diff_privacy import NoiseAdaGaussianRandom\n        >>> gradients = Tensor([0.2, 0.9], mstype.float32)\n        >>> norm_bound = 1.0\n        >>> initial_noise_multiplier = 1.0\n        >>> seed = 0\n        >>> noise_decay_rate = 6e-6\n        >>> decay_policy = \"Exp\"\n        >>> net = NoiseAdaGaussianRandom(norm_bound, initial_noise_multiplier, seed, noise_decay_rate, decay_policy)\n        >>> res = net(gradients)\n    \"\"\"\n\n    def __init__(self, norm_bound=1.0, initial_noise_multiplier=1.0, seed=0, noise_decay_rate=6e-6, decay_policy='Exp'):\n        super(NoiseAdaGaussianRandom, self).__init__(norm_bound=norm_bound,\n                                                     initial_noise_multiplier=initial_noise_multiplier,\n                                                     seed=seed)\n        self._noise_multiplier = Parameter(self._initial_noise_multiplier,\n                                           name='noise_multiplier')\n        noise_decay_rate = check_param_type('noise_decay_rate', noise_decay_rate, float)\n        check_param_in_range('noise_decay_rate', noise_decay_rate, 0.0, 1.0)\n        self._noise_decay_rate = Tensor(noise_decay_rate, mstype.float32)\n        if decay_policy not in ['Time', 'Step', 'Exp']:\n            raise NameError(\"The decay_policy must be in ['Time', 'Step', 'Exp'], but \"\n                            \"get {}\".format(decay_policy))\n        self._decay_policy = decay_policy\n\n    def construct(self, gradients):\n        \"\"\"\n        Generated Adaptive Gaussian noise.\n\n        Args:\n            gradients(Tensor): The gradients.\n\n        Returns:\n            Tensor, generated noise with shape like given gradients.\n        \"\"\"\n        shape = P.Shape()(gradients)\n        stddev = P.Mul()(self._norm_bound, self._noise_multiplier)\n        noise = normal(shape, self._mean, stddev, self._seed)\n        return noise\n\n\nclass _MechanismsParamsUpdater(Cell):\n    \"\"\"\n    Update mechanisms parameters, the parameters will refresh in train period.\n\n    Args:\n        decay_policy(str): Pass in by the mechanisms class, mechanisms parameters\n            update policy.\n        decay_rate(Tensor): Pass in by the mechanisms class, hyper parameter for\n            controlling the decay size.\n        cur_noise_multiplier(Parameter): Pass in by the mechanisms class,\n            current params value in this time.\n        init_noise_multiplier(Parameter):Pass in by the mechanisms class,\n            initial params value to be updated.\n\n    Returns:\n        Tuple, next params value.\n    \"\"\"\n    def __init__(self, decay_policy, decay_rate, cur_noise_multiplier, init_noise_multiplier):\n        super(_MechanismsParamsUpdater, self).__init__()\n        self._decay_policy = decay_policy\n        self._decay_rate = decay_rate\n        self._cur_noise_multiplier = cur_noise_multiplier\n        self._init_noise_multiplier = init_noise_multiplier\n\n        self._div = P.Div()\n        self._add = P.Add()\n        self._assign = P.Assign()\n        self._sub = P.Sub()\n        self._one = Tensor(1, mstype.float32)\n        self._mul = P.Mul()\n        self._exp = P.Exp()\n\n    def construct(self):\n        \"\"\"\n        update parameters to `self._cur_params`.\n\n        Returns:\n            Tuple, next step parameters value.\n        \"\"\"\n        if self._decay_policy == 'Time':\n            temp = self._div(self._init_noise_multiplier, self._cur_noise_multiplier)\n            temp = self._add(temp, self._decay_rate)\n            next_noise_multiplier = self._assign(self._cur_noise_multiplier,\n                                                 self._div(self._init_noise_multiplier, temp))\n        elif self._decay_policy == 'Step':\n            temp = self._sub(self._one, self._decay_rate)\n            next_noise_multiplier = self._assign(self._cur_noise_multiplier,\n                                                 self._mul(temp, self._cur_noise_multiplier))\n        else:\n            next_noise_multiplier = self._assign(self._cur_noise_multiplier,\n                                                 self._div(self._cur_noise_multiplier, self._exp(self._decay_rate)))\n        return next_noise_multiplier\n\n\nclass AdaClippingWithGaussianRandom(Cell):\n    r\"\"\"\n    Adaptive clipping. If `decay_policy` is 'Linear', the update formula :math:`norm\\_bound = norm\\_bound -\n    learning\\_rate*(beta - target\\_unclipped\\_quantile)`.\n    If `decay_policy` is 'Geometric', the update formula is :math:`norm\\_bound =\n    norm\\_bound*exp(-learning\\_rate*(empirical\\_fraction - target\\_unclipped\\_quantile))`.\n    where beta is the empirical fraction of samples with the value at most\n    `target_unclipped_quantile`.\n\n    Args:\n        decay_policy(str): Decay policy of adaptive clipping, `decay_policy` must\n            be ``'Linear'`` or ``'Geometric'``. Default: ``'Linear'``.\n        learning_rate(float): Learning rate of update norm clip. Default: ``0.001``.\n        target_unclipped_quantile(float): Target quantile of norm clip. Default: ``0.9``.\n        fraction_stddev(float): The stddev of Gaussian normal which used in\n            empirical_fraction, the formula is empirical_fraction + N(0, fraction_stddev).\n            Default: ``0.01``.\n        seed(int): Original random seed, if `seed` is ``0`` random normal will use secure\n            random number. IF `seed` is not ``0`` random normal will generate values using\n            given seed. Default: ``0``.\n\n    Returns:\n        Tensor, undated norm clip .\n\n    Examples:\n        >>> from mindspore import Tensor\n        >>> from mindspore.common import dtype as mstype\n        >>> from mindarmour.privacy.diff_privacy import AdaClippingWithGaussianRandom\n        >>> decay_policy = 'Linear'\n        >>> beta = Tensor(0.5, mstype.float32)\n        >>> norm_bound = Tensor(1.0, mstype.float32)\n        >>> beta_stddev = 0.01\n        >>> learning_rate = 0.001\n        >>> target_unclipped_quantile = 0.9\n        >>> ada_clip = AdaClippingWithGaussianRandom(decay_policy=decay_policy,\n        ...                                          learning_rate=learning_rate,\n        ...                                          target_unclipped_quantile=target_unclipped_quantile,\n        ...                                          fraction_stddev=beta_stddev)\n        >>> next_norm_bound = ada_clip(beta, norm_bound)\n\n    \"\"\"\n\n    def __init__(self, decay_policy='Linear', learning_rate=0.001,\n                 target_unclipped_quantile=0.9, fraction_stddev=0.01, seed=0):\n        super(AdaClippingWithGaussianRandom, self).__init__()\n        if decay_policy not in ['Linear', 'Geometric']:\n            msg = \"decay policy of adaptive clip must be in ['Linear', 'Geometric'], \\\n                but got: {}\".format(decay_policy)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        self._decay_policy = decay_policy\n        learning_rate = check_param_type('learning_rate', learning_rate, float)\n        learning_rate = check_value_positive('learning_rate', learning_rate)\n        self._learning_rate = Tensor(learning_rate, mstype.float32)\n        fraction_stddev = check_param_type('fraction_stddev', fraction_stddev, float)\n        self._fraction_stddev = Tensor(fraction_stddev, mstype.float32)\n        target_unclipped_quantile = check_param_type('target_unclipped_quantile',\n                                                     target_unclipped_quantile,\n                                                     float)\n        self._target_unclipped_quantile = Tensor(target_unclipped_quantile,\n                                                 mstype.float32)\n\n        self._zero = Tensor(0, mstype.float32)\n        self._add = P.Add()\n        self._sub = P.Sub()\n        self._mul = P.Mul()\n        self._exp = P.Exp()\n        seed = check_param_type('seed', seed, int)\n        self._seed = check_value_non_negative('seed', seed)\n\n    def construct(self, empirical_fraction, norm_bound):\n        \"\"\"\n        Update value of norm_bound.\n\n        Args:\n            empirical_fraction(Tensor): empirical fraction of samples with the\n                value at most `target_unclipped_quantile`.\n            norm_bound(Tensor): Clipping bound for the l2 norm of the gradients.\n\n        Returns:\n            Tensor, generated noise with shape like given gradients.\n        \"\"\"\n        fraction_noise = normal((1,), self._zero, self._fraction_stddev, self._seed)\n        empirical_fraction = self._add(empirical_fraction, fraction_noise)\n        if self._decay_policy == 'Linear':\n            grad_clip = self._sub(empirical_fraction,\n                                  self._target_unclipped_quantile)\n            next_norm_bound = self._sub(norm_bound,\n                                        self._mul(self._learning_rate, grad_clip))\n\n        else:\n            grad_clip = self._sub(empirical_fraction,\n                                  self._target_unclipped_quantile)\n            grad_clip = self._exp(self._mul(-self._learning_rate, grad_clip))\n            next_norm_bound = self._mul(norm_bound, grad_clip)\n        return next_norm_bound\n"
  },
  {
    "path": "mindarmour/privacy/diff_privacy/monitor/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\ninit monitor.\n\"\"\"\n"
  },
  {
    "path": "mindarmour/privacy/diff_privacy/monitor/monitor.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\" Monitor module of differential privacy training. \"\"\"\nimport numpy as np\nfrom scipy import special\n\nfrom mindspore.train.callback import Callback\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_int_positive, \\\n    check_value_positive, check_param_in_range, check_param_type\n\nLOGGER = LogUtil.get_instance()\nTAG = 'DP monitor'\n\n\nclass PrivacyMonitorFactory:\n    \"\"\"\n    Factory class of DP training's privacy monitor.\n    For details, please check `Tutorial <https://mindspore.cn/mindarmour/docs/zh-CN/master/protect_user_privacy_with_differential_privacy.html#%E5%B7%AE%E5%88%86%E9%9A%90%E7%A7%81>`_.\n\n    \"\"\"\n\n    def __init__(self):\n        pass\n\n    @staticmethod\n    def create(policy, *args, **kwargs):\n        \"\"\"\n        Create a privacy monitor class.\n\n        Args:\n            policy (str): Monitor policy, ``'rdp'`` and ``'zcdp'`` are supported\n                by now. If `policy` is ``'rdp'``, the monitor will compute the\n                privacy budget of DP training based on Renyi differential\n                privacy theory; If `policy` is ``'zcdp'``, the monitor will compute\n                the privacy budget of DP training based on zero-concentrated\n                differential privacy theory. It's worth noting that ``'zcdp'``\n                is not suitable for subsampling noise mechanism.\n            args (Union[int, float, numpy.ndarray, list, str]): Parameters\n                used for creating a privacy monitor.\n            kwargs (Union[int, float, numpy.ndarray, list, str]): Keyword\n                parameters used for creating a privacy monitor.\n\n        Returns:\n            Callback, a privacy monitor.\n\n        Examples:\n            >>> from mindarmour.privacy.diff_privacy import PrivacyMonitorFactory\n            >>> rdp = PrivacyMonitorFactory.create(policy='rdp', num_samples=60000, batch_size=32)\n        \"\"\"\n        if policy == 'rdp':\n            return RDPMonitor(*args, **kwargs)\n        if policy == 'zcdp':\n            return ZCDPMonitor(*args, **kwargs)\n        raise ValueError(\"The policy must be 'rdp' or 'zcdp', but got {}\".format(policy))\n\n\nclass RDPMonitor(Callback):\n    r\"\"\"\n    Compute the privacy budget of DP training based on Renyi differential\n    privacy (RDP) theory. According to the reference below, if a randomized\n    mechanism is said to have ε'-Renyi differential privacy of order α, it\n    also satisfies conventional differential privacy (ε, δ) as below:\n\n    .. math::\n        (ε'+\\frac{log(1/δ)}{α-1}, δ)\n\n    For details, please check `Tutorial <https://mindspore.cn/mindarmour/docs/zh-CN/master/protect_user_privacy_with_differential_privacy.html#%E5%B7%AE%E5%88%86%E9%9A%90%E7%A7%81>`_.\n\n    Reference: `Rényi Differential Privacy of the Sampled Gaussian Mechanism\n    <https://arxiv.org/abs/1908.10530>`_\n\n    Args:\n        num_samples (int): The total number of samples in training data sets.\n        batch_size (int): The number of samples in a batch while training.\n        initial_noise_multiplier (Union[float, int]): Ratio of the standard\n            deviation of Gaussian noise divided by the norm_bound, which will\n            be used to calculate privacy spent. Default: ``1.5``.\n        max_eps (Union[float, int, None]): The maximum acceptable epsilon\n            budget for DP training, which is used for estimating the max\n            training epochs. ``None`` means there is no limit to epsilon budget.\n            Default: ``10.0``.\n        target_delta (Union[float, int, None]): Target delta budget for DP\n            training. If target_delta is set to be δ, then the privacy budget\n            δ would be fixed during the whole training process. Default: ``1e-3``.\n        max_delta (Union[float, int, None]): The maximum acceptable delta\n            budget for DP training, which is used for estimating the max\n            training epochs. Max_delta must be less than 1 and suggested\n            to be less than 1e-3, otherwise overflow would be encountered.\n            'None' means there is no limit to delta budget. Default: ``None``.\n        target_eps (Union[float, int, None]): Target epsilon budget for DP\n            training. If target_eps is set to be ε, then the privacy budget\n            ε would be fixed during the whole training process. Default: ``None``.\n        orders (Union[None, list[int, float]]): Finite orders used for\n            computing rdp, which must be greater than 1. The computation result\n            of privacy budget would be different for various orders. In order\n            to obtain a tighter (smaller) privacy budget estimation, a list\n            of orders could be tried. Default: ``None``.\n        noise_decay_mode (Union[None, str]): Decay mode of adding noise while\n            training, which can be ``None``, ``'Time'``, ``'Step'`` or ``'Exp'``.\n            Default: ``'Time'``.\n        noise_decay_rate (float): Decay rate of noise while training. Default: ``6e-4``.\n        per_print_times　(int): The interval steps of computing and printing\n            the privacy budget. Default: ``50``.\n        dataset_sink_mode (bool): If ``True``, all training data would be passed\n            to device(Ascend) one-time. If ``False``, training data would be passed\n            to device after each step training. Default: ``False``.\n\n    Examples:\n        >>> from mindarmour.privacy.diff_privacy import PrivacyMonitorFactory\n        >>> rdp = PrivacyMonitorFactory.create(policy='rdp', num_samples=100, batch_size=32)\n    \"\"\"\n\n    def __init__(self, num_samples, batch_size, initial_noise_multiplier=1.5,\n                 max_eps=10.0, target_delta=1e-3, max_delta=None,\n                 target_eps=None, orders=None, noise_decay_mode='Time',\n                 noise_decay_rate=6e-4, per_print_times=50, dataset_sink_mode=False):\n        super(RDPMonitor, self).__init__()\n        check_int_positive('num_samples', num_samples)\n        check_int_positive('batch_size', batch_size)\n        if batch_size >= num_samples:\n            msg = 'Batch_size must be less than num_samples.'\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        check_value_positive('initial_noise_multiplier',\n                             initial_noise_multiplier)\n        if max_eps is not None:\n            check_value_positive('max_eps', max_eps)\n        if target_delta is not None:\n            check_value_positive('target_delta', target_delta)\n        if max_delta is not None:\n            check_value_positive('max_delta', max_delta)\n            if max_delta >= 1:\n                msg = 'max_delta must be less than 1.'\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n        if target_eps is not None:\n            check_value_positive('target_eps', target_eps)\n        if orders is not None:\n            for item in orders:\n                check_value_positive('order', item)\n                if item <= 1:\n                    msg = 'orders must be greater than 1'\n                    LOGGER.error(TAG, msg)\n                    raise ValueError(msg)\n        if noise_decay_mode is not None:\n            if noise_decay_mode not in ('Step', 'Time', 'Exp'):\n                msg = \"Noise decay mode must be in ('Step', 'Time', 'Exp')\"\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n            noise_decay_rate = check_param_type('noise_decay_rate', noise_decay_rate, float)\n            check_param_in_range('noise_decay_rate', noise_decay_rate, 0.0, 1.0)\n        check_int_positive('per_print_times', per_print_times)\n        check_param_type('dataset_sink_mode', dataset_sink_mode, bool)\n\n        self._num_samples = num_samples\n        self._batch_size = batch_size\n        self._initial_noise_multiplier = initial_noise_multiplier\n        self._max_eps = max_eps\n        self._target_delta = target_delta\n        self._max_delta = max_delta\n        self._target_eps = target_eps\n        self._orders = orders\n        self._noise_decay_mode = noise_decay_mode\n        self._noise_decay_rate = noise_decay_rate\n        self._rdp = 0\n        self._per_print_times = per_print_times\n        if self._target_eps is None and self._target_delta is None:\n            msg = 'target eps and target delta cannot both be None'\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n        if self._target_eps is not None and self._target_delta is not None:\n            msg = 'One of target eps and target delta must be None'\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n        if dataset_sink_mode:\n            self._per_print_times = int(self._num_samples / self._batch_size)\n\n    def max_epoch_suggest(self):\n        \"\"\"\n        Estimate the maximum training epochs to satisfy the predefined\n        privacy budget.\n\n        Returns:\n            int, the recommended maximum training epochs.\n        \"\"\"\n        if self._target_delta is not None and self._max_eps is None:\n            msg = 'max_eps should be consistent with target_delta, but got None.'\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        if self._target_eps is not None and self._max_delta is None:\n            msg = 'max_delta should be consistent with target_eps, but got None.'\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        epoch = 1\n        while epoch < 10000:\n            steps = self._num_samples // self._batch_size\n            eps, delta = self._compute_privacy_steps(\n                list(np.arange((epoch - 1)*steps, epoch*steps + 1)))\n            if self._max_eps is not None:\n                if eps <= self._max_eps:\n                    epoch += 1\n                else:\n                    break\n            if self._max_delta is not None:\n                if delta <= self._max_delta:\n                    epoch += 1\n                else:\n                    break\n        # reset the rdp for model training\n        self._rdp = 0\n        return epoch\n\n    def step_end(self, run_context):\n        \"\"\"\n        Compute privacy budget after each training step.\n\n        Args:\n            run_context (RunContext): Include some information of the model.\n        \"\"\"\n        cb_params = run_context.original_args()\n        cur_step = cb_params.cur_step_num\n        cur_step_in_epoch = (cb_params.cur_step_num - 1) % \\\n                            cb_params.batch_num + 1\n\n        if cb_params.cur_step_num % self._per_print_times == 0:\n            steps = np.arange(cur_step - self._per_print_times, cur_step + 1)\n            eps, delta = self._compute_privacy_steps(list(steps))\n            if np.isnan(eps) or np.isinf(eps):\n                msg = 'epoch: {} step: {}, invalid eps, terminating ' \\\n                      'training.'.format(\n                          cb_params.cur_epoch_num, cur_step_in_epoch)\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n            if np.isnan(delta) or np.isinf(delta):\n                msg = 'epoch: {} step: {}, invalid delta, terminating ' \\\n                      'training.'.format(\n                          cb_params.cur_epoch_num, cur_step_in_epoch)\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n            print(\"epoch: %s step: %s, delta is %s, eps is %s\" % (\n                cb_params.cur_epoch_num, cur_step_in_epoch, delta, eps))\n\n    def _compute_privacy_steps(self, steps):\n        \"\"\"\n        Compute privacy budget corresponding to steps.\n\n        Args:\n            steps (list): Training steps.\n\n        Returns:\n            float, privacy budget.\n        \"\"\"\n        if self._orders is None:\n            self._orders = (\n                [1.005, 1.01, 1.02, 1.08, 1.2, 2, 5, 10, 20, 40, 80])\n\n        sampling_rate = self._batch_size / self._num_samples\n        noise_stddev_step = self._initial_noise_multiplier\n\n        if self._noise_decay_mode is None:\n            self._rdp += self._compute_rdp(sampling_rate, noise_stddev_step)*len(\n                steps)\n        else:\n            if self._noise_decay_mode == 'Time':\n                noise_stddev_step = [self._initial_noise_multiplier / (\n                    1 + self._noise_decay_rate*step) for step in steps]\n\n            elif self._noise_decay_mode == 'Step':\n                noise_stddev_step = [self._initial_noise_multiplier*(\n                    1 - self._noise_decay_rate)**step for step in steps]\n            elif self._noise_decay_mode == 'Exp':\n                noise_stddev_step = [self._initial_noise_multiplier*np.exp(\n                    -step*self._noise_decay_rate) for step in steps]\n            self._rdp += sum(\n                [self._compute_rdp(sampling_rate, noise) for noise in\n                 noise_stddev_step])\n        eps, delta = self._compute_privacy_budget(self._rdp)\n\n        return eps, delta\n\n    def _compute_rdp(self, sample_rate, noise_stddev):\n        \"\"\"\n        Compute rdp according to sampling rate, added noise and Renyi\n        divergence orders.\n\n        Args:\n            sample_rate (float): Sampling rate of each batch of samples.\n            noise_stddev (float): Noise multiplier.\n\n        Returns:\n            float or numpy.ndarray, rdp values.\n        \"\"\"\n        rdp = np.array(\n            [_compute_rdp_with_order(sample_rate, noise_stddev, order) for order in self._orders])\n        return rdp\n\n    def _compute_privacy_budget(self, rdp):\n        \"\"\"\n        Compute delta or eps for given rdp.\n\n        Args:\n            rdp (Union[float, numpy.ndarray]): Renyi differential privacy.\n\n        Returns:\n            float, delta budget or eps budget.\n        \"\"\"\n        if self._target_eps is not None:\n            delta = self._compute_delta(rdp)\n            return self._target_eps, delta\n        eps = self._compute_eps(rdp)\n        return eps, self._target_delta\n\n    def _compute_delta(self, rdp):\n        \"\"\"\n        Compute delta for given rdp and eps.\n\n        Args:\n            rdp (Union[float, numpy.ndarray]): Renyi differential privacy.\n\n        Returns:\n            float, delta budget.\n        \"\"\"\n        orders = np.atleast_1d(self._orders)\n        rdps = np.atleast_1d(rdp)\n        deltas = np.exp((rdps - self._target_eps)*(orders - 1))\n        min_delta = np.min(deltas)\n        return np.min([min_delta, 1.])\n\n    def _compute_eps(self, rdp):\n        \"\"\"\n        Compute eps for given rdp and delta.\n\n        Args:\n            rdp (Union[float, numpy.ndarray]): Renyi differential privacy.\n\n        Returns:\n            float, eps budget.\n        \"\"\"\n        orders = np.atleast_1d(self._orders)\n        rdps = np.atleast_1d(rdp)\n        eps = rdps - np.log(self._target_delta) / (orders - 1)\n        return np.min(eps)\n\n\nclass ZCDPMonitor(Callback):\n    r\"\"\"\n    Compute the privacy budget of DP training based on zero-concentrated\n    differential privacy theory (zcdp). According to the reference below,\n    if a randomized mechanism is said to have ρ-ｚCDP, it also satisfies\n    conventional differential privacy (ε, δ) as below:\n\n    .. math::\n        (ρ+２\\sqrt{ρ*log(1/δ)}, δ)\n\n    It should be noted that ZCDPMonitor is not suitable for subsampling\n    noise mechanisms(such as NoiseAdaGaussianRandom and NoiseGaussianRandom).\n    The matching noise mechanism of ZCDP will be developed in the future.\n\n    For details, please check `Tutorial <https://mindspore.cn/mindarmour/docs/zh-CN/master/protect_user_privacy_with_differential_privacy.html#%E5%B7%AE%E5%88%86%E9%9A%90%E7%A7%81>`_.\n\n    Reference: `Concentrated Differentially Private Gradient Descent with\n    Adaptive per-Iteration Privacy Budget <https://arxiv.org/abs/1808.09501>`_\n\n    Args:\n        num_samples (int): The total number of samples in training data sets.\n        batch_size (int): The number of samples in a batch while training.\n        initial_noise_multiplier (Union[float, int]): Ratio of the standard\n            deviation of Gaussian noise divided by the norm_bound, which will\n            be used to calculate privacy spent. Default: ``1.5``.\n        max_eps (Union[float, int]): The maximum acceptable epsilon budget for\n            DP training, which is used for estimating the max training epochs.\n            Default: ``10.0``.\n        target_delta (Union[float, int]): Target delta budget for DP training.\n            If target_delta is set to be δ, then the privacy budget δ would be\n            fixed during the whole training process. Default: ``1e-3``.\n        noise_decay_mode (Union[None, str]): Decay mode of adding noise while\n            training, which can be ``None``, ``'Time'``, ``'Step'`` or ``'Exp'``.\n            Default: ``'Time'``.\n        noise_decay_rate (float): Decay rate of noise while training. Default: ``6e-4``.\n        per_print_times　(int): The interval steps of computing and printing\n            the privacy budget. Default: ``50``.\n        dataset_sink_mode (bool): If ``True``, all training data would be passed\n            to device(Ascend) one-time. If ``False``, training data would be passed\n            to device after each step training. Default: ``False``.\n\n    Examples:\n        >>> from mindarmour.privacy.diff_privacy import PrivacyMonitorFactory\n        >>> zcdp = PrivacyMonitorFactory.create(policy='zcdp',\n        ...                                     num_samples=100,\n        ...                                     batch_size=32,\n        ...                                     initial_noise_multiplier=1.5)\n    \"\"\"\n\n    def __init__(self, num_samples, batch_size, initial_noise_multiplier=1.5,\n                 max_eps=10.0, target_delta=1e-3, noise_decay_mode='Time',\n                 noise_decay_rate=6e-4, per_print_times=50, dataset_sink_mode=False):\n        super(ZCDPMonitor, self).__init__()\n        check_int_positive('num_samples', num_samples)\n        check_int_positive('batch_size', batch_size)\n        if batch_size >= num_samples:\n            msg = 'Batch_size must be less than num_samples.'\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        check_value_positive('initial_noise_multiplier',\n                             initial_noise_multiplier)\n        if noise_decay_mode is not None:\n            if noise_decay_mode not in ('Step', 'Time', 'Exp'):\n                msg = \"Noise decay mode must be in ('Step', 'Time', 'Exp'), but got {}.\".\\\n                    format(noise_decay_mode)\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n            noise_decay_rate = check_param_type('noise_decay_rate', noise_decay_rate, float)\n            check_param_in_range('noise_decay_rate', noise_decay_rate, 0.0, 1.0)\n        check_int_positive('per_print_times', per_print_times)\n        check_param_type('dataset_sink_mode', dataset_sink_mode, bool)\n\n        self._num_samples = num_samples\n        self._batch_size = batch_size\n        self._initial_noise_multiplier = initial_noise_multiplier\n        self._max_eps = check_value_positive('max_eps', max_eps)\n        self._target_delta = check_param_in_range('target_delta', target_delta, 0.0, 1.0)\n        self._noise_decay_mode = noise_decay_mode\n        self._noise_decay_rate = noise_decay_rate\n        # initialize zcdp\n        self._zcdp = 0\n        self._per_print_times = per_print_times\n        if dataset_sink_mode:\n            self._per_print_times = int(self._num_samples / self._batch_size)\n\n    def max_epoch_suggest(self):\n        \"\"\"\n        Estimate the maximum training epochs to satisfy the predefined\n        privacy budget.\n\n        Returns:\n            int, the recommended maximum training epochs.\n        \"\"\"\n        epoch = 1\n        while epoch < 10000:\n            steps = self._num_samples // self._batch_size\n            eps, _ = self._compute_privacy_steps(\n                list(np.arange((epoch - 1)*steps, epoch*steps + 1)))\n            if eps <= self._max_eps:\n                epoch += 1\n            else:\n                break\n\n        # initialize the zcdp for model training\n        self._zcdp = 0\n        return epoch\n\n    def step_end(self, run_context):\n        \"\"\"\n        Compute privacy budget after each training step.\n\n        Args:\n            run_context (RunContext): Include some information of the model.\n        \"\"\"\n        cb_params = run_context.original_args()\n        cur_step = cb_params.cur_step_num\n        cur_step_in_epoch = (cb_params.cur_step_num - 1) % \\\n                            cb_params.batch_num + 1\n\n        if cb_params.cur_step_num % self._per_print_times == 0:\n            steps = np.arange(cur_step - self._per_print_times, cur_step + 1)\n            eps, delta = self._compute_privacy_steps(list(steps))\n            if np.isnan(eps) or np.isinf(eps) or np.isnan(delta) or np.isinf(\n                    delta):\n                msg = 'epoch: {} step: {}, invalid eps, terminating ' \\\n                      'training.'.format(\n                          cb_params.cur_epoch_num, cur_step_in_epoch)\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n            print(\"epoch: %s step: %s, delta is %s, eps is %s\" % (\n                cb_params.cur_epoch_num, cur_step_in_epoch, delta, eps))\n\n    def _compute_privacy_steps(self, steps):\n        \"\"\"\n        Compute privacy budget corresponding to steps.\n\n        Args:\n            steps (list): Training steps.\n\n        Returns:\n            float, privacy budget.\n        \"\"\"\n        noise_stddev_step = self._initial_noise_multiplier\n\n        if self._noise_decay_mode is None:\n            self._zcdp += self._compute_zcdp(noise_stddev_step)*len(\n                steps)\n        else:\n            if self._noise_decay_mode == 'Time':\n                noise_stddev_step = [self._initial_noise_multiplier / (\n                    1 + self._noise_decay_rate*step) for step in steps]\n\n            elif self._noise_decay_mode == 'Step':\n                noise_stddev_step = [self._initial_noise_multiplier*(\n                    1 - self._noise_decay_rate)**step for step in steps]\n            elif self._noise_decay_mode == 'Exp':\n                noise_stddev_step = [self._initial_noise_multiplier*np.exp(\n                    -step*self._noise_decay_rate) for step in steps]\n            self._zcdp += sum(\n                [self._compute_zcdp(noise) for noise in noise_stddev_step])\n        eps = self._compute_eps(self._zcdp)\n\n        return eps, self._target_delta\n\n    def _compute_zcdp(self, noise_stddev):\n        \"\"\"\n        Compute zcdp according to added noise.\n\n        Args:\n            noise_stddev (float): Noise multiplier.\n\n        Returns:\n            float or numpy.ndarray, zcdp values.\n        \"\"\"\n        zcdp = 1 / (2*noise_stddev**2)\n        return zcdp\n\n    def _compute_eps(self, zcdp):\n        \"\"\"\n        Compute eps for given zcdp and delta.\n\n        Args:\n            zcdp (Union[float, numpy.ndarray]): zero-concentrated\n            differential privacy.\n\n        Returns:\n            float, eps budget.\n        \"\"\"\n        eps = zcdp + 2*np.sqrt(zcdp*np.log(1 / self._target_delta))\n        return eps\n\n\ndef _compute_rdp_with_order(sample_rate, noise_stddev, order):\n    \"\"\"\n    Compute rdp for each order.\n\n    Args:\n        sample_rate (float): Sampling probability.\n        noise_stddev (float): Noise multiplier.\n        order: The order used for computing rdp.\n\n    Returns:\n        float, rdp value.\n    \"\"\"\n    if float(order).is_integer():\n        log_integrate = -np.inf\n        for k in range(order + 1):\n            term_k = (np.log(\n                special.binom(order, k)) + k*np.log(sample_rate) + (\n                    order - k)*np.log(\n                        1 - sample_rate)) + (k*k - k) / (2*(noise_stddev**2))\n            log_integrate = _log_add(log_integrate, term_k)\n        return float(log_integrate) / (order - 1)\n    log_part_0, log_part_1 = -np.inf, -np.inf\n    k = 0\n    z0 = noise_stddev**2*np.log(1 / sample_rate - 1) + 1 / 2\n    while True:\n        bi_coef = special.binom(order, k)\n        log_coef = np.log(abs(bi_coef))\n        j = order - k\n\n        term_k_part_0 = log_coef + k*np.log(sample_rate) + j*np.log(1 - sample_rate) + (\n            k*k - k) / (2*(noise_stddev**2)) + special.log_ndtr(\n                (z0 - k) / noise_stddev)\n\n        term_k_part_1 = log_coef + j*np.log(sample_rate) + k*np.log(1 - sample_rate) + (\n            j*j - j) / (2*(noise_stddev**2)) + special.log_ndtr(\n                (j - z0) / noise_stddev)\n\n        if bi_coef > 0:\n            log_part_0 = _log_add(log_part_0, term_k_part_0)\n            log_part_1 = _log_add(log_part_1, term_k_part_1)\n        else:\n            log_part_0 = _log_subtract(log_part_0, term_k_part_0)\n            log_part_1 = _log_subtract(log_part_1, term_k_part_1)\n\n        k += 1\n        if np.max([term_k_part_0, term_k_part_1]) < -30:\n            break\n\n    return _log_add(log_part_0, log_part_1) / (order - 1)\n\n\ndef _log_add(x, y):\n    \"\"\"\n    Add x and y in log space.\n    \"\"\"\n    if x == -np.inf:\n        return y\n    if y == -np.inf:\n        return x\n    return np.max([x, y]) + np.log1p(np.exp(-abs(x - y)))\n\n\ndef _log_subtract(x, y):\n    \"\"\"\n    Subtract y from x in log space, x must be greater than y.\n    \"\"\"\n    if x <= y:\n        msg = 'The antilog of log functions must be positive'\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n    if y == -np.inf:\n        return x\n    return np.log1p(np.exp(y - x)) + x\n"
  },
  {
    "path": "mindarmour/privacy/diff_privacy/optimizer/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\ninit optimizer.\n\"\"\"\n"
  },
  {
    "path": "mindarmour/privacy/diff_privacy/optimizer/optimizer.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nDifferential privacy optimizer.\n\"\"\"\nfrom mindspore import nn\nfrom mindspore import Tensor\nfrom mindspore.ops import composite as C\nfrom mindspore.ops import operations as P\nfrom mindspore.ops import functional as F\nfrom mindspore.common import dtype as mstype\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_int_positive\nfrom ..mechanisms.mechanisms import NoiseMechanismsFactory\nfrom ..mechanisms.mechanisms import _MechanismsParamsUpdater\n\nLOGGER = LogUtil.get_instance()\nTAG = 'DP optimizer'\n\n_grad_scale = C.MultitypeFuncGraph(\"grad_scale\")\n_reciprocal = P.Reciprocal()\n\n\n@_grad_scale.register(\"Tensor\", \"Tensor\")\ndef tensor_grad_scale(scale, grad):\n    \"\"\" grad scaling \"\"\"\n    return grad * _reciprocal(scale)\n\n\nclass _TupleAdd(nn.Cell):\n    def __init__(self):\n        super(_TupleAdd, self).__init__()\n        self.add = P.Add()\n        self.hyper_map = C.HyperMap()\n\n    def construct(self, input1, input2):\n        \"\"\"Add two tuple of data.\"\"\"\n        out = self.hyper_map(self.add, input1, input2)\n        return out\n\n\nclass DPOptimizerClassFactory:\n    \"\"\"\n    Factory class of Optimizer.\n\n    Args:\n        micro_batches (int): The number of small batches split from an original batch.\n            Default: ``2``.\n\n    Returns:\n        Optimizer, Optimizer class.\n\n    Examples:\n        >>> from mindarmour.privacy.diff_privacy import DPOptimizerClassFactory\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._relu = nn.ReLU()\n        ...     def construct(self, inputs):\n        ...         out = self._relu(inputs)\n        ...         return out\n        >>> network = Net()\n        >>> GaussianSGD = DPOptimizerClassFactory(micro_batches=2)\n        >>> GaussianSGD.set_mechanisms('Gaussian', norm_bound=1.0, initial_noise_multiplier=1.5)\n        >>> net_opt = GaussianSGD.create('Momentum')(params=network.trainable_params(),\n        ...                                          learning_rate=0.001,\n        ...                                          momentum=0.9)\n    \"\"\"\n\n    def __init__(self, micro_batches=2):\n        self._mech_factory = NoiseMechanismsFactory()\n        self._mech = None\n        self._micro_batches = check_int_positive('micro_batches', micro_batches)\n\n    def set_mechanisms(self, policy, *args, **kwargs):\n        \"\"\"\n        Get noise mechanism object. Policies can be 'Gaussian' or 'AdaGaussian'.\n        Candidate args and kwargs can be seen in class NoiseMechanismsFactory of mechanisms.py.\n\n        Args:\n            policy (str): Choose mechanism type.\n        \"\"\"\n        self._mech = self._mech_factory.create(policy, *args, **kwargs)\n\n    def create(self, policy):\n        \"\"\"\n        Create DP optimizer. Policies can be 'sgd', 'momentum'\n        or 'adam'.\n\n        Args:\n            policy (str): Choose original optimizer type.\n\n        Returns:\n            Optimizer, an optimizer with DP.\n        \"\"\"\n        policy_ = policy.lower()\n        if policy_ == 'sgd':\n            dp_opt_class = self._get_dp_optimizer_class(nn.SGD)\n        elif policy_ == 'momentum':\n            dp_opt_class = self._get_dp_optimizer_class(nn.Momentum)\n        elif policy_ == 'adam':\n            dp_opt_class = self._get_dp_optimizer_class(nn.Adam)\n        else:\n            msg = \"The policy must be in ('SGD', 'Momentum', 'Adam'), but got {}.\" \\\n                .format(policy)\n            LOGGER.error(TAG, msg)\n            raise NameError(msg)\n        return dp_opt_class\n\n    def _get_dp_optimizer_class(self, opt_class):\n        \"\"\"\n        Wrap original mindspore optimizer with `self._mech`.\n        \"\"\"\n        if self._mech is None:\n            msg = 'Noise mechanism should be given through set_mechanisms(), but got None.'\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        mech = self._mech\n        micro_batches = self._micro_batches\n\n        class DPOptimizer(opt_class):\n            \"\"\"\n            Initialize the DPOptimizerClass.\n\n            Returns:\n                Optimizer, Optimizer class.\n            \"\"\"\n\n            def __init__(self, *args, **kwargs):\n                super(DPOptimizer, self).__init__(*args, **kwargs)\n                self._mech = mech\n                self._tuple_add = _TupleAdd()\n                self._hyper_map = C.HyperMap()\n                self._micro_batches = Tensor(micro_batches, mstype.float32)\n\n                self._mech_param_updater = None\n                if self._mech is not None and self._mech._decay_policy is not None:\n                    self._mech_param_updater = _MechanismsParamsUpdater(\n                        decay_policy=self._mech._decay_policy,\n                        decay_rate=self._mech._noise_decay_rate,\n                        cur_noise_multiplier=self._mech._noise_multiplier,\n                        init_noise_multiplier=self._mech._initial_noise_multiplier)\n\n            def construct(self, gradients):\n                \"\"\"\n                construct a compute flow.\n                \"\"\"\n                # generate noise\n                grad_noise_tuple = ()\n                for grad_item in gradients:\n                    grad_noise = self._mech(grad_item)\n                    grad_noise_tuple = grad_noise_tuple + (grad_noise,)\n                # add noise\n                gradients = self._tuple_add(gradients, grad_noise_tuple)\n                # div by self._micro_batches\n                gradients = self._hyper_map(F.partial(_grad_scale, self._micro_batches), gradients)\n                # update mech parameters\n                if self._mech_param_updater is not None:\n                    multiplier = self._mech_param_updater()\n                    gradients = F.depend(gradients, multiplier)\n                gradients = super(DPOptimizer, self).construct(gradients)\n                return gradients\n\n        return DPOptimizer\n"
  },
  {
    "path": "mindarmour/privacy/diff_privacy/train/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\ninit train.\n\"\"\"\n"
  },
  {
    "path": "mindarmour/privacy/diff_privacy/train/model.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nDifferential privacy model.\n\"\"\"\nfrom easydict import EasyDict as edict\n\nfrom mindspore.train.model import Model\nfrom mindspore.train import amp\nfrom mindspore.train.amp import _config_level\nfrom mindspore.common import dtype as mstype\nfrom mindspore.nn.wrap.cell_wrapper import _VirtualDatasetCell\nfrom mindspore.parallel._utils import _get_parallel_mode\nfrom mindspore.train.model import ParallelMode\nfrom mindspore.train.amp import _do_keep_batchnorm_fp32\nfrom mindspore.train.amp import _add_loss_network\nfrom mindspore import context\nfrom mindspore import nn\nfrom mindspore import Tensor\nfrom mindspore.ops import composite as C\nfrom mindspore.ops import operations as P\nfrom mindspore.ops import functional as F\nfrom mindspore.ops.operations import NPUGetFloatStatus\nfrom mindspore.ops.operations import NPUAllocFloatStatus\nfrom mindspore.ops.operations import NPUClearFloatStatus\nfrom mindspore.ops.operations import ReduceSum\nfrom mindspore.ops.operations import LessEqual\nfrom mindspore.parallel._utils import _get_gradients_mean\nfrom mindspore.parallel._utils import _get_device_num\nfrom mindspore.nn.wrap.grad_reducer import DistributedGradReducer\nfrom mindspore.common.parameter import Parameter\nfrom mindspore.nn.wrap.loss_scale import _grad_overflow\nfrom mindspore.nn import Cell\nfrom mindspore import ParameterTuple\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils import _check_param as validator\nfrom mindarmour.utils._check_param import check_value_positive, check_param_type\nfrom mindarmour.utils._check_param import check_int_positive, check, check_value_type\nfrom ..mechanisms.mechanisms import _MechanismsParamsUpdater\n\nLOGGER = LogUtil.get_instance()\nTAG = 'DP model'\n\n_grad_scale = C.MultitypeFuncGraph(\"grad_scale\")\n_reciprocal = P.Reciprocal()\n\n\n@_grad_scale.register(\"Tensor\", \"Tensor\")\ndef tensor_grad_scale(scale, grad):\n    \"\"\" grad scaling \"\"\"\n    return grad * F.cast(_reciprocal(scale), F.dtype(grad))\n\n\nclass DPModel(Model):\n    \"\"\"\n    DPModel is used for constructing a model for differential privacy training.\n    This class is overload mindspore.train.Model.\n\n    For details, please check `Protecting User Privacy with Differential Privacy Mechanism\n    <https://mindspore.cn/mindarmour/docs/en/master/protect_user_privacy_with_differential_privacy.html#%E5%B7%AE%E5%88%86%E9%9A%90%E7%A7%81>`_.\n\n    Args:\n        micro_batches (int): The number of small batches split from an original\n            batch. Default: ``2``.\n        norm_bound (float): The norm bound that is used to clip the gradient of\n         each sample. Default: ``1.0``.\n        noise_mech (Mechanisms): The object can generate the different type of\n            noise. Default: ``None``.\n        clip_mech (Mechanisms): The object is used to update the adaptive clip.\n            Default: ``None``.\n        optimizer (Cell): Optimizer used for differential privacy training, which can be original mindspore\n            optimizers (for example, Momentum optimizer) or optimizers generated by DPOptimizerClassFactory.\n            Default: ``nn.Momentum``.\n\n    Raises:\n        ValueError: If `optimizer` is ``None``.\n        ValueError: If `optimizer` is not DPOptimizer and `noise_mech` is ``None``.\n        ValueError: If `optimizer` is DPOptimizer and `noise_mech` is not ``None``.\n        ValueError: If `noise_mech` or DPOptimizer's mech method is adaptive while `clip_mech` is not ``None``.\n\n    \"\"\"\n\n    def __init__(self, micro_batches=2, norm_bound=1.0, noise_mech=None,\n                 clip_mech=None, optimizer=nn.Momentum, **kwargs):\n        if micro_batches:\n            self._micro_batches = check_int_positive('micro_batches',\n                                                     micro_batches)\n        else:\n            self._micro_batches = None\n        norm_bound = check_param_type('norm_bound', norm_bound, float)\n        norm_bound = check_value_positive('norm_bound', norm_bound)\n        norm_bound = Tensor(norm_bound, mstype.float32)\n        self._norm_bound = Parameter(norm_bound, 'norm_bound')\n        if optimizer is None:\n            msg = 'Optimizer need to be set, but got None.'\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        opt_name = optimizer.__class__.__name__\n        # Check whether noise_mech and DPOptimizer are both None or not None, if so, raise ValueError.\n        # And check whether noise_mech or DPOtimizer's mech method is adaptive while clip_mech is not None,\n        # if so, raise ValuerError too.\n        if noise_mech is not None and \"DPOptimizer\" in opt_name:\n            msg = 'DPOptimizer is not supported while noise_mech is not None'\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        if noise_mech is None:\n            if \"DPOptimizer\" in opt_name:\n                if 'Ada' in optimizer._mech.__class__.__name__ and clip_mech is not None:\n                    msg = \"When DPOptimizer's mech method is adaptive, clip_mech must be None.\"\n                    LOGGER.error(TAG, msg)\n                    raise ValueError(msg)\n            else:\n                msg = 'DPModel should set noise_mech or DPOptimizer configure, ' \\\n                      'please refer to example.'\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n        self._noise_mech = noise_mech\n        if noise_mech is not None:\n            if 'Ada' in noise_mech.__class__.__name__ and clip_mech is not None:\n                msg = 'When noise_mech is Adaptive, clip_mech must be None.'\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n\n        if clip_mech is None or isinstance(clip_mech, Cell):\n            self._clip_mech = clip_mech\n        super(DPModel, self).__init__(optimizer=optimizer, **kwargs)\n\n        # judge device_target, only GPU or Ascend is supported until now\n        device = context.get_context(\"device_target\")\n        if device not in [\"GPU\", \"Ascend\"]:\n            msg = \"'device_target' for DP training should be 'GPU' or 'Ascend', but got {}.\".format(device)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n    def _amp_build_train_network(self, network, optimizer, loss_fn=None,\n                                 level='O0', **kwargs):\n        \"\"\"\n        Build the mixed precision training cell automatically.\n\n        Args:\n            network (Cell): Definition of the network.\n            loss_fn (Union[None, Cell]): Definition of the loss_fn. If None,\n                the `network` should have the loss inside. Default: ``None``.\n            optimizer (Optimizer): Optimizer to update the Parameter.\n            level (str): Supports [O0, O2]. Default: \"O0\".\n\n                - O0: Do not change.\n                - O2: Cast network to float16, keep batchnorm and `loss_fn`\n                  (if set) run in float32, using dynamic loss scale.\n\n            cast_model_type (:class:`mindspore.dtype`): Supports `mstype.float16`\n                or `mstype.float32`. If set to `mstype.float16`, use `float16`\n                mode to train. If set, overwrite the level setting.\n            keep_batchnorm_fp32 (bool): Keep Batchnorm run in `float32`. If set,\n                overwrite the level setting.\n            loss_scale_manager (Union[None, LossScaleManager]): If None, not\n                scale the loss, or else scale the loss by LossScaleManager.\n                If set, overwrite the level setting.\n        \"\"\"\n        check_value_type('network', network, nn.Cell, None)\n        check_value_type('optimizer', optimizer, nn.Optimizer, None)\n        check('level', level, \"\", ['O0', 'O2'], validator.IN, None)\n        self._check_kwargs(kwargs)\n        config = dict(_config_level[level], **kwargs)\n        config = edict(config)\n\n        if config.cast_model_type == mstype.float16:\n            network.to_float(mstype.float16)\n\n            if config.keep_batchnorm_fp32:\n                _do_keep_batchnorm_fp32(network)\n\n        if loss_fn:\n            network = _add_loss_network(network, loss_fn,\n                                        config.cast_model_type)\n\n        if _get_parallel_mode() in (\n                ParallelMode.SEMI_AUTO_PARALLEL, ParallelMode.AUTO_PARALLEL):\n            network = _VirtualDatasetCell(network)\n\n        loss_scale = 1.0\n        if config.loss_scale_manager is not None:\n            loss_scale_manager = config.loss_scale_manager\n            loss_scale = loss_scale_manager.get_loss_scale()\n            update_cell = loss_scale_manager.get_update_cell()\n            if update_cell is not None:\n                # only cpu not support `TrainOneStepWithLossScaleCell` for control flow.\n                if not context.get_context(\"enable_ge\") and context.get_context(\n                        \"device_target\") == \"CPU\":\n                    msg = \"Only `loss_scale_manager=None` and \" \\\n                          \"`loss_scale_manager=FixedLossScaleManager(drop_overflow\" \\\n                          \"_update=False)` are supported in current version. \" \\\n                          \"If you use `O2` option, please use \" \\\n                          \"`loss_scale_manager=None` or `FixedLossScaleManager`\"\n                    LOGGER.error(TAG, msg)\n                    raise ValueError(msg)\n                network = _TrainOneStepWithLossScaleCell(network,\n                                                         optimizer,\n                                                         scale_update_cell=update_cell,\n                                                         micro_batches=self._micro_batches,\n                                                         norm_bound=self._norm_bound,\n                                                         clip_mech=self._clip_mech,\n                                                         noise_mech=self._noise_mech).set_train()\n                return network\n\n        network = _TrainOneStepCell(network,\n                                    optimizer,\n                                    self._norm_bound,\n                                    loss_scale,\n                                    micro_batches=self._micro_batches,\n                                    clip_mech=self._clip_mech,\n                                    noise_mech=self._noise_mech).set_train()\n        return network\n\n    def _build_train_network(self):\n        \"\"\"Build train network\"\"\"\n        network = self._network\n        if self._micro_batches:\n            if self._optimizer:\n                if self._loss_scale_manager_set:\n                    network = self._amp_build_train_network(network,\n                                                            self._optimizer,\n                                                            self._loss_fn,\n                                                            level=self._amp_level,\n                                                            loss_scale_manager=self._loss_scale_manager,\n                                                            keep_batchnorm_fp32=self._keep_bn_fp32)\n                else:\n                    network = self._amp_build_train_network(network,\n                                                            self._optimizer,\n                                                            self._loss_fn,\n                                                            level=self._amp_level,\n                                                            keep_batchnorm_fp32=self._keep_bn_fp32)\n            elif self._loss_fn:\n                network = nn.WithLossCell(network, self._loss_fn)\n        else:\n            if self._optimizer:\n                if self._loss_scale_manager_set:\n                    network = amp.build_train_network(network,\n                                                      self._optimizer,\n                                                      self._loss_fn,\n                                                      level=self._amp_level,\n                                                      loss_scale_manager=self._loss_scale_manager,\n                                                      keep_batchnorm_fp32=self._keep_bn_fp32)\n                else:\n                    network = amp.build_train_network(network,\n                                                      self._optimizer,\n                                                      self._loss_fn,\n                                                      level=self._amp_level,\n                                                      keep_batchnorm_fp32=self._keep_bn_fp32)\n            elif self._loss_fn:\n                network = nn.WithLossCell(network, self._loss_fn)\n\n        if self._parallel_mode in (ParallelMode.SEMI_AUTO_PARALLEL,\n                                   ParallelMode.AUTO_PARALLEL):\n            network.set_auto_parallel()\n        return network\n\n\nclass _ClipGradients(nn.Cell):\n    \"\"\"\n    Clip gradients.\n\n    Inputs:\n        grads (tuple[Tensor]): Gradients to clip.\n        clip_norm (float): The l2-norm bound used to clip the gradients.\n        cur_norm (float): The l2-norm of grads. If None, the norm will be\n            calculated in this function. Default: ``None``.\n\n    Outputs:\n        tuple[Tensor], clipped gradients.\n    \"\"\"\n\n    def __init__(self):\n        super(_ClipGradients, self).__init__()\n        self._add = P.Add()\n        self._reduce_sum = P.ReduceSum()\n        self._square_all = P.Square()\n        self._sqrt = P.Sqrt()\n\n    def construct(self, grads, clip_norm, cur_norm=None):\n        \"\"\"\n        construct a compute flow.\n        \"\"\"\n        if cur_norm is None:\n            # calculate current l2-norm of grads\n            square_sum = Tensor(0, mstype.float32)\n            for grad in grads:\n                square_sum = self._add(square_sum, self._reduce_sum(self._square_all(grad)))\n            cur_norm = self._sqrt(square_sum)\n\n        if cur_norm <= clip_norm:\n            return grads\n\n        new_grads = ()\n        for grad in grads:\n            clipped_grad = grad * (clip_norm / cur_norm)\n            new_grads = new_grads + (clipped_grad,)\n        return new_grads\n\n\nclass _TupleAdd(nn.Cell):\n    def __init__(self):\n        super(_TupleAdd, self).__init__()\n        self.add = P.Add()\n        self.hyper_map = C.HyperMap()\n\n    def construct(self, input1, input2):\n        \"\"\"Add two tuple of data.\"\"\"\n        out = self.hyper_map(self.add, input1, input2)\n        return out\n\n\nclass _TrainOneStepWithLossScaleCell(Cell):\n    r\"\"\"\n    Network training with loss scaling.\n\n    This is a training step with loss scaling. It takes a network, an optimizer\n    and possibly a scale update Cell as args. The loss scale value can be\n    updated in both host side or device side. The TrainOneStepWithLossScaleCell\n    will be compiled to be graph which takes `data`, `label`, `sens` as input\n    data. The `sens` is acting as loss scaling value. If you want to update it\n    on host side, the value should be provided. If `sens` is not given, the loss\n    scale update logic should be provied by `scale_update_cell`. If\n    `scale_update_cell` is not None and `sens` is provided, the\n    `scale_update_cell` will be ignored.\n\n    Args:\n        network (Cell): The training network.\n        optimizer (Cell): Optimizer for updating the weights.\n        scale_update_cell(Cell): The loss scaling update logic cell.\n            Default: ``None``.\n        micro_batches (int): The number of small batches split from an original\n            batch. Default: ``None``.\n        norm_bound (Tensor): The norm bound that is used to clip the gradient of\n         each sample. Default: 1.0.\n        noise_mech (Mechanisms): The object can generate the different type of\n            noise. Default: ``None``.\n\n    Inputs:\n        - **inputs** (Tensor) - Tensor of shape :math:`(N, \\ldots)`.\n        - **label** (Tensor) - Tensor of shape :math:`(N, \\ldots)`.\n        - **scaling_sens** (Tensor) - Tensor of shape :math:`()`.\n\n    Outputs:\n        Tuple of 3 Tensor, the loss, overflow flag and current loss scaling value.\n\n        - **loss** (Tensor) -  Tensor with shape :math:`()`.\n        - **overflow** (Tensor) -  Tensor with shape :math:`()`, type is bool.\n        - **loss_scale** (Tensor) -  Tensor with shape :math:`()`.\n    \"\"\"\n\n    def __init__(self, network, optimizer, scale_update_cell=None,\n                 micro_batches=None, norm_bound=1.0, noise_mech=None,\n                 clip_mech=None):\n        super(_TrainOneStepWithLossScaleCell, self).__init__(auto_prefix=False)\n        self.network = network\n        self.network.set_grad()\n        self.network.add_flags(defer_inline=True)\n        self.weights = ParameterTuple(network.trainable_params())\n        self.optimizer = optimizer\n        self.grad = C.GradOperation(get_by_list=True, sens_param=True)\n        self.hyper_map = C.HyperMap()\n        if context.get_context(\"device_target\") == \"GPU\":\n            self.gpu_target = True\n            self.float_status = P.FloatStatus()\n            self.addn = P.AddN()\n            self.reshape = P.Reshape()\n        else:\n            self.gpu_target = False\n            self.alloc_status = NPUAllocFloatStatus()\n            self.get_status = NPUGetFloatStatus()\n            self.clear_status = NPUClearFloatStatus()\n        self.reduce_sum = ReduceSum(keep_dims=False)\n        self.base = Tensor(1, mstype.float32)\n        self.less_equal = LessEqual()\n        self.allreduce = P.AllReduce()\n        self.parallel_mode = _get_parallel_mode()\n        self.grad_reducer = F.identity\n        self.reducer_flag = self.parallel_mode in [ParallelMode.DATA_PARALLEL,\n                                                   ParallelMode.HYBRID_PARALLEL]\n        if self.reducer_flag:\n            mean = _get_gradients_mean()\n            degree = _get_device_num()\n            self.grad_reducer = DistributedGradReducer(optimizer.parameters,\n                                                       mean, degree)\n        self.is_distributed = self.parallel_mode != ParallelMode.STAND_ALONE\n\n        self.loss_scale = None\n        self.loss_scaling_manager = scale_update_cell\n        if scale_update_cell:\n            self.loss_scale = Parameter(Tensor(scale_update_cell.get_loss_scale(), dtype=mstype.float32),\n                                        name=\"loss_scale\")\n        self.add_flags(has_effect=True)\n\n        # dp params\n        self._micro_batches = micro_batches\n        self._norm_bound = norm_bound\n        self._split = P.Split(0, self._micro_batches)\n        self._clip_by_global_norm = _ClipGradients()\n        self._noise_mech = noise_mech\n        self._clip_mech = clip_mech\n        self._add = P.Add()\n        self._norm = nn.Norm()\n        self._tuple_add = _TupleAdd()\n        self._hyper_map = C.HyperMap()\n        self._micro_float = Tensor(micro_batches, mstype.float32)\n        self._zero = Tensor(0, mstype.float32)\n        self._assign = P.Assign()\n        self._div = P.Div()\n        self._sqrt = P.Sqrt()\n        self._reduce_sum = P.ReduceSum()\n        self._square_all = P.Square()\n        self._less = P.Less()\n        self._cast = P.Cast()\n\n        self._noise_mech_param_updater = None\n        if self._noise_mech is not None and self._noise_mech._decay_policy is not None:\n            self._noise_mech_param_updater = _MechanismsParamsUpdater(\n                decay_policy=self._noise_mech._decay_policy,\n                decay_rate=self._noise_mech._noise_decay_rate,\n                cur_noise_multiplier=self._noise_mech._noise_multiplier,\n                init_noise_multiplier=self._noise_mech._initial_noise_multiplier)\n\n    def construct(self, data, label, sens=None):\n        \"\"\"\n        construct a compute flow.\n        \"\"\"\n        init = False\n        if not self.gpu_target:\n            # init overflow buffer\n            init = self.alloc_status()\n            # clear overflow buffer\n            self.clear_status(init)\n\n        if sens is None:\n            scaling_sens = self.loss_scale\n        else:\n            scaling_sens = sens\n\n        # DP clip\n        weights = self.weights\n        record_datas = self._split(data)\n        record_labels = self._split(label)\n        # first index\n        loss = self.network(record_datas[0], record_labels[0])\n        scaling_sens_filled = C.ones_like(loss) * F.cast(scaling_sens,\n                                                         F.dtype(loss))\n        record_grad = self.grad(self.network, weights)(record_datas[0],\n                                                       record_labels[0],\n                                                       scaling_sens_filled)\n\n        beta = self._zero\n        square_sum = self._zero\n        for grad in record_grad:\n            square_sum = self._add(square_sum,\n                                   self._reduce_sum(self._square_all(grad)))\n        norm_grad = self._sqrt(square_sum)\n        beta = self._add(beta,\n                         self._cast(self._less(norm_grad, self._norm_bound),\n                                    mstype.float32))\n        record_grad = self._clip_by_global_norm(record_grad,\n                                                self._norm_bound, norm_grad)\n        grads = record_grad\n        total_loss = loss\n        for i in range(1, self._micro_batches):\n            loss = self.network(record_datas[i], record_labels[i])\n            scaling_sens_filled = C.ones_like(loss) * F.cast(scaling_sens,\n                                                             F.dtype(loss))\n            record_grad = self.grad(self.network, weights)(record_datas[i],\n                                                           record_labels[i],\n                                                           scaling_sens_filled)\n\n            square_sum = self._zero\n            for grad in record_grad:\n                square_sum = self._add(square_sum,\n                                       self._reduce_sum(self._square_all(grad)))\n            norm_grad = self._sqrt(square_sum)\n            beta = self._add(beta,\n                             self._cast(self._less(norm_grad, self._norm_bound),\n                                        mstype.float32))\n\n            record_grad = self._clip_by_global_norm(record_grad,\n                                                    self._norm_bound, norm_grad)\n            grads = self._tuple_add(grads, record_grad)\n            total_loss = P.Add()(total_loss, loss)\n        loss = P.Div()(total_loss, self._micro_float)\n        beta = self._div(beta, self._micro_batches)\n\n        if self._noise_mech is not None:\n            grad_noise_tuple = ()\n            for grad_item in grads:\n                grad_noise = self._noise_mech(grad_item)\n                grad_noise_tuple = grad_noise_tuple + (grad_noise,)\n            grads = self._tuple_add(grads, grad_noise_tuple)\n            grads = self._hyper_map(F.partial(_grad_scale, self._micro_float),\n                                    grads)\n            # update mech parameters\n\n            if self._noise_mech_param_updater is not None:\n                multiplier = self._noise_mech_param_updater()\n                loss = F.depend(loss, multiplier)\n\n        grads = self.hyper_map(F.partial(_grad_scale, scaling_sens), grads)\n        # apply grad reducer on grads\n        grads = self.grad_reducer(grads)\n        # get the overflow buffer\n        if not self.gpu_target:\n            self.get_status(init)\n            # sum overflow buffer elements, 0:not overflow , >0:overflow\n            flag_sum = self.reduce_sum(init, (0,))\n        else:\n            flag_sum = self.hyper_map(F.partial(_grad_overflow), grads)\n            flag_sum = self.addn(flag_sum)\n            # convert flag_sum to scalar\n            flag_sum = self.reshape(flag_sum, (()))\n        if self.is_distributed:\n            # sum overflow flag over devices\n            flag_reduce = self.allreduce(flag_sum)\n            cond = self.less_equal(self.base, flag_reduce)\n        else:\n            cond = self.less_equal(self.base, flag_sum)\n        overflow = cond\n        if sens is None:\n            overflow = self.loss_scaling_manager(self.loss_scale, cond)\n        # if there is no overflow, do optimize\n        if overflow:\n            opt = False\n        else:\n            opt = self.optimizer(grads)\n        ret = (loss, cond, scaling_sens)\n\n        if self._clip_mech is not None:\n            next_norm_bound = self._clip_mech(beta, self._norm_bound)\n            P.assign(self._norm_bound, next_norm_bound)\n        return F.depend(ret, opt)\n\n\nclass _TrainOneStepCell(Cell):\n    r\"\"\"\n    Network training package class.\n\n    Wraps the network with an optimizer. The resulting Cell be trained with\n    input data and label. Backward graph will be created in the construct\n    function to do parameter updating. Different parallel modes are available\n    to run the training.\n\n    Args:\n        network (Cell): The training network.\n        optimizer (Cell): Optimizer for updating the weights.\n        sens (Number): The scaling number to be filled as the input of back\n            propagation. Default value is 1.0.\n        micro_batches (int): The number of small batches split from an original\n            batch. Default: ``None``.\n        norm_bound (Tensor): The norm bound that is used to clip the gradient of\n         each sample. Default: 1.0.\n        noise_mech (Mechanisms): The object can generate the different type\n            of noise. Default: ``None``.\n        clip_mech (Mechanisms): The object is used to update the adaptive clip.\n            Default: ``None``.\n\n    Inputs:\n        - **data** (Tensor) - Tensor of shape :math:`(N, \\ldots)`.\n        - **label** (Tensor) - Tensor of shape :math:`(N, \\ldots)`.\n\n    Outputs:\n        Tensor, a scalar Tensor with shape :math:`()`.\n    \"\"\"\n\n    def __init__(self, network, optimizer, norm_bound=1.0, sens=1.0,\n                 micro_batches=None,\n                 noise_mech=None, clip_mech=None):\n        super(_TrainOneStepCell, self).__init__(auto_prefix=False)\n        self.network = network\n        self.network.set_grad()\n        self.network.add_flags(defer_inline=True)\n        self.weights = optimizer.parameters\n        self.optimizer = optimizer\n        self.grad = C.GradOperation(get_by_list=True, sens_param=True)\n        self.sens = sens\n        self.reducer_flag = False\n        self.grad_reducer = None\n        parallel_mode = _get_parallel_mode()\n        if parallel_mode in (\n                ParallelMode.DATA_PARALLEL, ParallelMode.HYBRID_PARALLEL):\n            self.reducer_flag = True\n        if self.reducer_flag:\n            mean = _get_gradients_mean()\n            degree = _get_device_num()\n            self.grad_reducer = DistributedGradReducer(optimizer.parameters,\n                                                       mean, degree)\n\n        # dp params\n        if micro_batches is None:\n            msg = 'micro_batches must give in differential privacy, but got value: {}'.format(\n                micro_batches)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        self._micro_batches = micro_batches\n        self._norm_bound = norm_bound\n        self._split = P.Split(0, self._micro_batches)\n        self._clip_by_global_norm = _ClipGradients()\n        self._noise_mech = noise_mech\n        self._clip_mech = clip_mech\n        self._tuple_add = _TupleAdd()\n        self._add = P.Add()\n        self._norm = nn.Norm()\n        self._hyper_map = C.HyperMap()\n        self._zero = Tensor(0, mstype.float32)\n        self._assign = P.Assign()\n        self._div = P.Div()\n        self._sqrt = P.Sqrt()\n        self._reduce_sum = P.ReduceSum()\n        self._square_all = P.Square()\n        self._less = P.Less()\n        self._cast = P.Cast()\n\n        self._micro_float = Tensor(micro_batches, mstype.float32)\n\n        self._noise_mech_param_updater = None\n        if self._noise_mech is not None and self._noise_mech._decay_policy is not None:\n            self._noise_mech_param_updater = _MechanismsParamsUpdater(\n                decay_policy=self._noise_mech._decay_policy,\n                decay_rate=self._noise_mech._noise_decay_rate,\n                cur_noise_multiplier=self._noise_mech._noise_multiplier,\n                init_noise_multiplier=self._noise_mech._initial_noise_multiplier)\n\n    def construct(self, data, label):\n        \"\"\"\n        construct a compute flow.\n        \"\"\"\n        weights = self.weights\n        record_datas = self._split(data)\n        record_labels = self._split(label)\n        loss = self.network(record_datas[0], record_labels[0])\n        sens = P.Fill()(P.DType()(loss), P.Shape()(loss), self.sens)\n        record_grad = self.grad(self.network, weights)(record_datas[0],\n                                                       record_labels[0], sens)\n\n        # calcu norm_grad\n        square_sum = self._zero\n        for grad in record_grad:\n            square_sum = self._add(square_sum, self._reduce_sum(self._square_all(grad)))\n        norm_grad = self._sqrt(square_sum)\n\n        # calcu beta\n        beta = self._zero\n        if self._clip_mech is not None:\n            beta = self._add(beta,\n                             self._cast(self._less(norm_grad, self._norm_bound),\n                                        mstype.float32))\n\n        record_grad = self._clip_by_global_norm(record_grad,\n                                                self._norm_bound, norm_grad)\n        grads = record_grad\n        total_loss = loss\n        for i in range(1, self._micro_batches):\n            loss = self.network(record_datas[i], record_labels[i])\n            sens = P.Fill()(P.DType()(loss), P.Shape()(loss), self.sens)\n            record_grad = self.grad(self.network, weights)(record_datas[i],\n                                                           record_labels[i],\n                                                           sens)\n\n            # calcu norm_grad\n            square_sum = self._zero\n            for grad in record_grad:\n                square_sum = self._add(square_sum,\n                                       self._reduce_sum(self._square_all(grad)))\n            norm_grad = self._sqrt(square_sum)\n\n            # calcu beta\n            if self._clip_mech is not None:\n                beta = self._add(beta,\n                                 self._cast(self._less(norm_grad, self._norm_bound),\n                                            mstype.float32))\n\n            record_grad = self._clip_by_global_norm(record_grad,\n                                                    self._norm_bound, norm_grad)\n            grads = self._tuple_add(grads, record_grad)\n            total_loss = P.Add()(total_loss, loss)\n        loss = self._div(total_loss, self._micro_float)\n\n        if self._noise_mech is not None:\n            grad_noise_tuple = ()\n            for grad_item in grads:\n                grad_noise = self._noise_mech(grad_item)\n                grad_noise_tuple = grad_noise_tuple + (grad_noise,)\n            grads = self._tuple_add(grads, grad_noise_tuple)\n            grads = self._hyper_map(F.partial(_grad_scale, self._micro_float),\n                                    grads)\n            # update mech parameters\n            if self._noise_mech_param_updater is not None:\n                multiplier = self._noise_mech_param_updater()\n                loss = F.depend(loss, multiplier)\n\n        if self.reducer_flag:\n            # apply grad reducer on grads\n            grads = self.grad_reducer(grads)\n\n        if self._clip_mech is not None:\n            beta = self._div(beta, self._micro_batches)\n            next_norm_bound = self._clip_mech(beta, self._norm_bound)\n            self._norm_bound = self._assign(self._norm_bound, next_norm_bound)\n            loss = F.depend(loss, self._norm_bound)\n\n        return F.depend(loss, self.optimizer(grads))\n"
  },
  {
    "path": "mindarmour/privacy/evaluation/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis module provides some methods to evaluate the risk of privacy leakage of\ngiven model.\n\"\"\"\n\nfrom .membership_inference import MembershipInference\nfrom .inversion_attack import ImageInversionAttack\nfrom .model_inversion_attack import ModelInversionAttack\nfrom .shadow_model_attack import ShadowModelAttack\n__all__ = ['MembershipInference', 'ImageInversionAttack', 'ModelInversionAttack', 'ShadowModelAttack']\n"
  },
  {
    "path": "mindarmour/privacy/evaluation/_check_config.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nVerify attack config\n\"\"\"\n\nimport numpy as np\n\nfrom mindarmour.utils._check_param import check_param_type\nfrom mindarmour.utils.logger import LogUtil\n\nLOGGER = LogUtil.get_instance()\n\nTAG = \"check_config\"\n\n\ndef _is_positive_int(item):\n    \"\"\"Verify that the value is a positive integer.\"\"\"\n    if not isinstance(item, int):\n        return False\n    return item > 0\n\n\ndef _is_non_negative_int(item):\n    \"\"\"Verify that the value is a non-negative integer.\"\"\"\n    if not isinstance(item, int):\n        return False\n    return item >= 0\n\n\ndef _is_positive_float(item):\n    \"\"\"Verify that value is a positive number.\"\"\"\n    if not isinstance(item, (int, float)):\n        return False\n    return item > 0\n\n\ndef _is_non_negative_float(item):\n    \"\"\"Verify that value is a non-negative number.\"\"\"\n    if not isinstance(item, (int, float)):\n        return False\n    return item >= 0\n\n\ndef _is_range_0_1_float(item):\n    if not isinstance(item, (int, float)):\n        return False\n    return 0 <= item < 1\n\n\ndef _is_positive_int_tuple(item):\n    \"\"\"Verify that the input parameter is a positive integer tuple.\"\"\"\n    if not isinstance(item, tuple):\n        return False\n    for i in item:\n        if not _is_positive_int(i):\n            return False\n    return True\n\n\ndef _is_dict(item):\n    \"\"\"Check whether the type is dict.\"\"\"\n    return isinstance(item, dict)\n\n\ndef _is_list(item):\n    \"\"\"Check whether the type is list\"\"\"\n    return isinstance(item, list)\n\n\ndef _is_str(item):\n    \"\"\"Check whether the type is str.\"\"\"\n    return isinstance(item, str)\n\n\n_VALID_CONFIG_CHECKLIST = {\n    \"knn\": {\n        \"n_neighbors\": [_is_positive_int],\n        \"weights\": [{\"uniform\", \"distance\"}, callable],\n        \"algorithm\": [{\"auto\", \"ball_tree\", \"kd_tree\", \"brute\"}],\n        \"leaf_size\": [_is_positive_int],\n        \"p\": [_is_positive_int],\n        \"metric\": [_is_str, callable],\n        \"metric_params\": [_is_dict, {None}]\n    },\n    \"lr\": {\n        \"penalty\": [{\"l1\", \"l2\", \"elasticnet\", \"none\"}],\n        \"dual\": [{True, False}],\n        \"tol\": [_is_positive_float],\n        \"C\": [_is_positive_float],\n        \"fit_intercept\": [{True, False}],\n        \"intercept_scaling\": [_is_positive_float],\n        \"class_weight\": [{\"balanced\", None}, _is_dict],\n        \"random_state\": None,\n        \"solver\": [{\"newton-cg\", \"lbfgs\", \"liblinear\", \"sag\", \"saga\"}]\n    },\n    \"mlp\": {\n        \"hidden_layer_sizes\": [_is_positive_int_tuple],\n        \"activation\": [{\"identity\", \"logistic\", \"tanh\", \"relu\"}],\n        \"solver\": [{\"lbfgs\", \"sgd\", \"adam\"}],\n        \"alpha\": [_is_positive_float],\n        \"batch_size\": [{\"auto\"}, _is_positive_int],\n        \"learning_rate\": [{\"constant\", \"invscaling\", \"adaptive\"}],\n        \"learning_rate_init\": [_is_positive_float],\n        \"power_t\": [_is_positive_float],\n        \"max_iter\": [_is_positive_int],\n        \"shuffle\": [{True, False}],\n        \"random_state\": None,\n        \"tol\": [_is_positive_float],\n        \"verbose\": [{True, False}],\n        \"warm_start\": [{True, False}],\n        \"momentum\": [_is_positive_float],\n        \"nesterovs_momentum\": [{True, False}],\n        \"early_stopping\": [{True, False}],\n        \"validation_fraction\": [_is_range_0_1_float],\n        \"beta_1\": [_is_range_0_1_float],\n        \"beta_2\": [_is_range_0_1_float],\n        \"epsilon\": [_is_positive_float],\n        \"n_iter_no_change\": [_is_positive_int],\n        \"max_fun\": [_is_positive_int]\n    },\n    \"rf\": {\n        \"n_estimators\": [_is_positive_int],\n        \"criterion\": [{\"gini\", \"entropy\"}],\n        \"max_depth\": [{None}, _is_positive_int],\n        \"min_samples_split\": [_is_positive_float],\n        \"min_samples_leaf\": [_is_positive_float],\n        \"min_weight_fraction_leaf\": [_is_non_negative_float],\n        \"max_features\": [{\"auto\", \"sqrt\", \"log2\", None}, _is_positive_float],\n        \"max_leaf_nodes\": [_is_positive_int, {None}],\n        \"min_impurity_decrease\": [_is_non_negative_float],\n        \"min_impurity_split\": [{None}, _is_positive_float],\n        \"bootstrap\": [{True, False}],\n        \"n_jobs\": [_is_positive_int, {None}],\n        \"random_state\": None,\n        \"verbose\": [_is_non_negative_int],\n        \"warm_start\": [{True, False}],\n        \"class_weight\": [{\"balanced\", \"balanced_subsample\"}, _is_dict, _is_list],\n        \"ccp_alpha\": [_is_non_negative_float],\n        \"max_samples\": [{None}, _is_positive_int, _is_range_0_1_float]\n    }\n}\n\n\ndef _check_config(attack_config, config_checklist):\n    \"\"\"\n    Verify that config_list is valid.\n    Check_params is the valid value range of the parameter.\n    \"\"\"\n    for config in attack_config:\n        check_param_type(\"config\", config, dict)\n        if set(config.keys()) != {\"params\", \"method\"}:\n            msg = \"Keys of each config in attack_config must be {},\" \\\n                  \"but got {}.\".format({'method', 'params'}, set(config.keys()))\n            LOGGER.error(TAG, msg)\n            raise KeyError(msg)\n\n        method = str.lower(config[\"method\"])\n        params = config[\"params\"]\n\n        if method not in config_checklist.keys():\n            msg = \"Method {} is not supported.\".format(method)\n            LOGGER.error(TAG, msg)\n            raise NameError(msg)\n\n        if not params.keys() <= config_checklist[method].keys():\n            msg = \"Params in method {} is not accepted, the parameters \" \\\n                  \"that can be set are {}.\".format(method, set(config_checklist[method].keys()))\n\n            LOGGER.error(TAG, msg)\n            raise KeyError(msg)\n\n        for param_key in params.keys():\n            param_value = params[param_key]\n            candidate_values = config_checklist[method][param_key]\n            check_param_type('param_value', param_value, (list, tuple, np.ndarray))\n\n            if candidate_values is None:\n                continue\n\n            for item_value in param_value:\n                flag = False\n                for candidate_value in candidate_values:\n                    if isinstance(candidate_value, set) and item_value in candidate_value:\n                        flag = True\n                        break\n                    elif not isinstance(candidate_value, set) and candidate_value(item_value):\n                        flag = True\n                        break\n\n                if not flag:\n                    msg = \"Setting of parameter {} in method {} is invalid\".format(param_key, method)\n                    raise ValueError(msg)\n\n\ndef verify_config_params(attack_config):\n    \"\"\"\n    External interfaces to verify attack config.\n    \"\"\"\n    _check_config(attack_config, _VALID_CONFIG_CHECKLIST)\n"
  },
  {
    "path": "mindarmour/privacy/evaluation/attacker.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nAttacker of Membership Inference.\n\"\"\"\nimport warnings\n\nfrom sklearn.neighbors import KNeighborsClassifier\nfrom sklearn.linear_model import LogisticRegression\nfrom sklearn.neural_network import MLPClassifier\nfrom sklearn.ensemble import RandomForestClassifier\nfrom sklearn.model_selection import GridSearchCV\nfrom sklearn.model_selection import RandomizedSearchCV\nfrom sklearn.exceptions import ConvergenceWarning\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_pair_numpy_param, check_param_type\n\nLOGGER = LogUtil.get_instance()\nTAG = \"Attacker\"\n\n\ndef _attack_knn(features, labels, param_grid, n_jobs):\n    \"\"\"\n    Train and return a KNN model.\n\n    Args:\n        features (numpy.ndarray): Loss and logits characteristics of each sample.\n        labels (numpy.ndarray): Labels of each sample whether belongs to training set.\n        param_grid (dict): Setting of GridSearchCV.\n        n_jobs (int): Number of jobs run in parallel. -1 means using all processors,\n            otherwise the value of n_jobs must be a positive integer.\n\n    Returns:\n        sklearn.model_selection.GridSearchCV, trained model.\n    \"\"\"\n    knn_model = KNeighborsClassifier()\n    knn_model = GridSearchCV(\n        knn_model, param_grid=param_grid, cv=3, n_jobs=n_jobs, verbose=0,\n    )\n    knn_model.fit(X=features, y=labels)\n    return knn_model\n\n\ndef _attack_lr(features, labels, param_grid, n_jobs):\n    \"\"\"\n    Train and return a LR model.\n\n    Args:\n        features (numpy.ndarray): Loss and logits characteristics of each sample.\n        labels (numpy.ndarray): Labels of each sample whether belongs to training set.\n        param_grid (dict): Setting of GridSearchCV.\n        n_jobs (int): Number of jobs run in parallel. -1 means using all processors,\n            otherwise the value of n_jobs must be a positive integer.\n\n    Returns:\n        sklearn.model_selection.GridSearchCV, trained model.\n    \"\"\"\n    lr_model = LogisticRegression(C=1.0, penalty=\"l2\", max_iter=300)\n    lr_model = GridSearchCV(\n        lr_model, param_grid=param_grid, cv=3, n_jobs=n_jobs, verbose=0,\n    )\n    lr_model.fit(X=features, y=labels)\n    return lr_model\n\n\ndef _attack_mlpc(features, labels, param_grid, n_jobs):\n    \"\"\"\n    Train and return a MLPC model.\n\n    Args:\n        features (numpy.ndarray): Loss and logits characteristics of each sample.\n        labels (numpy.ndarray): Labels of each sample whether belongs to training set.\n        param_grid (dict): Setting of GridSearchCV.\n        n_jobs (int): Number of jobs run in parallel. -1 means using all processors,\n            otherwise the value of n_jobs must be a positive integer.\n\n    Returns:\n        sklearn.model_selection.GridSearchCV, trained model.\n    \"\"\"\n    mlpc_model = MLPClassifier(random_state=1, max_iter=300)\n    mlpc_model = GridSearchCV(\n        mlpc_model, param_grid=param_grid, cv=3, n_jobs=n_jobs, verbose=0,\n    )\n    mlpc_model.fit(features, labels)\n    return mlpc_model\n\n\ndef _attack_rf(features, labels, random_grid, n_jobs):\n    \"\"\"\n    Train and return a RF model.\n\n    Args:\n        features (numpy.ndarray): Loss and logits characteristics of each sample.\n        labels (numpy.ndarray): Labels of each sample whether belongs to training set.\n        random_grid (dict): Setting of RandomizedSearchCV.\n        n_jobs (int): Number of jobs run in parallel. -1 means using all processors,\n            otherwise the value of n_jobs must be a positive integer.\n\n    Returns:\n        sklearn.model_selection.RandomizedSearchCV, trained model.\n    \"\"\"\n    rf_model = RandomForestClassifier(max_depth=2, random_state=0)\n    rf_model = RandomizedSearchCV(\n        rf_model, param_distributions=random_grid, n_iter=7, cv=3, n_jobs=n_jobs,\n        verbose=0,\n    )\n    rf_model.fit(features, labels)\n    return rf_model\n\n\ndef _get_attack_model(features, labels, config, n_jobs=-1):\n    \"\"\"\n    Get trained attack model specify by config.\n\n    Args:\n        features (numpy.ndarray): Loss and logits characteristics of each sample.\n        labels (numpy.ndarray): Labels of each sample whether belongs to training set.\n        config (dict): Config of attacker, with key in [\"method\", \"params\"].\n            The format is {\"method\": \"knn\", \"params\": {\"n_neighbors\": [3, 5, 7]}},\n            params of each method must within the range of changeable parameters.\n            Tips of params implement can be found in\n            \"https://scikit-learn.org/0.16/modules/generated/sklearn.grid_search.GridSearchCV.html\".\n        n_jobs (int): Number of jobs run in parallel. -1 means using all processors,\n            otherwise the value of n_jobs must be a positive integer.\n\n    Returns:\n        sklearn.BaseEstimator, trained model specify by config[\"method\"].\n\n    Examples:\n        >>> from mindarmour.privacy.evaluation.attacker import _get_attack_model\n        >>> features = np.random.randn(10, 10)\n        >>> labels = np.random.randint(0, 2, 10)\n        >>> config = {\"method\": \"knn\", \"params\": {\"n_neighbors\": [3, 5]}}\n        >>> attack_model = _get_attack_model(features, labels, config)\n    \"\"\"\n    features, labels = check_pair_numpy_param(\"features\", features, \"labels\", labels)\n    config = check_param_type(\"config\", config, dict)\n    n_jobs = check_param_type(\"n_jobs\", n_jobs, int)\n    if not (n_jobs == -1 or n_jobs > 0):\n        msg = \"Value of n_jobs must be -1 or positive integer.\"\n        raise ValueError(msg)\n\n    method = str.lower(config[\"method\"])\n    with warnings.catch_warnings():\n        warnings.filterwarnings('ignore', category=ConvergenceWarning)\n        if method == \"knn\":\n            return _attack_knn(features, labels, config[\"params\"], n_jobs)\n        if method == \"lr\":\n            return _attack_lr(features, labels, config[\"params\"], n_jobs)\n        if method == \"mlp\":\n            return _attack_mlpc(features, labels, config[\"params\"], n_jobs)\n        if method == \"rf\":\n            return _attack_rf(features, labels, config[\"params\"], n_jobs)\n\n    msg = \"Method {} is not supported.\".format(config[\"method\"])\n    LOGGER.error(TAG, msg)\n    raise NameError(msg)\n"
  },
  {
    "path": "mindarmour/privacy/evaluation/inversion_attack.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nInversion Attack\n\"\"\"\nimport numpy as np\nfrom scipy.special import softmax\n\nfrom mindspore.nn import Cell, MSELoss\nfrom mindspore import Tensor\nfrom mindspore.ops import operations as P\nfrom mindspore import context\n\nfrom mindarmour.utils.util import GradWrapWithLoss\nfrom mindarmour.utils._check_param import check_param_type, check_param_multi_types, \\\n    check_int_positive, check_numpy_param, check_value_positive, check_equal_shape\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils.util import calculate_lp_distance, compute_ssim\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'Image inversion attack'\n\n\nclass InversionLoss(Cell):\n    \"\"\"\n     The loss function for inversion attack.\n\n     Args:\n         network (Cell): The network used to infer images' deep representations.\n         weights (Union[list, tuple]): Weights of three sub-loss in InversionLoss, which can be adjusted to\n             obtain better results.\n     \"\"\"\n    def __init__(self, network, weights):\n        super(InversionLoss, self).__init__()\n        self._network = check_param_type('network', network, Cell)\n        self._mse_loss = MSELoss()\n        self._weights = check_param_multi_types('weights', weights, [list, tuple])\n        self._get_shape = P.Shape()\n        self._zeros = P.ZerosLike()\n        self._device_target = context.get_context(\"device_target\")\n\n    def construct(self, input_data, target_features):\n        \"\"\"\n        Calculate the inversion attack loss, which consists of three parts. Loss_1 is for evaluating the difference\n        between the target deep representations and current representations; Loss_2 is for evaluating the continuity\n        between adjacent pixels; Loss_3 is for regularization.\n\n        Args:\n            input_data (Tensor): The reconstructed image during inversion attack.\n            target_features (Tensor): Deep representations of the original image.\n\n        Returns:\n            Tensor, inversion attack loss of the current iteration.\n        \"\"\"\n        output = self._network(input_data)\n        loss_1 = self._mse_loss(output, target_features) / self._mse_loss(target_features, self._zeros(target_features))\n\n        data_shape = self._get_shape(input_data)\n        if self._device_target == 'CPU':\n            split_op_1 = P.Split(2, data_shape[2])\n            split_op_2 = P.Split(3, data_shape[3])\n            data_split_1 = split_op_1(input_data)\n            data_split_2 = split_op_2(input_data)\n            loss_2 = 0\n            for i in range(1, data_shape[2]):\n                loss_2 += self._mse_loss(data_split_1[i], data_split_1[i - 1])\n            for j in range(1, data_shape[3]):\n                loss_2 += self._mse_loss(data_split_2[j], data_split_2[j - 1])\n        else:\n            data_copy_1 = self._zeros(input_data)\n            data_copy_2 = self._zeros(input_data)\n            data_copy_1[:, :, :(data_shape[2] - 1), :] = input_data[:, :, 1:, :]\n            data_copy_2[:, :, :, :(data_shape[2] - 1)] = input_data[:, :, :, 1:]\n            loss_2 = self._mse_loss(input_data, data_copy_1) + self._mse_loss(input_data, data_copy_2)\n\n        loss_3 = self._mse_loss(input_data, self._zeros(input_data))\n\n        loss = loss_1*self._weights[0] + loss_2*self._weights[1] + loss_3*self._weights[2]\n        return loss\n\n\nclass ImageInversionAttack:\n    r\"\"\"\n    An attack method used to reconstruct images by inverting their deep representations.\n\n    References: `Aravindh Mahendran, Andrea Vedaldi. Understanding Deep Image Representations by Inverting Them.\n    2014. <https://arxiv.org/pdf/1412.0035.pdf>`_\n\n    Args:\n        network (Cell): The network used to infer images' deep representations.\n        input_shape (tuple): Data shape of single network input, which should be in accordance with the given\n            network. The format of shape should be :math:`(channel, image\\_width, image\\_height)`.\n        input_bound (Union[tuple, list]): The pixel range of original images, which should be like [minimum_pixel,\n            maximum_pixel] or (minimum_pixel, maximum_pixel).\n        loss_weights (Union[list, tuple]): Weights of three sub-loss in InversionLoss, which can be adjusted to\n            obtain better results. Default: ``(1, 0.2, 5)``.\n\n    Raises:\n        TypeError: If the type of `network` is not Cell.\n        ValueError: If any value of `input_shape` is not positive int.\n        ValueError: If any value of `loss_weights` is not positive value.\n\n    Examples:\n            >>> import mindspore.ops.operations as P\n            >>> from mindspore.nn import Cell\n            >>> from mindarmour.privacy.evaluation.inversion_attack import ImageInversionAttack\n            >>> class Net(Cell):\n            ...     def __init__(self):\n            ...         super(Net, self).__init__()\n            ...         self._softmax = P.Softmax()\n            ...         self._reduce = P.ReduceSum()\n            ...         self._squeeze = P.Squeeze(1)\n            ...     def construct(self, inputs):\n            ...         out = self._softmax(inputs)\n            ...         out = self._reduce(out, 2)\n            ...         return self._squeeze(out)\n            >>> net = Net()\n            >>> original_images = np.random.random((2,1,10,10)).astype(np.float32)\n            >>> target_features =  np.random.random((2,10)).astype(np.float32)\n            >>> inversion_attack = ImageInversionAttack(net,\n            ...                                         input_shape=(1, 10, 10),\n            ...                                         input_bound=(0, 1),\n            ...                                         loss_weights=[1, 0.2, 5])\n            >>> inversion_images = inversion_attack.generate(target_features, iters=10)\n            >>> evaluate_result = inversion_attack.evaluate(original_images, inversion_images)\n    \"\"\"\n    def __init__(self, network, input_shape, input_bound, loss_weights=(1, 0.2, 5)):\n        self._network = check_param_type('network', network, Cell)\n        for sub_loss_weight in loss_weights:\n            check_value_positive('sub_loss_weight', sub_loss_weight)\n        self._loss = InversionLoss(self._network, loss_weights)\n        self._input_shape = check_param_type('input_shape', input_shape, tuple)\n        for shape_dim in input_shape:\n            check_int_positive('shape_dim', shape_dim)\n        self._input_bound = check_param_multi_types('input_bound', input_bound, [list, tuple])\n        for value_bound in self._input_bound:\n            check_param_multi_types('value_bound', value_bound, [float, int])\n        if self._input_bound[0] > self._input_bound[1]:\n            msg = 'input_bound[0] should not be larger than input_bound[1], but got them as {} and {}'.format(\n                self._input_bound[0], self._input_bound[1])\n            raise ValueError(msg)\n\n    def generate(self, target_features, iters=100):\n        \"\"\"\n        Reconstruct images based on target_features.\n\n        Args:\n            target_features (numpy.ndarray): Deep representations of original images. The first dimension of\n                target_features should be img_num. It should be noted that the shape of target_features should be\n                :math:`(1, dim2, dim3, ...)` if img_num equals 1.\n            iters (int): iteration times of inversion attack, which should be positive integers. Default: ``100``.\n\n        Returns:\n            numpy.ndarray, reconstructed images, which are expected to be similar to original images.\n\n        Raises:\n            TypeError: If the type of target_features is not numpy.ndarray.\n            ValueError: If any value of iters is not positive int.Z.\n        \"\"\"\n        target_features = check_numpy_param('target_features', target_features)\n        iters = check_int_positive('iters', iters)\n\n        # shape checking\n        img_num = target_features.shape[0]\n        test_input = np.random.random((img_num,) + self._input_shape).astype(np.float32)\n        test_out = self._network(Tensor(test_input)).asnumpy()\n        if test_out.shape != target_features.shape:\n            msg = \"The shape of target_features ({}) is not in accordance with the shape\" \\\n                  \" of network output({})\".format(target_features.shape, test_out.shape)\n            raise ValueError(msg)\n        loss_net = self._loss\n        loss_grad = GradWrapWithLoss(loss_net)\n\n        inversion_images = []\n        for i in range(img_num):\n            target_feature_n = target_features[i]\n            inversion_image_n = np.random.random((1,) + self._input_shape).astype(np.float32)*0.05\n            for s in range(iters):\n                x_grad = loss_grad(Tensor(inversion_image_n), Tensor(target_feature_n)).asnumpy()\n                x_grad_sign = np.sign(x_grad)\n                inversion_image_n -= x_grad_sign*0.01\n                inversion_image_n = np.clip(inversion_image_n, self._input_bound[0], self._input_bound[1])\n                current_loss = loss_net(Tensor(inversion_image_n), Tensor(target_feature_n))\n                LOGGER.info(TAG, 'iteration step: {}, loss is {}'.format(s, current_loss))\n            inversion_images.append(inversion_image_n)\n        return np.concatenate(np.array(inversion_images))\n\n    def evaluate(self, original_images, inversion_images, labels=None, new_network=None):\n        r\"\"\"\n        Evaluate the quality of inverted images by three index: the average L2 distance and SSIM value between\n        original images and inversion images, and the average of inverted images' confidence on true labels of inverted\n        inferred by a new trained network.\n\n        Args:\n            original_images (numpy.ndarray): Original images, whose shape should be\n                :math:`(img\\_num, channels, img\\_width, img\\_height)`.\n            inversion_images (numpy.ndarray): Inversion images, whose shape should be\n                :math:`(img\\_num, channels, img\\_width, img\\_height)`.\n            labels (numpy.ndarray): Ground truth labels of original images. Default: ``None``.\n            new_network (Cell): A network whose structure contains all parts of self._network, but loaded with different\n                checkpoint file. Default: ``None``.\n\n        Returns:\n            - float, l2 distance.\n\n            - float, average ssim value.\n\n            - Union[float, None], average confidence. It would be None if labels or new_network is None.\n        \"\"\"\n        check_numpy_param('original_images', original_images)\n        check_numpy_param('inversion_images', inversion_images)\n        if labels is not None:\n            check_numpy_param('labels', labels)\n            true_labels = np.squeeze(labels)\n            if len(true_labels.shape) > 1:\n                msg = 'Shape of true_labels should be (1, n) or (n,), but got {}'.format(true_labels.shape)\n                raise ValueError(msg)\n            if true_labels.size != original_images.shape[0]:\n                msg = 'The size of true_labels should equal the number of images, but got {} and {}'.format(\n                    true_labels.size, original_images.shape[0])\n                raise ValueError(msg)\n        if new_network is not None:\n            check_param_type('new_network', new_network, Cell)\n            LOGGER.info(TAG, 'Please make sure that the network you pass is loaded with different checkpoint files '\n                             'compared with that of self._network.')\n\n        img_1, img_2 = check_equal_shape('original_images', original_images, 'inversion_images', inversion_images)\n        if (len(img_1.shape) != 4) or (img_1.shape[1] != 1 and img_1.shape[1] != 3):\n            msg = 'The shape format of img_1 and img_2 should be (img_num, channels, img_width, img_height),' \\\n                  ' but got {} and {}'.format(img_1.shape, img_2.shape)\n            raise ValueError(msg)\n\n        total_l2_distance = 0\n        total_ssim = 0\n        img_1 = img_1.transpose(0, 2, 3, 1)\n        img_2 = img_2.transpose(0, 2, 3, 1)\n        for i in range(img_1.shape[0]):\n            _, l2_dis, _ = calculate_lp_distance(img_1[i], img_2[i])\n            total_l2_distance += l2_dis\n            total_ssim += compute_ssim(img_1[i], img_2[i])\n        avg_l2_dis = total_l2_distance / img_1.shape[0]\n        avg_ssim = total_ssim / img_1.shape[0]\n        avg_confi = None\n        if (new_network is not None) and (labels is not None):\n            pred_logits = new_network(Tensor(inversion_images.astype(np.float32))).asnumpy()\n            logits_softmax = softmax(pred_logits, axis=1)\n            avg_confi = np.mean(logits_softmax[np.arange(img_1.shape[0]), true_labels])\n        return avg_l2_dis, avg_ssim, avg_confi\n"
  },
  {
    "path": "mindarmour/privacy/evaluation/membership_inference.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nMembership Inference\n\"\"\"\n\nfrom multiprocessing import cpu_count\nimport numpy as np\n\nimport mindspore as ms\nfrom mindspore.train import Model\nfrom mindspore.dataset.engine import Dataset\nfrom mindspore import Tensor\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_param_type, check_param_multi_types, \\\n    check_model, check_numpy_param\nfrom .attacker import _get_attack_model\nfrom ._check_config import verify_config_params\n\nLOGGER = LogUtil.get_instance()\nTAG = \"MembershipInference\"\n\n\ndef _eval_info(pred, truth, option):\n    \"\"\"\n    Calculate the performance according to pred and truth.\n\n    Args:\n        pred (numpy.ndarray): Predictions for each sample.\n        truth (numpy.ndarray): Ground truth for each sample.\n        option (str): Type of evaluation indicators; Possible\n            values are 'precision', 'accuracy' and 'recall'.\n\n    Returns:\n        float32, calculated evaluation results.\n\n    Raises:\n        ValueError, size of parameter pred or truth is 0.\n        ValueError, value of parameter option must be in [\"precision\", \"accuracy\", \"recall\"].\n    \"\"\"\n    check_numpy_param(\"pred\", pred)\n    check_numpy_param(\"truth\", truth)\n\n    if option == \"accuracy\":\n        count = np.sum(pred == truth)\n        return count / len(pred)\n    if option == \"precision\":\n        if np.sum(pred) == 0:\n            return -1\n        count = np.sum(pred & truth)\n        return count / np.sum(pred)\n    if option == \"recall\":\n        if np.sum(truth) == 0:\n            return -1\n        count = np.sum(pred & truth)\n        return count / np.sum(truth)\n\n    msg = \"The metric value {} is undefined.\".format(option)\n    LOGGER.error(TAG, msg)\n    raise ValueError(msg)\n\n\ndef _softmax_cross_entropy(logits, labels, epsilon=1e-12):\n    \"\"\"\n    Calculate the SoftmaxCrossEntropy result between logits and labels.\n\n    Args:\n        logits (numpy.ndarray): Numpy array of shape(N, C).\n        labels (numpy.ndarray): Numpy array of shape(N, ).\n        epsilon (float): The calculated value of softmax will be clipped into [epsilon, 1 - epsilon]. Default: 1e-12.\n\n    Returns:\n        numpy.ndarray: numpy array of shape(N, ), containing loss value for each vector in logits.\n    \"\"\"\n    labels = np.eye(logits.shape[1])[labels].astype(np.int32)\n\n    exp_logits = np.exp(logits - np.max(logits, axis=-1, keepdims=True))\n    predictions = exp_logits / np.sum(exp_logits, axis=-1, keepdims=True)\n    predictions = np.clip(predictions, epsilon, 1.0 - epsilon)\n    loss = -1 * np.sum(labels*np.log(predictions), axis=-1)\n    return loss\n\n\nclass MembershipInference:\n    \"\"\"\n    Proposed by Shokri, Stronati, Song and Shmatikov, membership inference is a grey-box attack\n    for inferring user's privacy data. It requires loss or logits results of the training samples. Privacy refers\n    to some sensitive attributes of a single user.\n\n    For details, please refer to the `Using Membership Inference to Test Model Security\n    <https://mindspore.cn/mindarmour/docs/en/master/test_model_security_membership_inference.html>`_.\n\n    References: `Reza Shokri, Marco Stronati, Congzheng Song, Vitaly Shmatikov.\n    Membership Inference Attacks against Machine Learning Models. 2017.\n    <https://arxiv.org/abs/1610.05820v2>`_.\n\n    Args:\n        model (Model): Target model.\n        n_jobs (int): Number of jobs run in parallel. ``-1`` means using all processors,\n            otherwise the value of `n_jobs` must be a positive integer.\n\n    Raises:\n        TypeError: If type of model is not `mindspore.train.Model`.\n        TypeError: If type of `n_jobs` is not int.\n        ValueError: The value of `n_jobs` is neither ``-1`` nor a positive integer.\n\n\n    Examples:\n        >>> import mindspore.ops.operations as P\n        >>> from mindspore.nn import Cell\n        >>> from mindspore import Model\n        >>> from mindarmour.privacy.evaluation import MembershipInference\n        >>> def dataset_generator():\n        ...     batch_size = 16\n        ...     batches = 1\n        ...     data =  np.random.randn(batches * batch_size,1,10).astype(np.float32)\n        ...     label =  np.random.randint(0,10, batches * batch_size).astype(np.int32)\n        ...     for i in range(batches):\n        ...         yield data[i*batch_size:(i+1)*batch_size], label[i*batch_size:(i+1)*batch_size]\n        >>> class Net(Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...         self._Dense = nn.Dense(10,10)\n        ...         self._squeeze = P.Squeeze(1)\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         out = self._Dense(out)\n        ...         return self._squeeze(out)\n        >>> net = Net()\n        >>> loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True)\n        >>> opt = nn.Momentum(params=net.trainable_params(), learning_rate=0.1, momentum=0.9)\n        >>> model = Model(network=net, loss_fn=loss, optimizer=opt)\n        >>> inference_model = MembershipInference(model, 2)\n        >>> config = [{\n        ...     \"method\": \"KNN\",\n        ...     \"params\": {\"n_neighbors\": [3, 5, 7],}\n        ...     }]\n        >>> ds_train = ds.GeneratorDataset(dataset_generator, [\"image\", \"label\"])\n        >>> ds_test = ds.GeneratorDataset(dataset_generator, [\"image\", \"label\"])\n        >>> inference_model.train(ds_train, ds_test, config)\n        >>> metrics = [\"precision\", \"accuracy\", \"recall\"]\n        >>> eval_train = ds.GeneratorDataset(dataset_generator, [\"image\", \"label\"])\n        >>> eval_test = ds.GeneratorDataset(dataset_generator, [\"image\", \"label\"])\n        >>> result = inference_model.eval(eval_train. eval_test, metrics)\n        >>> print(result)\n    \"\"\"\n\n    def __init__(self, model, n_jobs=-1):\n        check_param_type(\"n_jobs\", n_jobs, int)\n        if not (n_jobs == -1 or n_jobs > 0):\n            msg = \"Value of n_jobs must be either -1 or positive integer, but got {}.\".format(n_jobs)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n        self._model = check_model(\"model\", model, Model)\n        self._n_jobs = min(n_jobs, cpu_count())\n        self._attack_list = []\n\n    def train(self, dataset_train, dataset_test, attack_config):\n        \"\"\"\n        Depending on the configuration, use the input dataset to train the attack model.\n\n        Args:\n            dataset_train (mindspore.dataset): The training dataset for the target model.\n            dataset_test (mindspore.dataset): The test set for the target model.\n            attack_config (Union[list, tuple]): Parameter setting for the attack model. The format is as follows:\n\n                .. code-block:: python\n\n                    attack_config =\n                        [{\"method\": \"knn\", \"params\": {\"n_neighbors\": [3, 5, 7]}},\n                         {\"method\": \"lr\", \"params\": {\"C\": np.logspace(-4, 2, 10)}}]\n\n                The support methods are knn, lr, mlp and rf, and the params of each method\n                must within the range of changeable parameters. Tips of params implement\n                can be found below:\n                `KNN <https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html>`_,\n                `LR <https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html>`_,\n                `RF <https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html>`_,\n                `MLP <https://scikit-learn.org/stable/modules/generated/sklearn.neural_network.MLPRegressor.html>`_.\n\n        Raises:\n            KeyError: If any config in attack_config doesn't have keys {\"method\", \"params\"}.\n            NameError: If the method(case insensitive) in attack_config is not ``\"lr\"``, ``\"knn\"``, ``\"rf\"``\n                or ``\"mlp\"``.\n        \"\"\"\n        check_param_type(\"dataset_train\", dataset_train, Dataset)\n        check_param_type(\"dataset_test\", dataset_test, Dataset)\n        check_param_multi_types(\"attack_config\", attack_config, (list, tuple))\n        verify_config_params(attack_config)\n\n        features, labels = self._transform(dataset_train, dataset_test)\n        for config in attack_config:\n            self._attack_list.append(_get_attack_model(features, labels, config, n_jobs=self._n_jobs))\n\n\n    def eval(self, dataset_train, dataset_test, metrics):\n        \"\"\"\n        Evaluate the different privacy of the target model.\n        Evaluation indicators shall be specified by metrics.\n\n        Args:\n            dataset_train (mindspore.dataset): The training dataset for the target model.\n            dataset_test (mindspore.dataset): The test dataset for the target model.\n            metrics (Union[list, tuple]): Evaluation indicators. The value of metrics\n                must be ``\"precision\"``, ``\"accuracy\"`` or ``\"recall\"``. Default: ``\"precision\"``.\n\n        Returns:\n            list, each element contains an evaluation indicator for the attack model.\n        \"\"\"\n        check_param_type(\"dataset_train\", dataset_train, Dataset)\n        check_param_type(\"dataset_test\", dataset_test, Dataset)\n        check_param_multi_types(\"metrics\", metrics, (list, tuple))\n\n        metrics = set(metrics)\n        metrics_list = {\"precision\", \"accuracy\", \"recall\"}\n        if not metrics <= metrics_list:\n            msg = \"Element in 'metrics' must be in {}, but got {}.\".format(metrics_list, metrics)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n        result = []\n        features, labels = self._transform(dataset_train, dataset_test)\n        for attacker in self._attack_list:\n            pred = attacker.predict(features)\n            item = {}\n            for option in metrics:\n                item[option] = _eval_info(pred, labels, option)\n            result.append(item)\n        return result\n\n    def _transform(self, dataset_train, dataset_test):\n        \"\"\"\n        Generate corresponding loss_logits features and new label, and return after shuffle.\n\n        Args:\n            dataset_train (mindspore.dataset): The train set for the target model.\n            dataset_test (mindspore.dataset): The test set for the target model.\n\n        Returns:\n            - numpy.ndarray, loss_logits features for each sample. Shape is (N, C).\n                N is the number of sample. C = 1 + dim(logits).\n            - numpy.ndarray, labels for each sample, Shape is (N,).\n        \"\"\"\n        features_train, labels_train = self._generate(dataset_train, 1)\n        features_test, labels_test = self._generate(dataset_test, 0)\n        features = np.vstack((features_train, features_test))\n        labels = np.hstack((labels_train, labels_test))\n        shuffle_index = np.array(range(len(labels)))\n        np.random.shuffle(shuffle_index)\n        features = features[shuffle_index]\n        labels = labels[shuffle_index]\n\n        return features, labels\n\n    def _generate(self, input_dataset, label):\n        \"\"\"\n        Return a loss_logits features and labels for training attack model.\n\n        Args:\n            input_dataset (mindspore.dataset): The dataset to be generated.\n            label (int): Whether input_dataset belongs to the target model.\n\n        Returns:\n            - numpy.ndarray, loss_logits features for each sample. Shape is (N, C).\n                N is the number of sample. C = 1 + dim(logits).\n\n            - numpy.ndarray, labels for each sample, Shape is (N,).\n        \"\"\"\n        loss_logits = np.array([])\n        for batch in input_dataset.create_tuple_iterator(output_numpy=True):\n            batch_data = Tensor(batch[0], ms.float32)\n            batch_labels = batch[1].astype(np.int32)\n            batch_logits = self._model.predict(batch_data).asnumpy()\n            batch_loss = _softmax_cross_entropy(batch_logits, batch_labels)\n\n            batch_feature = np.hstack((batch_loss.reshape(-1, 1), batch_logits))\n            if loss_logits.size == 0:\n                loss_logits = batch_feature\n            else:\n                loss_logits = np.vstack((loss_logits, batch_feature))\n\n        if label == 1:\n            labels = np.ones(len(loss_logits), np.int32)\n        elif label == 0:\n            labels = np.zeros(len(loss_logits), np.int32)\n        else:\n            msg = \"The value of label must be 0 or 1, but got {}.\".format(label)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        return loss_logits, labels\n"
  },
  {
    "path": "mindarmour/privacy/evaluation/model_inversion_attack.py",
    "content": "# Copyright 2024 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nModel Inversion Attack\n\"\"\"\nimport os\nimport mindspore as ms\nfrom mindspore import nn\nfrom mindspore import Tensor\n\nfrom mindarmour.utils._check_param import check_param_type, check_int_positive\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils.util import compute_ssim, compute_psnr\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'Model Inversion attack'\n\n\nclass ModelInversionLoss(nn.Cell):\n    \"\"\"\n    The loss function for model inversion attack.\n\n    Args:\n        network (Cell): The network used to infer images' intermediate representations.\n        invnet (Cell): The network used to reply to the original image input through intermediate representations.\n        loss_fn (Cell): The Loss function used to calculate the distance between the original input and the reply input.\n        target_layer (str): Split target layer in split learning.\n    \"\"\"\n    def __init__(self, network, invnet, loss_fn, target_layer='conv1'):\n        super(ModelInversionLoss, self).__init__()\n        self._network = check_param_type('network', network, nn.Cell)\n        self._invnet = check_param_type('invnet', invnet, nn.Cell)\n        self._loss_fn = check_param_type('loss_fn', loss_fn, nn.Cell)\n        self._target_layer = check_param_type('target_layer', target_layer, str)\n        self._network.set_train(False)\n\n    def construct(self, inputs):\n        orginal_model_output = self._network.get_layer_output(inputs, self._target_layer)\n        decoder_model_output = self._invnet(orginal_model_output)\n        loss = self._loss_fn(inputs, decoder_model_output)\n        return loss\n\n\nclass ModelInversionAttack:\n    \"\"\"\n    An model attack method used to reconstruct images by invert their model.\n\n    References: [1] HE Z, ZHANG T, LEE R B. Model inversion attacks against collaborative inference.\n    https://dl.acm.org/doi/10.1145/3359789.3359824\n\n    Args:\n        network (Cell): The network used to infer images' intermediate representations.\n        ckpoint_path (str): The path used to save invert model parameters.\n        split_layer(str): Split target layer in split learning.\n        ds_name (str): The name of the dataset used to train the reverse model.\n\n    Raises:\n        TypeError: If the type of `network` is not Cell.\n    \"\"\"\n    def __init__(self, network, inv_network, input_shape, ckpoint_path=None, split_layer='conv1'):\n        self._network = check_param_type('network', network, nn.Cell)\n        self._invnet = check_param_type('inv_network', inv_network, nn.Cell)\n        self._split_layer = check_param_type('split_layer', split_layer, str)\n        self._ckpath = ckpoint_path  #check_param_type('ckpoint_path', ckpoint_path, str)\n        self.check_inv_network(input_shape)\n        if self._ckpath is None:\n            self._ckpath = './trained_inv_ckpt_file'\n        else:\n            load_dict = ms.load_checkpoint(self._ckpath)\n            ms.load_param_into_net(self._invnet, load_dict)\n\n    def check_inv_network(self, input_shape):\n        input_shape = check_param_type('input_shape', input_shape, tuple)\n        inputs = ms.numpy.ones((1,) + input_shape)\n        orginal_model_output = self._network.get_layer_output(inputs, self._split_layer)\n        inv_model_output = self._invnet(orginal_model_output)\n        if inputs.shape != inv_model_output.shape:\n            msg = \"InvModel error, input shape is {}, but invmodel output shape is {}\" \\\n                .format(inputs.shape, inv_model_output.shape)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n    def train_inversion_model(self, dataset, epochs=50, learningrate=1e-3, eps=1e-3, apply_ams=True):\n        \"\"\"\n        Train reverse model based on dataset\n\n        Args:\n            dataset (MappableDataset): Data for training reverse models.\n            Nepochs (int): Training rounds, which should be positive integers. Defalult: ``50``.\n            LearninigRate (float): The learning rate used to update the parameters of the reverse model.\n            eps (float): The epsilon used to update the parameters of the reverse model.\n            AMSGrad (bool): Whether to use AMSGrad to update the parameters of the reverse model.\n\n        Raises:\n            TypeError: If the type of `dataset` is not MappableDataset.\n            TypeError: If the type of `Nepochs` is not int.\n            TypeError: If the type of `LearningRate` is not float.\n            TypeError: If the type of `eps` is not float.\n            TypeError: If the type of `AMSGrad` is not bool.\n        \"\"\"\n        epochs = check_int_positive('epochs', epochs)\n        learningrate = check_param_type('learningrate', learningrate, float)\n        eps = check_param_type('eps', eps, float)\n        apply_ams = check_param_type('apply_ams', apply_ams, bool)\n\n        self._invnet.set_train(True)\n        net_loss = nn.MSELoss()\n        optim = nn.Adam(self._invnet.trainable_params(), learning_rate=learningrate, eps=eps, use_amsgrad=apply_ams)\n        net = ModelInversionLoss(self._network, self._invnet, net_loss, self._split_layer)\n        net = nn.TrainOneStepCell(net, optim)\n        if not os.path.exists(self._ckpath):\n            os.makedirs(self._ckpath)\n\n        for epoch in range(epochs):\n            loss = 0\n            for inputs, _ in dataset.create_tuple_iterator():\n                loss += net(Tensor(inputs)).asnumpy()\n            LOGGER.info(TAG, \"Epoch: {}, Loss: {}\".format(epoch, loss))\n            if epoch % 10 == 0:\n                ms.save_checkpoint(self._invnet, self._ckpath + '/invmodel_{}_{}.ckpt'.format(self._split_layer, epoch))\n\n    def evaluate(self, dataset):\n        \"\"\"\n        Evaluate the model inversion attack.\n\n        Args:\n            dataset (MappableDataset): Data for evaluation.\n\n        Returns:\n            - float, average ssim value.\n            - float, average psnr value.\n\n        \"\"\"\n        self._invnet.set_train(False)\n\n        total_ssim = 0\n        total_psnr = 0\n        size = 0\n        for inputs, _ in dataset.create_tuple_iterator():\n            orginal_model_output = self._network.get_layer_output(Tensor(inputs), self._split_layer)\n            decoder_model_output = self._invnet(orginal_model_output)\n            decoder_model_output = decoder_model_output.clip(0, 1)\n            for i in range(inputs.shape[0]):\n                original_image = inputs[i].transpose(1, 2, 0).asnumpy()\n                compared_image = decoder_model_output[i].transpose(1, 2, 0).asnumpy()\n                ssim = compute_ssim(original_image, compared_image)\n                psnr = compute_psnr(original_image, compared_image)\n\n                total_ssim += ssim\n                total_psnr += psnr\n            size += inputs.shape[0]\n        if size != 0:\n            avg_ssim = total_ssim / size\n            avg_psnr = total_psnr / size\n            return avg_ssim, avg_psnr\n        return 0, 0\n\n    def inverse(self, target_feature):\n        \"\"\"\n        inverse the target feature.\n\n        Args:\n            target_feature (Tensor): The target feature.\n        Returns:\n            - Tensor, the reconstructed image.\n        \"\"\"\n        target_feature = check_param_type('target_feature', target_feature, Tensor)\n        return self._invnet(target_feature)\n"
  },
  {
    "path": "mindarmour/privacy/evaluation/shadow_model_attack.py",
    "content": "# Copyright 2024 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============================================================================\n\"\"\"\nModel Inversion Attack\n\"\"\"\nimport os\nimport mindspore as ms\nfrom mindspore import nn\nfrom mindspore import Tensor\nfrom mindarmour.utils._check_param import check_param_type, \\\n    check_int_positive\nfrom mindarmour.utils.logger import LogUtil\n\nLOGGER = LogUtil.get_instance()\nLOGGER.set_level('INFO')\nTAG = 'Model Inversion attack'\n\n\nclass ShadowModelLoss(nn.Cell):\n    \"\"\"\n    The Loss function for shadow model attack.\n    \"\"\"\n    def __init__(self, network, shadow_net, loss_fn, target_layer='conv11'):\n        super(ShadowModelLoss, self).__init__()\n        self._network = check_param_type('network', network, nn.Cell)\n        self._shadow_net = check_param_type('shadow_net', shadow_net, nn.Cell)\n        self._loss_fn = check_param_type('loss_fn', loss_fn, nn.Cell)\n        self._target_layer = check_param_type('target_layer', target_layer, str)\n        self._network.set_train(False)\n\n    def construct(self, inputs, targets):\n        mid_output = self._shadow_net(Tensor(inputs))\n        final_output = self._network.forward_from(mid_output, self._target_layer)\n        loss = self._loss_fn(final_output, targets)\n        return loss\n\n\nclass ShadowModelAttack:\n    \"\"\"\n    Train a shadow model based on a dataset that is known to be accessible,\n    and then interrogate the shadow model to extract sensitive information.\n\n    References: [1] HE Z, ZHANG T, LEE R B. Model inversion attacks against collaborative inference.\n    https://dl.acm.org/doi/10.1145/3359789.3359824\n\n    Args:\n        network (Cell): The original network.\n        shadow_network (Cell): The network used to simulate the original network.\n        ckpoint_path (str): The path used to save invert model parameters.\n        split_layer(str): Split target layer in split learning.\n\n    Raises:\n        TypeError: If the type of `network` or `shadow_network` is not Cell.\n        ValueError: If any value of `split_layer` is not in the network.\n\n    Examples:\n            >>> import mindspore.ops.operations as P\n            >>> from mindspore.nn import Cell\n            >>> from mindarmour.privacy.evaluation.inversion_attack import ImageInversionAttack\n            >>> from mindarmour.privacy.evaluation.shadow_model_attack import ShadowModelAttack\n            >>> class Net(Cell):\n            ...     def __init__(self):\n            ...         super(Net, self).__init__()\n            ...         self._softmax = P.Softmax()\n            ...         self._reduce = P.ReduceSum()\n            ...         self._squeeze = P.Squeeze(1)\n            ...     def construct(self, inputs):\n            ...         out = self._softmax(inputs)\n            ...         out = self._reduce(out, 2)\n            ...         return self._squeeze(out)\n            >>> net = Net()\n            >>> shadow_net = InvNet()\n            >>> original_images = np.random.random((2,1,10,10)).astype(np.float32)\n            >>> target_features =  np.random.random((2,10)).astype(np.float32)\n            >>> shadow_model_attack = ImageInversionAttack(net,\n            ...                                         shadow_net,\n            ...                                         ckpoint_path='./trained_shadow_ckpt_file',\n            ...                                         split_layer='conv11')\n            >>> attack_config = {'epochs': 10, 'learningrate': 1e-3, 'eps': 1e-3, 'num_classes': 10,\n            ...                         'apply_ams': True}\n            >>> shadow_model_attack.train_shadow_model(dataset, attack_config)\n            >>> inversion_attack = ImageInversionAttack(shadow_net,\n            ...                                         input_shape=(1, 10, 10),\n            ...                                         input_bound=(0, 1),\n            ...                                         loss_weights=[1, 0.2, 5])\n            >>> inversion_images = inversion_attack.generate(target_features, iters=10)\n            >>> evaluate_result = inversion_attack.evaluate(original_images, inversion_images)\n    \"\"\"\n    def __init__(self, network, shadow_network, ckpoint_path='', split_layer='conv1'):\n        self._network = check_param_type('network', network, nn.Cell)\n        self._shadow_network = check_param_type('shadow_network', shadow_network, nn.Cell)\n        self._split_layer = check_param_type('split_layer', split_layer, str)\n        self._ckpath = check_param_type('ckpoint_path', ckpoint_path, str)\n        if self._ckpath == '':\n            self._ckpath = './trained_shadow_ckpt_file'\n            if not os.path.exists(self._ckpath):\n                os.makedirs(self._ckpath)\n        else:\n            load_dict = ms.load_checkpoint(self._ckpath)\n            ms.load_param_into_net(self._shadow_network, load_dict)\n\n    def train_shadow_model(self, dataset, attack_config):\n        \"\"\"\n        Train a shadow model based on a dataset that is known to be accessible,\n        and then interrogate the shadow model to extract sensitive information.\n\n        Args:\n            train_dataset (Dataset): The training dataset.\n            epoch_size (int): The number of epochs. Default: 1.\n            attack_config (dict): The attack configuration.\n\n                .. code-block:: python\n\n                    attack_config =\n                        {\"epochs\": 50, \"learningrate\": 1e-3, \"eps\": 1e-3,\n                         \"num_classes\": 10, \"apply_ams\": True}\n\n        \"\"\"\n        epochs = attack_config.get('epcohs', 50)\n        learningrate = attack_config.get('learningrate', 1e-3)\n        eps = attack_config.get('eps', 1e-3)\n        num_classes = attack_config.get('num_classes', 10)\n        apply_ams = attack_config.get('apply_ams', True)\n\n        epochs = check_int_positive('epochs', epochs)\n        learningrate = check_param_type('learningrate', learningrate, float)\n        eps = check_param_type('eps', eps, float)\n        num_classes = check_int_positive('num_classes', num_classes)\n        apply_ams = check_param_type('apply_ams', apply_ams, bool)\n\n        net_loss = nn.SoftmaxCrossEntropyWithLogits(reduction='mean')\n        optim = nn.Adam(self._shadow_network.trainable_params(), learning_rate=learningrate)\n        net = ShadowModelLoss(self._network, self._shadow_network, net_loss, target_layer=self._split_layer)\n        net = nn.TrainOneStepCell(net, optim)\n        onehot_op = nn.OneHot(depth=num_classes)\n        for epoch in range(epochs):\n            loss = 0\n            for inputs, targets in dataset.create_tuple_iterator():\n                targets = onehot_op(targets)\n                loss += net(inputs, targets).asnumpy()\n            LOGGER.info(TAG, \"Epoch: {}, Loss: {}\".format(epoch, loss))\n            if epoch % 10 == 0:\n                ms.save_checkpoint(self._shadow_network, os.path.join(\n                    self._ckpath, './shadow_{}_{}.ckpt'.format(self._split_layer, epoch)\n                ))\n\n    def evaluate(self, dataset, num_classes=10):\n        \"\"\"\n        Evaluate the shadow model.\n\n        Args:\n            dataset (MappableDataset): Data for evaluation.\n\n        Returns:\n            - float, average loss.\n        \"\"\"\n        num_classes = check_int_positive('num_classes', num_classes)\n        self._shadow_network.set_train(False)\n\n        size = 0\n        total_loss = 0\n        loss_fn = nn.SoftmaxCrossEntropyWithLogits(reduction='mean')\n        onehot_op = nn.OneHot(depth=num_classes)\n        for inputs, targets in dataset.create_tuple_iterator():\n            mid_output = self._shadow_network(Tensor(inputs))\n            final_output = self._network.forward_from(mid_output, self._split_layer)\n            targets = onehot_op(targets)\n            total_loss += loss_fn(final_output, Tensor(targets))\n            size += inputs.shape[0]\n        if size != 0:\n            avg_loss = total_loss / size\n            return avg_loss\n        return 0\n"
  },
  {
    "path": "mindarmour/privacy/sup_privacy/__init__.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis module provides Suppress Privacy feature to protect user privacy.\n\"\"\"\nfrom .mask_monitor.masker import SuppressMasker\nfrom .train.model import SuppressModel\nfrom .sup_ctrl.conctrl import SuppressPrivacyFactory\nfrom .sup_ctrl.conctrl import SuppressCtrl\nfrom .sup_ctrl.conctrl import MaskLayerDes\n\n__all__ = ['SuppressMasker',\n           'SuppressModel',\n           'SuppressPrivacyFactory',\n           'SuppressCtrl',\n           'MaskLayerDes']\n"
  },
  {
    "path": "mindarmour/privacy/sup_privacy/mask_monitor/__init__.py",
    "content": ""
  },
  {
    "path": "mindarmour/privacy/sup_privacy/mask_monitor/masker.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nMasker module of suppress-based privacy..\n\"\"\"\nfrom mindspore.train.callback import Callback\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_param_type\nfrom mindarmour.privacy.sup_privacy.train.model import SuppressModel\nfrom mindarmour.privacy.sup_privacy.sup_ctrl.conctrl import SuppressCtrl\n\nLOGGER = LogUtil.get_instance()\nTAG = 'suppress masker'\n\n\nclass SuppressMasker(Callback):\n    \"\"\"\n    Periodicity check suppress privacy function status and toggle suppress operation.\n    For details, please check `Protecting User Privacy with Suppression Privacy\n    <https://mindspore.cn/mindarmour/docs/en/master/protect_user_privacy_with_suppress_privacy.html>`_.\n\n    Args:\n        model (SuppressModel):  SuppressModel instance.\n        suppress_ctrl (SuppressCtrl): SuppressCtrl instance.\n\n    Examples:\n        >>> import mindspore.nn as nn\n        >>> import mindspore as ms\n        >>> from mindspore import set_context, ops\n        >>> from mindspore.nn import Accuracy\n        >>> from mindarmour.privacy.sup_privacy import SuppressModel\n        >>> from mindarmour.privacy.sup_privacy import SuppressMasker\n        >>> from mindarmour.privacy.sup_privacy import SuppressPrivacyFactory\n        >>> from mindarmour.privacy.sup_privacy import MaskLayerDes\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = ops.Softmax()\n        ...         self._Dense = nn.Dense(10,10)\n        ...         self._squeeze = ops.Squeeze(1)\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         out = self._Dense(out)\n        ...         return self._squeeze(out)\n        >>> set_context(mode=ms.PYNATIVE_MODE, device_target=\"GPU\")\n        >>> network = Net()\n        >>> masklayers = []\n        >>> masklayers.append(MaskLayerDes(\"_Dense.weight\", 0, False, True, 10))\n        >>> suppress_ctrl_instance = SuppressPrivacyFactory().create(networks=network,\n        ...                                                          mask_layers=masklayers,\n        ...                                                          policy=\"local_train\",\n        ...                                                          end_epoch=10,\n        ...                                                          batch_num=1,\n        ...                                                          start_epoch=3,\n        ...                                                          mask_times=10,\n        ...                                                          lr=0.05,\n        ...                                                          sparse_end=0.95,\n        ...                                                          sparse_start=0.0)\n        >>> net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction=\"mean\")\n        >>> net_opt = nn.SGD(network.trainable_params(), 0.05)\n        >>> model_instance = SuppressModel(network=network,\n        ...                                loss_fn=net_loss,\n        ...                                optimizer=net_opt,\n        ...                                metrics={\"Accuracy\": Accuracy()})\n        >>> model_instance.link_suppress_ctrl(suppress_ctrl_instance)\n        >>> masker_instance = SuppressMasker(model_instance, suppress_ctrl_instance)\n    \"\"\"\n\n    def __init__(self, model, suppress_ctrl):\n\n        super(SuppressMasker, self).__init__()\n\n        self._model = check_param_type('model', model, SuppressModel)\n        self._suppress_ctrl = check_param_type('suppress_ctrl', suppress_ctrl, SuppressCtrl)\n\n    def step_end(self, run_context):\n        \"\"\"\n        Update mask matrix tensor used for SuppressModel instance.\n\n        Args:\n            run_context (RunContext): Include some information of the model.\n        \"\"\"\n        cb_params = run_context.original_args()\n        cur_step = cb_params.cur_step_num\n        cur_step_in_epoch = (cb_params.cur_step_num - 1) % cb_params.batch_num + 1\n\n        if self._suppress_ctrl is not None and self._model.network_end is not None:\n            if not self._suppress_ctrl.mask_initialized:\n                raise ValueError(\"Not initialize network!\")\n            if cur_step_in_epoch % 100 == 1:\n                self._suppress_ctrl.calc_theoretical_sparse_for_conv()\n                _, _, _ = self._suppress_ctrl.calc_actual_sparse_for_conv(\n                    self._suppress_ctrl.networks)\n            self._suppress_ctrl.update_status(cb_params.cur_epoch_num, cur_step, cur_step_in_epoch)\n            if self._suppress_ctrl.to_do_mask:\n                self._suppress_ctrl.update_mask(self._suppress_ctrl.networks, cur_step)\n                LOGGER.info(TAG, \"suppress update\")\n            elif not self._suppress_ctrl.to_do_mask and self._suppress_ctrl.mask_started:\n                self._suppress_ctrl.reset_zeros()\n"
  },
  {
    "path": "mindarmour/privacy/sup_privacy/sup_ctrl/__init__.py",
    "content": ""
  },
  {
    "path": "mindarmour/privacy/sup_privacy/sup_ctrl/conctrl.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\ncontrol function of suppress-based privacy.\n\"\"\"\nimport math\nimport gc\nimport numpy as np\n\nfrom mindspore import Tensor\nfrom mindspore.ops import operations as P\nfrom mindspore.common import dtype as mstype\nfrom mindspore.nn import Cell\n\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_int_positive, check_value_positive, \\\n    check_value_non_negative, check_param_type\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Suppression training.'\n\n\nclass SuppressPrivacyFactory:\n    \"\"\"\n    Factory class of SuppressCtrl mechanisms.\n\n    For details, please check `Protecting User Privacy with Suppress Privacy\n    <https://mindspore.cn/mindarmour/docs/en/master/protect_user_privacy_with_suppress_privacy.html>`_.\n    \"\"\"\n\n    def __init__(self):\n        pass\n\n    @staticmethod\n    def create(networks, mask_layers, policy=\"local_train\", end_epoch=10, batch_num=20, start_epoch=3,\n               mask_times=1000, lr=0.05, sparse_end=0.90, sparse_start=0.0):\n        \"\"\"\n        Args:\n            networks (Cell): The training network.\n                This networks parameter should be same as `network` parameter of `SuppressModel()`.\n            mask_layers (list): Description of the training network layers that need to be suppressed.\n            policy (str): Training policy for suppress privacy training. Default: ``\"local_train\"``,\n                means local training.\n            end_epoch (int): The last epoch in suppress operations, 0<start_epoch<=end_epoch<=100. Default: ``10``.\n                This end_epoch parameter should be same as `epoch` parameter of `mindspore.train.model.train()`.\n            batch_num (int): The num of batches in an epoch, should be equal to num_samples/batch_size.\n                Default: ``20``.\n            start_epoch (int): The first epoch in suppress operations, 0<start_epoch<=end_epoch<=100.\n                Default: ``3``.\n            mask_times (int): The num of suppress operations. Default: ``1000``.\n            lr (Union[float, int]): Learning rate, should be unchanged during training. 0<lr<=0.50.\n                Default: ``0.05``. This `lr` parameter should be same as `learning_rate` parameter of\n                `mindspore.nn.SGD()`.\n            sparse_end (float): The sparsity to reach, 0.0<=sparse_start<sparse_end<1.0. Default: ``0.90``.\n            sparse_start (Union[float, int]): The sparsity to start, 0.0<=sparse_start<sparse_end<1.0.\n                Default: ``0.0``.\n\n        Returns:\n            SuppressCtrl, class of Suppress Privavy Mechanism.\n\n        Examples:\n            >>> import mindspore.nn as nn\n            >>> import mindspore as ms\n            >>> from mindspore import set_context, ops\n            >>> from mindspore.nn import Accuracy\n            >>> from mindarmour.privacy.sup_privacy import SuppressPrivacyFactory\n            >>> from mindarmour.privacy.sup_privacy import MaskLayerDes\n            >>> from mindarmour.privacy.sup_privacy import SuppressModel\n            >>> class Net(nn.Cell):\n            ...     def __init__(self):\n            ...         super(Net, self).__init__()\n            ...         self._softmax = ops.Softmax()\n            ...         self._Dense = nn.Dense(10,10)\n            ...         self._squeeze = ops.Squeeze(1)\n            ...     def construct(self, inputs):\n            ...         out = self._softmax(inputs)\n            ...         out = self._Dense(out)\n            ...         return self._squeeze(out)\n            >>> set_context(mode=ms.PYNATIVE_MODE, device_target=\"CPU\")\n            >>> network = Net()\n            >>> masklayers = []\n            >>> masklayers.append(MaskLayerDes(\"_Dense.weight\", 0, False, True, 10))\n            >>> suppress_ctrl_instance = SuppressPrivacyFactory().create(networks=network,\n            ...                                                          mask_layers=masklayers,\n            ...                                                          policy=\"local_train\",\n            ...                                                          end_epoch=10,\n            ...                                                          batch_num=1,\n            ...                                                          start_epoch=3,\n            ...                                                          mask_times=10,\n            ...                                                          lr=0.05,\n            ...                                                          sparse_end=0.95,\n            ...                                                          sparse_start=0.0)\n            >>> net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction=\"mean\")\n            >>> net_opt = nn.SGD(network.trainable_params(), 0.05)\n            >>> model_instance = SuppressModel(network=network,\n            ...                                loss_fn=net_loss,\n            ...                                optimizer=net_opt,\n            ...                                metrics={\"Accuracy\": Accuracy()})\n            >>> model_instance.link_suppress_ctrl(suppress_ctrl_instance)\n        \"\"\"\n        check_param_type('policy', policy, str)\n        if policy == \"local_train\":\n            return SuppressCtrl(networks, mask_layers, end_epoch, batch_num, start_epoch, mask_times, lr,\n                                sparse_end, sparse_start)\n        msg = \"Only local training is supported now, but got {}.\".format(policy)\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n\n\nclass SuppressCtrl(Cell):\n    \"\"\"\n    Complete suppress privacy operation, including computing suppress ration,\n    finding the parameters that should be suppressed, and suppress these\n    parameters permanently.\n\n    For details, please check `Protecting User Privacy with Suppress Privacy\n    <https://mindspore.cn/mindarmour/docs/en/master/protect_user_privacy_with_suppress_privacy.html>`_.\n\n    Args:\n        networks (Cell): The training network.\n        mask_layers (list): Description of those layers that need to be suppressed.\n        end_epoch (int): The last epoch in suppress operations.\n        batch_num (int): The num of grad operation in an epoch.\n        start_epoch (int): The first epoch in suppress operations.\n        mask_times (int): The num of suppress operations.\n        lr (Union[float, int]): Learning rate.\n        sparse_end (float): The sparsity to reach.\n        sparse_start (Union[float, int]): The sparsity to start.\n    \"\"\"\n\n    def __init__(self, networks, mask_layers, end_epoch, batch_num, start_epoch, mask_times, lr,\n                 sparse_end, sparse_start):\n        super(SuppressCtrl, self).__init__()\n        self.networks = check_param_type('networks', networks, Cell)\n        self.mask_layers = check_param_type('mask_layers', mask_layers, list)\n        self.mask_end_epoch = check_int_positive('end_epoch', end_epoch)\n        self.batch_num = check_int_positive('batch_num', batch_num)\n        self.mask_start_epoch = check_int_positive('start_epoch', start_epoch)\n        self.mask_times = check_int_positive('mask_times', mask_times)\n        self.lr = check_value_positive('lr', lr)\n        self.sparse_end = check_param_type('sparse_end', sparse_end, float)\n        self.sparse_start = check_value_non_negative('sparse_start', sparse_start)\n\n        self.weight_lower_bound = 0.005  # all network weight will be larger than this value\n        self.sparse_vibra = 0.02  # the sparsity may have certain range of variations\n        self.sparse_valid_max_weight = 0.02  # if max network weight is less than this value, operation stop temporarily\n        self.add_noise_thd = 0.50  # if network weight is more than this value, noise is forced\n        self.noise_volume = 0.1  # noise volume 0.1\n        self.base_ground_thd = 0.0000001  # if network weight is less than this value, will be considered as 0\n        self.model = None  # SuppressModel instance\n        self.grads_mask_list = []  # list for Grad Mask Matrix tensor\n        self.de_weight_mask_list = []  # list for weight Mask Matrix tensor\n        self.to_do_mask = False  # the flag means suppress operation is toggled immediately\n        self.mask_started = False  # the flag means suppress operation has been started\n        self.mask_start_step = 0  # suppress operation is actually started at this step\n        self.mask_prev_step = 0  # previous suppress operation is done at this step\n        self.cur_sparse = 0.0  # current sparsity to which one suppress will get\n        self.mask_all_steps = (end_epoch - start_epoch + 1) * batch_num  # the amount of step contained in all operation\n        self.mask_step_interval = self.mask_all_steps / mask_times  # the amount of step contained in one operation\n        self.mask_initialized = False  # flag means the initialization is done\n        self.grad_idx_map = []\n\n        self._check_params()\n\n        if mask_layers is not None:\n            self._check_mask_layers()\n\n        if networks is not None:\n            for layer in networks.get_parameters(expand=True):\n                shape = np.shape([1])\n                mul_mask_array = np.ones(shape, dtype=np.float32)\n                grad_mask_cell = GradMaskInCell(mul_mask_array, False, False, -1)\n                grad_mask_cell.mask_able = False\n                self.grads_mask_list.append(grad_mask_cell)\n\n                add_mask_array = np.zeros(shape, dtype=np.float32)\n                de_weight_cell = DeWeightInCell(add_mask_array)\n                de_weight_cell.mask_able = False\n                self.de_weight_mask_list.append(de_weight_cell)\n\n                self.grad_idx_map.append(-1)\n\n            m = 0\n            for layer in networks.get_parameters(expand=True):\n                one_mask_layer = None\n                if mask_layers is not None:\n                    one_mask_layer = get_one_mask_layer(mask_layers, layer.name)\n                if one_mask_layer is not None and not one_mask_layer.inited:\n                    one_mask_layer.inited = True\n                    shape = P.Shape()(layer)\n                    mul_mask_array = np.ones(shape, dtype=np.float32)\n                    grad_mask_cell = GradMaskInCell(mul_mask_array,\n                                                    one_mask_layer.is_add_noise,\n                                                    one_mask_layer.is_lower_clip,\n                                                    one_mask_layer.min_num,\n                                                    one_mask_layer.upper_bound)\n                    grad_mask_cell.mask_able = True\n                    self.grads_mask_list[one_mask_layer.grad_idx] = grad_mask_cell\n\n                    add_mask_array = np.zeros(shape, dtype=np.float32)\n                    de_weight_cell = DeWeightInCell(add_mask_array)\n                    de_weight_cell.mask_able = True\n                    self.de_weight_mask_list[one_mask_layer.grad_idx] = de_weight_cell\n                    self.grad_idx_map[m] = one_mask_layer.grad_idx\n                    msg = \"do mask {}, {}, {}\".format(m, one_mask_layer.layer_name, one_mask_layer.grad_idx)\n                    LOGGER.info(TAG, msg)\n                elif one_mask_layer is not None and one_mask_layer.inited:\n                    msg = \"repeated match masked setting {}=>{}.\".format(one_mask_layer.layer_name, layer.name)\n                    LOGGER.error(TAG, msg)\n                    raise ValueError(msg)\n                m += 1\n            self.mask_initialized = True\n            msg = \"init SuppressCtrl by networks\"\n            LOGGER.info(TAG, msg)\n        msg = \"complete init mask for lenet5.step_interval: {}\".format(self.mask_step_interval)\n        LOGGER.info(TAG, msg)\n\n        for one_mask_layer in mask_layers:\n            if not one_mask_layer.inited:\n                msg = \"can't match this mask layer: {} \".format(one_mask_layer.layer_name)\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n        msg = \"\\nThis networks parameter should be same as 'network' parameter of SuppressModel()\"\n        msg += \"\\nThis lr parameter should be same as 'learning_rate' parameter of mindspore.nn.SGD()\\n\"\n        msg += \"\\nThis end_epoch parameter should be same as 'epoch' parameter of mindspore.train.model.train()\\n\"\n        msg += \"\\nsup_privacy only support SGD optimizer\"\n        LOGGER.warn(TAG, msg)\n\n    def _check_params(self):\n        \"\"\"check parameters\"\"\"\n        if self.lr > 0.5:\n            msg = \"learning rate should not be greater than 0.5, but got {}\".format(self.lr)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n        if self.mask_start_epoch > self.mask_end_epoch:\n            msg = \"start_epoch should not be greater than end_epoch, but got start_epoch and end_epoch are: \" \\\n                  \"{}, {}\".format(self.mask_start_epoch, self.mask_end_epoch)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n        if self.mask_end_epoch > 100:\n            msg = \"The end_epoch should be smaller than 100, but got {}\".format(self.mask_end_epoch)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n        if self.mask_step_interval <= 0:\n            msg = \"step_interval should be greater than 0, but got {}\".format(self.mask_step_interval)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n        if self.mask_step_interval <= 10 or self.mask_step_interval >= 20:\n            msg = \"mask_interval should be greater than 10, smaller than 20, but got {}\".format(self.mask_step_interval)\n            msg += \"\\n Precision of trained model may be poor !!! \"\n            msg += \"\\n please modify epoch_start, epoch_end and batch_num !\"\n            msg += \"\\n mask_interval = (epoch_end-epoch_start+1)*batch_num/mask_times, batch_num = samples/batch_size\"\n            LOGGER.info(TAG, msg)\n\n        if self.sparse_end >= 1.00 or self.sparse_end <= 0:\n            msg = \"sparse_end should be in range (0, 1), but got {}\".format(self.sparse_end)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n        if self.sparse_start >= self.sparse_end:\n            msg = \"sparse_start should be smaller than sparse_end, but got sparse_start and sparse_end are: \" \\\n                  \"{}, {}\".format(self.sparse_start, self.sparse_end)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n    def _check_mask_layers(self):\n        \"\"\"check mask layers\"\"\"\n        mask_layer_id = 0\n        for one_mask_layer in self.mask_layers:\n            if not isinstance(one_mask_layer, MaskLayerDes):\n                msg = \"mask_layers should be a list of MaskLayerDes, but got a {}\".format(type(one_mask_layer))\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n            layer_name = one_mask_layer.layer_name\n            mask_layer_id2 = 0\n            for one_mask_layer_2 in self.mask_layers:\n                if mask_layer_id != mask_layer_id2 and layer_name == one_mask_layer_2.layer_name:\n                    msg = \"Mask layer name should be unique, but got duplicate name: {} in mask_layer {} and {}\". \\\n                        format(layer_name, mask_layer_id, mask_layer_id2)\n                    LOGGER.error(TAG, msg)\n                    raise ValueError(msg)\n                if mask_layer_id != mask_layer_id2 and one_mask_layer.grad_idx == one_mask_layer_2.grad_idx:\n                    msg = \"Grad_idx should be unique, but got duplicate idx: {} in mask_layer {} and {}\". \\\n                        format(layer_name, one_mask_layer_2.layer_name, one_mask_layer.grad_idx)\n                    LOGGER.error(TAG, msg)\n                    raise ValueError(msg)\n                mask_layer_id2 = mask_layer_id2 + 1\n            mask_layer_id = mask_layer_id + 1\n\n    def update_status(self, cur_epoch, cur_step, cur_step_in_epoch):\n        \"\"\"\n        Update the suppress operation status.\n\n        Args:\n            cur_epoch (int): Current epoch of the whole training process.\n            cur_step (int): Current step of the whole training process.\n            cur_step_in_epoch (int): Current step of the current epoch.\n        \"\"\"\n        if not self.mask_initialized:\n            self.mask_started = False\n        elif (self.mask_start_epoch <= cur_epoch <= self.mask_end_epoch) or self.mask_started:\n            if not self.mask_started:\n                self.mask_started = True\n                self.mask_start_step = cur_step\n            if cur_step >= (self.mask_prev_step + self.mask_step_interval):\n                self.mask_prev_step = cur_step\n                self.to_do_mask = True\n            # execute the last suppression operation\n            elif cur_epoch == self.mask_end_epoch and cur_step_in_epoch == self.batch_num - 2:\n                self.mask_prev_step = cur_step\n                self.to_do_mask = True\n            else:\n                self.to_do_mask = False\n        else:\n            self.to_do_mask = False\n            self.mask_started = False\n\n    def update_mask(self, networks, cur_step, target_sparse=0.0):\n        \"\"\"\n        Update add mask arrays and multiply mask arrays of network layers.\n\n        Args:\n            networks (Cell): The training network.\n            cur_step (int): Current epoch of the whole training process.\n            target_sparse(float): The sparsity to reach. Default: ``0.0``.\n        \"\"\"\n        if self.sparse_end <= 0.0:\n            return\n\n        last_sparse = self.cur_sparse\n        if target_sparse > 0.0:\n            self.cur_sparse = target_sparse\n        else:\n            self.cur_sparse = self.sparse_end + \\\n                              (self.sparse_start - self.sparse_end) * \\\n                              math.pow((1.0 - (cur_step + 0.0 - self.mask_start_step) / self.mask_all_steps), 3)\n        self.cur_sparse = max(self.sparse_start, max(last_sparse, min(self.cur_sparse, self.sparse_end)))\n        m = 0\n        for layer in networks.get_parameters(expand=True):\n            grad_idx = self.grad_idx_map[m]\n            if grad_idx < 0:\n                m = m + 1\n                continue\n            if self.grads_mask_list[grad_idx].mask_able:\n                len_array = self.grads_mask_list[grad_idx].para_num\n                min_num = self.grads_mask_list[grad_idx].min_num\n                sparse_min_thd = 1.0 - min(min_num, len_array) / len_array\n                actual_stop_pos = int(len_array * min(sparse_min_thd, self.cur_sparse))\n\n                grad_mask_cell = self.grads_mask_list[grad_idx]\n                last_sparse_pos = grad_mask_cell.sparse_pos_list[-1]\n                if actual_stop_pos <= 0 or \\\n                        (actual_stop_pos < last_sparse_pos + grad_mask_cell.part_num and \\\n                         grad_mask_cell.is_approximity and m > 0):\n                    sparse_weight_thd = 0\n                    msg = \"{} len={}, sparse={}, current sparse thd={}, [idle] \\n\" \\\n                        .format(layer.name, len_array, actual_stop_pos / len_array, sparse_weight_thd)\n                    LOGGER.info(TAG, msg)\n                    m = m + 1\n                    continue\n\n                weight_array = layer.data.asnumpy()\n                weight_avg = np.mean(weight_array)\n                weight_array_flat = weight_array.flatten()\n                weight_array_flat_abs = np.abs(weight_array_flat)\n                weight_abs_avg = np.mean(weight_array_flat_abs)\n                weight_abs_max = np.max(weight_array_flat_abs)\n                weight_abs_min = np.min(weight_array_flat_abs)\n\n                if m == 0 and weight_abs_max < self.sparse_valid_max_weight:\n                    msg = \"layer 0 weight_abs_max = {}, give up this masking ... \".format(weight_abs_max)\n                    LOGGER.info(TAG, msg)\n                    del weight_array_flat_abs\n                    del weight_array_flat\n                    del weight_array\n                    gc.collect()\n                    return\n\n                if grad_mask_cell.is_approximity and m > 0:\n                    sparse_weight_thd = self.update_mask_layer_approximity(weight_array_flat, weight_array_flat_abs,\n                                                                           actual_stop_pos, grad_idx)\n                else:\n                    partition = np.partition(weight_array_flat_abs, actual_stop_pos - 1)\n                    sparse_weight_thd = partition[actual_stop_pos - 1]\n                    self.update_mask_layer(weight_array_flat, sparse_weight_thd, actual_stop_pos,\n                                           weight_abs_max, grad_idx)\n                    del partition\n\n                msg = \"{} len={}, sparse={}, current sparse thd={}, max={}, min={}, avg={}, avg_abs={} \\n\".format(\n                    layer.name, len_array, actual_stop_pos / len_array, sparse_weight_thd,\n                    weight_abs_max, weight_abs_min, weight_avg, weight_abs_avg)\n                LOGGER.info(TAG, msg)\n                del weight_array_flat_abs\n                del weight_array_flat\n                del weight_array\n                gc.collect()\n            m = m + 1\n\n    def update_mask_layer(self, weight_array_flat, sparse_weight_thd, sparse_stop_pos, weight_abs_max, layer_index):\n        \"\"\"\n        Update add mask arrays and multiply mask arrays of one single layer.\n\n        Args:\n            weight_array_flat (numpy.ndarray): The weight array of layer's parameters.\n            sparse_weight_thd (float): The weight threshold of sparse operation.\n            sparse_stop_pos (int): The maximum number of elements to be suppressed.\n            weight_abs_max (float): The maximum absolute value of weights.\n            layer_index (int): The index of target layer.\n        \"\"\"\n        grad_mask_cell = self.grads_mask_list[layer_index]\n        mul_mask_array_flat = grad_mask_cell.mul_mask_array_flat\n        de_weight_cell = self.de_weight_mask_list[layer_index]\n        add_mask_array_flat = de_weight_cell.add_mask_array_flat\n        min_num = grad_mask_cell.min_num\n        is_add_noise = grad_mask_cell.is_add_noise\n        is_lower_clip = grad_mask_cell.is_lower_clip\n        upper_bound = grad_mask_cell.upper_bound\n\n        if not self.grads_mask_list[layer_index].mask_able:\n            return\n        m = 0\n        n = 0\n        p = 0\n        q = 0\n        # add noise on weights if not masking or clipping.\n        weight_noise_bound = min(self.add_noise_thd, max(self.noise_volume * 10, weight_abs_max * 0.75))\n        size = self.grads_mask_list[layer_index].para_num\n        for i in range(0, size):\n            if mul_mask_array_flat[i] <= 0.0:\n                add_mask_array_flat[i] = weight_array_flat[i] / self.lr\n                m = m + 1\n            elif abs(weight_array_flat[i]) <= sparse_weight_thd:\n                if m < size - min_num and m < sparse_stop_pos:\n                    # to mask\n                    mul_mask_array_flat[i] = 0.0\n                    add_mask_array_flat[i] = weight_array_flat[i] / self.lr\n                    m = m + 1\n                else:\n                    # not mask\n                    if weight_array_flat[i] > 0.0:\n                        add_mask_array_flat[i] = (weight_array_flat[i]\n                                                  - min(self.weight_lower_bound, sparse_weight_thd)) / self.lr\n                    else:\n                        add_mask_array_flat[i] = (weight_array_flat[i]\n                                                  + min(self.weight_lower_bound, sparse_weight_thd)) / self.lr\n                    p = p + 1\n            elif is_lower_clip and abs(weight_array_flat[i]) <= \\\n                    self.weight_lower_bound and sparse_weight_thd > self.weight_lower_bound * 0.5:\n                # not mask\n                mul_mask_array_flat[i] = 1.0\n                if weight_array_flat[i] > 0.0:\n                    add_mask_array_flat[i] = (weight_array_flat[i] - self.weight_lower_bound) / self.lr\n                else:\n                    add_mask_array_flat[i] = (weight_array_flat[i] + self.weight_lower_bound) / self.lr\n                p = p + 1\n            elif abs(weight_array_flat[i]) > upper_bound:\n                mul_mask_array_flat[i] = 1.0\n                if weight_array_flat[i] > 0.0:\n                    add_mask_array_flat[i] = (weight_array_flat[i] - upper_bound) / self.lr\n                else:\n                    add_mask_array_flat[i] = (weight_array_flat[i] + upper_bound) / self.lr\n                n = n + 1\n            else:\n                # not mask\n                mul_mask_array_flat[i] = 1.0\n                if is_add_noise and abs(weight_array_flat[i]) > weight_noise_bound > 0.0:\n                    # add noise\n                    add_mask_array_flat[i] = np.random.uniform(-self.noise_volume, self.noise_volume) / self.lr\n                    q = q + 1\n                else:\n                    add_mask_array_flat[i] = 0.0\n\n        grad_mask_cell.update()\n        de_weight_cell.update()\n        msg = \"Dimension of mask tensor is {}D, which located in the {}-th layer of the network. \\n The number of \" \\\n              \"suppressed elements, max-clip elements, min-clip elements and noised elements are {}, {}, {}, {}\" \\\n            .format(len(grad_mask_cell.mul_mask_array_shape), layer_index, m, n, p, q)\n        LOGGER.info(TAG, msg)\n        grad_mask_cell.sparse_pos_list.append(m)\n\n    def update_mask_layer_approximity(self, weight_array_flat, weight_array_flat_abs, actual_stop_pos, layer_index):\n        \"\"\"\n        Update add mask arrays and multiply mask arrays of one single layer with many parameter.\n        Disable clipping lower, clipping, adding noise operation\n\n        Args:\n            weight_array_flat (numpy.ndarray): The weight array of layer's parameters.\n            weight_array_flat_abs (numpy.ndarray): The abs weight array of layer's parameters.\n            actual_stop_pos (int): The actually para num should be suppressed.\n            layer_index (int): The index of target layer.\n        \"\"\"\n        grad_mask_cell = self.grads_mask_list[layer_index]\n        mul_mask_array_flat = grad_mask_cell.mul_mask_array_flat\n        de_weight_cell = self.de_weight_mask_list[layer_index]\n        add_mask_array_flat = de_weight_cell.add_mask_array_flat\n\n        part_size = grad_mask_cell.part_size\n        part_num = grad_mask_cell.part_num\n        para_num = grad_mask_cell.para_num\n        init_batch_suppress = False\n\n        if not self.grads_mask_list[layer_index].mask_able:\n            return 0.0\n        real_part_num = 0\n        sparse_thd = 0.0\n        last_sparse_pos = grad_mask_cell.sparse_pos_list[-1]\n        split_k_num = max(0, int((actual_stop_pos - last_sparse_pos) / part_num))\n        if last_sparse_pos <= 0:\n            init_batch_suppress = True\n        for i in range(0, part_num):\n            if split_k_num <= 0:\n                break\n            array_row_mul_mask = mul_mask_array_flat[i * part_size: (i + 1) * part_size]\n            array_row_flat_abs = weight_array_flat_abs[i * part_size: (i + 1) * part_size]\n            if not init_batch_suppress:\n                array_row_flat_abs_masked = np.where(array_row_mul_mask <= 0.0, -1.0, array_row_flat_abs)\n                set_abs = set(array_row_flat_abs_masked)\n                set_abs.remove(-1.0)\n                list2 = list(set_abs)\n                val_array_align = np.array(list2)\n                del array_row_flat_abs_masked\n                del set_abs\n                del list2\n            else:\n                val_array_align = array_row_flat_abs\n\n            real_split_k_num = min(split_k_num, len(val_array_align) - 1)\n            if real_split_k_num <= 0:\n                del array_row_flat_abs\n                del array_row_mul_mask\n                del val_array_align\n                continue\n\n            partition = np.partition(val_array_align, real_split_k_num - 1)\n            sparse_k_thd = partition[real_split_k_num - 1]\n            if sparse_k_thd > 0 or init_batch_suppress:\n                real_part_num = real_part_num + 1\n                sparse_thd = sparse_thd + sparse_k_thd\n            del array_row_flat_abs\n            del array_row_mul_mask\n            del val_array_align\n            del partition\n\n        if real_part_num > 0:\n            sparse_thd = sparse_thd / real_part_num\n            new_mul_mask_array_flat = np.where(weight_array_flat_abs <= sparse_thd, 0.0, 1.0)\n            grad_mask_cell.mul_mask_array_flat = new_mul_mask_array_flat\n            new_add_mask_array_flat = np.where(new_mul_mask_array_flat <= 0.0, weight_array_flat / self.lr, 0.0)\n            de_weight_cell.add_mask_array_flat = new_add_mask_array_flat\n            grad_mask_cell.update()\n            de_weight_cell.update()\n            del mul_mask_array_flat\n            del add_mask_array_flat\n            gc.collect()\n            real_suppress_num = para_num - int(np.sum(grad_mask_cell.mul_mask_array_flat))\n            grad_mask_cell.sparse_pos_list.append(real_suppress_num)\n        else:\n            real_suppress_num = 0\n\n        msg = \"Dimension of mask tensor is {}D, which located in the {}-th layer of the network. \" \\\n              \"\\n The ideal number of suppressed elements is {}/{}/{}, real suppress elements is {}\" \\\n            .format(len(grad_mask_cell.mul_mask_array_shape), layer_index,\n                    split_k_num, (actual_stop_pos - last_sparse_pos), actual_stop_pos, real_suppress_num)\n        LOGGER.info(TAG, msg)\n        if init_batch_suppress:\n            init_sparse_actual = real_suppress_num / para_num\n            print(\"init batch suppresss, actual sparse = {}\".format(init_sparse_actual))\n\n        gc.collect()\n        return sparse_thd\n\n    def reset_zeros(self):\n        \"\"\"\n        Set add mask arrays to be zero.\n        \"\"\"\n        for de_weight_cell in self.de_weight_mask_list:\n            de_weight_cell.reset_zeros()\n\n    def calc_theoretical_sparse_for_conv(self):\n        \"\"\"\n        Compute actually sparsity of mask matrix for conv1 layer and conv2 layer.\n        \"\"\"\n        array_mul_mask_flat_conv1 = self.grads_mask_list[0].mul_mask_array_flat\n        array_mul_mask_flat_conv2 = self.grads_mask_list[1].mul_mask_array_flat\n        sparse = 0.0\n        sparse_value_1 = 0.0\n        sparse_value_2 = 0.0\n        full = 0.0\n        full_conv1 = 0.0\n        full_conv2 = 0.0\n        for i in range(0, array_mul_mask_flat_conv1.size):\n            full += 1.0\n            full_conv1 += 1.0\n            if array_mul_mask_flat_conv1[i] <= 0.0:\n                sparse += 1.0\n                sparse_value_1 += 1.0\n        for i in range(0, array_mul_mask_flat_conv2.size):\n            full = full + 1.0\n            full_conv2 = full_conv2 + 1.0\n            if array_mul_mask_flat_conv2[i] <= 0.0:\n                sparse = sparse + 1.0\n                sparse_value_2 += 1.0\n        sparse = sparse / full\n        sparse_value_1 = sparse_value_1 / full_conv1\n        sparse_value_2 = sparse_value_2 / full_conv2\n        msg = \"conv sparse mask={}, sparse_1={}, sparse_2={}\".format(sparse, sparse_value_1, sparse_value_2)\n        LOGGER.info(TAG, msg)\n        return sparse, sparse_value_1, sparse_value_2\n\n    def calc_actual_sparse_for_conv(self, networks):\n        \"\"\"\n        Compute actually sparsity of network for conv1 layer and conv2 layer.\n\n        Args:\n            networks (Cell): The training network.\n        \"\"\"\n        sparse = 0.0\n        sparse_value_1 = 0.0\n        sparse_value_2 = 0.0\n        full = 0.0\n        full_conv1 = 0.0\n        full_conv2 = 0.0\n\n        conv1_matched = False\n        conv2_matched = False\n\n        array_cur_conv1 = np.ones(np.shape([1]), dtype=np.float32)\n        array_cur_conv2 = np.ones(np.shape([1]), dtype=np.float32)\n        for layer in networks.get_parameters(expand=True):\n            if not conv1_matched and \\\n                    (\"networks.conv1.weight\" in layer.name or \"networks.layers.0.weight\" in layer.name):\n                # lenet5/res50 vgg16\n                array_cur_conv1 = layer.data.asnumpy()\n                print(\"calc_actual_sparse, match conv1: {}\".format(layer.name))\n                conv1_matched = True\n            if not conv2_matched and \\\n                    (\"networks.conv2.weight\" in layer.name or \"networks.layers.3.weight\" in layer.name \\\n                     or \"networks.layer1.0.conv1.weight\" in layer.name):  # res50\n                array_cur_conv2 = layer.data.asnumpy()\n                print(\"calc_actual_sparse, match conv2: {}\".format(layer.name))\n                conv2_matched = True\n\n        array_mul_mask_flat_conv1 = array_cur_conv1.flatten()\n        array_mul_mask_flat_conv2 = array_cur_conv2.flatten()\n\n        for i in range(0, array_mul_mask_flat_conv1.size):\n            full += 1.0\n            full_conv1 += 1.0\n            if abs(array_mul_mask_flat_conv1[i]) <= self.base_ground_thd:\n                sparse += 1.0\n                sparse_value_1 += 1.0\n\n        for i in range(0, array_mul_mask_flat_conv2.size):\n            full = full + 1.0\n            full_conv2 = full_conv2 + 1.0\n            if abs(array_mul_mask_flat_conv2[i]) <= self.base_ground_thd:\n                sparse = sparse + 1.0\n                sparse_value_2 += 1.0\n\n        sparse = sparse / full\n        sparse_value_1 = sparse_value_1 / full_conv1\n        sparse_value_2 = sparse_value_2 / full_conv2\n        msg = \"conv sparse fact={}, sparse_1={}, sparse_2={}\".format(sparse, sparse_value_1, sparse_value_2)\n        LOGGER.info(TAG, msg)\n        del array_mul_mask_flat_conv1\n        del array_mul_mask_flat_conv2\n        del array_cur_conv1\n        del array_cur_conv2\n        gc.collect()\n        return sparse, sparse_value_1, sparse_value_2\n\n    def calc_actual_sparse_for_fc1(self, networks):\n        \"\"\"\n        Calculate actual sparse for full connection 1 layer\n\n        Args:\n            networks (Cell): The training network.\n        \"\"\"\n        return self.calc_actual_sparse_for_layer(networks, \"fc1.weight\")\n\n    def calc_actual_sparse_for_layer(self, networks, layer_name):\n        \"\"\"\n        Compute actually sparsity of one network layer\n\n        Args:\n            networks (Cell): The training network.\n            layer_name (str): The name of target layer.\n        \"\"\"\n        check_param_type('networks', networks, Cell)\n        check_param_type('layer_name', layer_name, str)\n\n        sparse = 0.0\n        full = 0.0\n\n        array_cur = None\n        for layer in networks.get_parameters(expand=True):\n            if layer_name in layer.name:\n                array_cur = layer.data.asnumpy()\n                break\n\n        if array_cur is None:\n            msg = \"no such layer to calc sparse: {} \".format(layer_name)\n            LOGGER.info(TAG, msg)\n            return 0.0\n\n        array_cur_flat = array_cur.flatten()\n\n        for i in range(0, array_cur_flat.size):\n            full += 1.0\n            if abs(array_cur_flat[i]) <= self.base_ground_thd:\n                sparse += 1.0\n\n        sparse = sparse / full\n        msg = \"{} sparse fact={} \".format(layer_name, sparse)\n        LOGGER.info(TAG, msg)\n        del array_cur_flat\n        del array_cur\n        gc.collect()\n        return sparse\n\n    def print_paras(self):\n        \"\"\"\n        Show parameters info\n        \"\"\"\n        msg = \"paras: start_epoch:{}, end_epoch:{}, batch_num:{}, interval:{}, lr:{}, sparse_end:{}, sparse_start:{}\" \\\n            .format(self.mask_start_epoch, self.mask_end_epoch, self.batch_num, self.mask_step_interval,\n                    self.lr, self.sparse_end, self.sparse_start)\n        LOGGER.info(TAG, msg)\n        msg = \"\\nThis networks parameter should be same as 'network' parameter of SuppressModel()\"\n        msg = \"\\nThis lr parameter should be same as 'learning_rate' parameter of mindspore.nn.SGD()\"\n        msg += \"\\nThis end_epoch parameter should be same as 'epoch' parameter of mindspore.train.model.train()\"\n        msg += \"\\nsup_privacy only support SGD optimizer\"\n        LOGGER.info(TAG, msg)\n\n\ndef get_one_mask_layer(mask_layers, layer_name):\n    \"\"\"\n    Returns the layer definitions that need to be suppressed.\n\n    Args:\n        mask_layers (list): The layers that need to be suppressed.\n        layer_name (str): The name of target layer.\n\n    Returns:\n        Union[MaskLayerDes, None], the layer definitions that need to be suppressed.\n    \"\"\"\n    for each_mask_layer in mask_layers:\n        if each_mask_layer.layer_name in layer_name and not each_mask_layer.inited:\n            return each_mask_layer\n    return None\n\n\nclass MaskLayerDes:\n    \"\"\"\n    Describe the layer that need to be suppressed.\n\n    Args:\n        layer_name (str): Layer name, get the name of one layer as following:\n\n            .. code-block::\n\n                for layer in networks.get_parameters(expand=True):\n                    if layer.name == \"conv\": ...\n\n        grad_idx (int): Mask layer's index in grad tuple.You can refer to the construct function\n            of TrainOneStepCell in mindarmour/privacy/sup_privacy/train/model.py to print the index of some specified\n            grad layers in PYNATIVE_MODE.\n        is_add_noise (bool): If True, the weight of this layer can add noise.\n            If False, the weight of this layer can not add noise.\n            If parameter num is greater than 100000, `is_add_noise` has no effect.\n        is_lower_clip (bool): If True, the weights of this layer would be clipped to greater than an lower bound value.\n            If False, the weights of this layer won't be clipped.\n            If parameter num is greater than 100000, `is_lower_clip` has no effect.\n        min_num (int): The number of weights left that not be suppressed.\n            If min_num is smaller than (parameter num*SupperssCtrl.sparse_end), `min_num` has not effect.\n        upper_bound (Union[float, int]): max abs value of weight in this layer, default: ``1.20``.\n            If parameter num is greater than 100000, `upper_bound` has not effect.\n\n    Examples:\n        >>> from mindarmour.privacy.sup_privacy import MaskLayerDes\n        >>> masklayers = []\n        >>> masklayers.append(MaskLayerDes(\"conv1.weight\", 0, False, True, 10))\n    \"\"\"\n\n    def __init__(self, layer_name, grad_idx, is_add_noise, is_lower_clip, min_num, upper_bound=1.20):\n        self.layer_name = check_param_type('layer_name', layer_name, str)\n        check_param_type('grad_idx', grad_idx, int)\n        self.grad_idx = check_value_non_negative('grad_idx', grad_idx)\n        self.is_add_noise = check_param_type('is_add_noise', is_add_noise, bool)\n        self.is_lower_clip = check_param_type('is_lower_clip', is_lower_clip, bool)\n        self.min_num = check_param_type('min_num', min_num, int)\n        self.upper_bound = check_value_positive('upper_bound', upper_bound)\n        self.inited = False\n\n\nclass GradMaskInCell(Cell):\n    \"\"\"\n    Define the mask matrix for gradients masking.\n\n    Args:\n        array (numpy.ndarray): The mask array.\n        is_add_noise (bool): If ``True``, the weight of this layer can add noise.\n            If ``False``, the weight of this layer can not add noise.\n        is_lower_clip (bool): If ``True``, the weights of this layer would be clipped to greater than an\n            lower bound value. If ``False``, the weights of this layer won't be clipped.\n        min_num (int): The number of weights left that not be suppressed.\n            If `min_num` is smaller than (parameter num*SupperssCtrl.sparse_end), `min_num` has no effect.\n        upper_bound ([float, int]): max abs value of weight in this layer, default: ``1.20``.\n    \"\"\"\n\n    def __init__(self, array, is_add_noise, is_lower_clip, min_num, upper_bound=1.20):\n        super(GradMaskInCell, self).__init__()\n        self.mul_mask_array_shape = array.shape\n        mul_mask_array = array.copy()\n        self.mul_mask_array_flat = mul_mask_array.flatten()\n        self.mul_mask_tensor = Tensor(array, mstype.float32)\n        self.mask_able = False\n        self.is_add_noise = is_add_noise\n        self.is_lower_clip = is_lower_clip\n        self.min_num = min_num\n        self.upper_bound = max(0.10, check_value_positive('upper_bound', upper_bound))\n\n        self.para_num = array.size\n        self.is_approximity = False\n        self.sparse_pos_list = [0]\n        self.part_num = 1\n        self.part_size = self.para_num\n        self.part_num_max = 16\n        self.para_many_num = 10000\n        self.para_huge_num = 10 * 10000 * 10000\n\n        if self.para_num > self.para_many_num:\n            self.is_approximity = True\n            self.is_add_noise = False\n            self.is_lower_clip = False\n\n            ratio = 2\n            if self.part_size > self.para_huge_num:\n                while self.part_size % ratio == 0 and self.part_size > self.para_huge_num \\\n                        and self.part_num < self.part_num_max:\n                    self.part_num = self.part_num * ratio\n                    self.part_size = int(self.part_size / ratio)\n            msg = \"this layer has {} para, disable the operation of clipping lower, clipping upper_bound, \" \\\n                  \"adding noise. \\n part_num={}, part_size={}\" \\\n                .format(self.para_num, self.part_num, self.part_size)\n            LOGGER.info(TAG, msg)\n\n    def construct(self):\n        \"\"\"\n        Return the mask matrix for optimization.\n        \"\"\"\n        return self.mask_able, self.mul_mask_tensor\n\n    def update(self):\n        \"\"\"\n        Update the mask tensor.\n        \"\"\"\n        self.mul_mask_tensor = Tensor(self.mul_mask_array_flat.reshape(self.mul_mask_array_shape), mstype.float32)\n\n\nclass DeWeightInCell(Cell):\n    \"\"\"\n    Define the mask matrix for de-weight masking.\n\n    Args:\n        array (numpy.ndarray): The mask array.\n    \"\"\"\n\n    def __init__(self, array):\n        super(DeWeightInCell, self).__init__()\n        self.add_mask_array_shape = array.shape\n        add_mask_array = array.copy()\n        self.add_mask_array_flat = add_mask_array.flatten()\n        self.add_mask_tensor = Tensor(array, mstype.float32)\n        self.mask_able = False\n        self.zero_mask_tensor = Tensor(np.zeros(array.shape, np.float32), mstype.float32)\n        self.just_update = -1.0\n\n    def construct(self):\n        \"\"\"\n        Return the mask matrix for optimization.\n        \"\"\"\n        if self.just_update > 0.0:\n            return self.mask_able, self.add_mask_tensor\n        return self.mask_able, self.zero_mask_tensor\n\n    def update(self):\n        \"\"\"\n        Update the mask tensor.\n        \"\"\"\n        self.just_update = 1.0\n        self.add_mask_tensor = Tensor(self.add_mask_array_flat.reshape(self.add_mask_array_shape), mstype.float32)\n\n    def reset_zeros(self):\n        \"\"\"\n        Make the de-weight operation expired.\n        \"\"\"\n        self.just_update = -1.0\n"
  },
  {
    "path": "mindarmour/privacy/sup_privacy/train/__init__.py",
    "content": ""
  },
  {
    "path": "mindarmour/privacy/sup_privacy/train/model.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nsuppress-basd privacy model.\n\"\"\"\nfrom easydict import EasyDict as edict\n\nfrom mindspore.train.model import Model\nfrom mindspore.train.amp import _config_level\nfrom mindspore.common import dtype as mstype\nfrom mindspore.nn.wrap.cell_wrapper import _VirtualDatasetCell\nfrom mindspore.parallel._utils import _get_parallel_mode\nfrom mindspore.train.model import ParallelMode\nfrom mindspore.train.amp import _do_keep_batchnorm_fp32\nfrom mindspore.train.amp import _add_loss_network\nfrom mindspore import nn\nfrom mindspore import context\nfrom mindspore.ops import composite as C\nfrom mindspore.ops import operations as P\nfrom mindspore.ops import functional as F\nfrom mindspore.parallel._utils import _get_gradients_mean\nfrom mindspore.parallel._utils import _get_device_num\nfrom mindspore.nn.wrap.grad_reducer import DistributedGradReducer\nfrom mindspore.nn import Cell\nfrom mindspore.nn.optim import SGD\nfrom mindarmour.utils import _check_param as validator\nfrom mindarmour.utils._check_param import check_param_type, check, check_value_type\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.privacy.sup_privacy.sup_ctrl.conctrl import SuppressCtrl\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Mask model'\n\nGRADIENT_CLIP_TYPE = 1\n_grad_scale = C.MultitypeFuncGraph(\"grad_scale\")\n_reciprocal = P.Reciprocal()\n\n\n@_grad_scale.register(\"Tensor\", \"Tensor\")\ndef tensor_grad_scale(scale, grad):\n    \"\"\" grad scaling \"\"\"\n    return grad*F.cast(_reciprocal(scale), F.dtype(grad))\n\n\nclass SuppressModel(Model):\n    \"\"\"\n    Suppress privacy training model, which is overload from mindspore.train.Model.\n\n    For details, please check `Protecting User Privacy with Suppress Privacy\n    <https://mindspore.cn/mindarmour/docs/en/master/protect_user_privacy_with_suppress_privacy.html>`_.\n\n    Args:\n        network (Cell): The training network.\n        loss_fn (Cell): Loss function of optimizers.\n        optimizer (Optimizer): optimizer instance.\n        kwargs: Keyword parameters used for creating a suppress model.\n    \"\"\"\n\n    def __init__(self,\n                 network,\n                 loss_fn,\n                 optimizer,\n                 **kwargs):\n\n        check_param_type('network', network, Cell)\n        check_param_type('optimizer', optimizer, SGD)\n\n        self.network_end = None\n        self._train_one_step = None\n\n        super(SuppressModel, self).__init__(network, loss_fn, optimizer, **kwargs)\n\n    def link_suppress_ctrl(self, suppress_pri_ctrl):\n        \"\"\"\n        Link self and SuppressCtrl instance.\n\n        Args:\n            suppress_pri_ctrl (SuppressCtrl): SuppressCtrl instance.\n        \"\"\"\n        check_param_type('suppress_pri_ctrl', suppress_pri_ctrl, SuppressCtrl)\n\n        suppress_pri_ctrl.model = self\n        if self._train_one_step is not None:\n            self._train_one_step.link_suppress_ctrl(suppress_pri_ctrl)\n\n    def _build_train_network(self):\n        \"\"\"Build train network\"\"\"\n        network = self._network\n\n        ms_mode = context.get_context(\"mode\")\n        if ms_mode != context.PYNATIVE_MODE:\n            raise ValueError(\"Only PYNATIVE_MODE is supported for suppress privacy now.\")\n\n        if self._optimizer:\n            network = self._amp_build_train_network(network,\n                                                    self._optimizer,\n                                                    self._loss_fn,\n                                                    level=self._amp_level,\n                                                    keep_batchnorm_fp32=self._keep_bn_fp32)\n        else:\n            raise ValueError(\"_optimizer is none\")\n\n        self._train_one_step = network\n\n        if self._parallel_mode in (ParallelMode.SEMI_AUTO_PARALLEL,\n                                   ParallelMode.AUTO_PARALLEL):\n            network.set_auto_parallel()\n\n        self.network_end = self._train_one_step.network\n        return network\n\n    def _amp_build_train_network(self, network, optimizer, loss_fn=None,\n                                 level='O0', **kwargs):\n        \"\"\"\n        Build the mixed precision training cell automatically.\n\n        Args:\n            network (Cell): Definition of the network.\n            loss_fn (Union[None, Cell]): Definition of the loss_fn. If None,\n                the `network` should have the loss inside. Default: ``None``.\n            optimizer (Optimizer): Optimizer to update the Parameter.\n            level (str): Supports [O0, O2]. Default: \"O0\".\n                - O0: Do not change.\n                - O2: Cast network to float16, keep batchnorm and `loss_fn`\n                  (if set) run in float32, using dynamic loss scale.\n            cast_model_type (:class:`mindspore.dtype`): Supports `mstype.float16`\n                or `mstype.float32`. If set to `mstype.float16`, use `float16`\n                mode to train. If set, overwrite the level setting.\n            keep_batchnorm_fp32 (bool): Keep Batchnorm run in `float32`. If set,\n                overwrite the level setting.\n            loss_scale_manager (Union[None, LossScaleManager]): If None, not\n                scale the loss, or else scale the loss by LossScaleManager.\n                If set, overwrite the level setting.\n        \"\"\"\n        check_value_type('network', network, nn.Cell, None)\n        check_value_type('optimizer', optimizer, nn.Optimizer, None)\n        check('level', level, \"\", ['O0', 'O2'], validator.IN, None)\n        self._check_kwargs(kwargs)\n        config = dict(_config_level[level], **kwargs)\n        config = edict(config)\n\n        if config.cast_model_type == mstype.float16:\n            network.to_float(mstype.float16)\n\n            if config.keep_batchnorm_fp32:\n                _do_keep_batchnorm_fp32(network)\n\n        if loss_fn:\n            network = _add_loss_network(network, loss_fn,\n                                        config.cast_model_type)\n\n        if _get_parallel_mode() in (\n                ParallelMode.SEMI_AUTO_PARALLEL, ParallelMode.AUTO_PARALLEL):\n            network = _VirtualDatasetCell(network)\n\n        loss_scale = 1.0\n        if config.loss_scale_manager is not None:\n            print(\"----model config have loss scale manager !\")\n        network = TrainOneStepCell(network, optimizer, sens=loss_scale).set_train()\n        return network\n\n\nclass _TupleAdd(nn.Cell):\n    \"\"\"\n    Add two tuple of data.\n    \"\"\"\n    def __init__(self):\n        super(_TupleAdd, self).__init__()\n        self.add = P.Add()\n        self.hyper_map = C.HyperMap()\n\n    def construct(self, input1, input2):\n        \"\"\"Add two tuple of data.\"\"\"\n        out = self.hyper_map(self.add, input1, input2)\n        return out\n\n\nclass _TupleMul(nn.Cell):\n    \"\"\"\n    Mul two tuple of data.\n    \"\"\"\n    def __init__(self):\n        super(_TupleMul, self).__init__()\n        self.mul = P.Mul()\n        self.hyper_map = C.HyperMap()\n\n    def construct(self, input1, input2):\n        \"\"\"Add two tuple of data.\"\"\"\n        out = self.hyper_map(self.mul, input1, input2)\n        return out\n\n\nclass TrainOneStepCell(Cell):\n    r\"\"\"\n    Network training package class.\n\n    Wraps the network with an optimizer. The resulting Cell be trained with input data and label.\n    Backward graph will be created in the construct function to do parameter updating. Different\n    parallel modes are available to run the training.\n\n    Args:\n        network (Cell): The training network.\n        optimizer (Cell): Optimizer for updating the weights.\n        sens (Number): The scaling number to be filled as the input of backpropagation.\n            Default value is ``1.0``.\n\n    Inputs:\n        - **data** (Tensor) - Tensor of shape :math:`(N, \\ldots)`.\n        - **label** (Tensor) - Tensor of shape :math:`(N, \\ldots)`.\n\n    Outputs:\n        Tensor, a scalar Tensor with shape :math:`()`.\n    \"\"\"\n    def __init__(self, network, optimizer, sens=1.0):\n        super(TrainOneStepCell, self).__init__(auto_prefix=False)\n        self.network = network\n        self.network.set_grad()\n        self.network.add_flags(defer_inline=True)\n        self.weights = optimizer.parameters\n        self.optimizer = optimizer\n        self.grad = C.GradOperation(get_by_list=True, sens_param=True)\n        self.sens = sens\n        self.reducer_flag = False\n        self.grad_reducer = None\n        self._tuple_add = _TupleAdd()\n        self._tuple_mul = _TupleMul()\n        parallel_mode = _get_parallel_mode()\n        if parallel_mode in (ParallelMode.DATA_PARALLEL, ParallelMode.HYBRID_PARALLEL):\n            self.reducer_flag = True\n        if self.reducer_flag:\n            mean = _get_gradients_mean()\n            degree = _get_device_num()\n            self.grad_reducer = DistributedGradReducer(optimizer.parameters, mean, degree)\n\n        self.do_privacy = False\n        self.grad_mask_tup = ()    # tuple containing grad_mask(cell)\n        self.de_weight_tup = ()    # tuple containing de_weight(cell)\n        self._suppress_pri_ctrl = None\n\n    def link_suppress_ctrl(self, suppress_pri_ctrl):\n        \"\"\"\n        Set Suppress Mask for grad_mask_tup and de_weight_tup.\n\n        Args:\n           suppress_pri_ctrl (SuppressCtrl): SuppressCtrl instance.\n        \"\"\"\n        self._suppress_pri_ctrl = suppress_pri_ctrl\n        if self._suppress_pri_ctrl.grads_mask_list:\n            for grad_mask_cell in self._suppress_pri_ctrl.grads_mask_list:\n                self.grad_mask_tup += (grad_mask_cell,)\n                self.do_privacy = True\n            for de_weight_cell in self._suppress_pri_ctrl.de_weight_mask_list:\n                self.de_weight_tup += (de_weight_cell,)\n        else:\n            self.do_privacy = False\n\n    def construct(self, data, label):\n        \"\"\"\n        Construct a compute flow.\n        \"\"\"\n        weights = self.weights\n        loss = self.network(data, label)\n        sens = P.Fill()(P.DType()(loss), P.Shape()(loss), self.sens)\n        grads = self.grad(self.network, weights)(data, label, sens)\n\n        new_grads = ()\n        m = 0\n        for grad in grads:\n            if self.do_privacy and self._suppress_pri_ctrl.mask_started:\n                enable_mask, grad_mask = self.grad_mask_tup[m]()\n                enable_de_weight, de_weight_array = self.de_weight_tup[m]()\n\n                if enable_mask and enable_de_weight:\n                    grad_n = self._tuple_add(de_weight_array, self._tuple_mul(grad, grad_mask))\n                    new_grads = new_grads + (grad_n,)\n                else:\n                    new_grads = new_grads + (grad,)\n            else:\n                new_grads = new_grads + (grad,)\n            m = m + 1\n\n        if self.reducer_flag:\n            new_grads = self.grad_reducer(new_grads)\n\n        return F.depend(loss, self.optimizer(new_grads))\n"
  },
  {
    "path": "mindarmour/reliability/__init__.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nReliability methods of MindArmour.\n\"\"\"\n\nfrom .model_fault_injection.fault_injection import FaultInjector\nfrom .concept_drift.concept_drift_check_time_series import ConceptDriftCheckTimeSeries\nfrom .concept_drift.concept_drift_check_images import OodDetector\nfrom .concept_drift.concept_drift_check_images import OodDetectorFeatureCluster\n\n__all__ = ['FaultInjector',\n           'ConceptDriftCheckTimeSeries',\n           'OodDetector',\n           'OodDetectorFeatureCluster']\n"
  },
  {
    "path": "mindarmour/reliability/concept_drift/README.md",
    "content": "# Concept Drift\n\n## Concept drift Description\n\nIn predictive analytics and machine learning, the concept drift means that the statistical properties of the target variable, which the model is trying to predict, change over time in unforeseen ways. This causes problems because the predictions become less accurate as time passes. Usually, concept drift is described as the change of data distribution over time.\n\n## Method for time series\n\n### Model Architecture\n\nThe concept drift detection method is based on the ESN (Echo state network). ESN is a type of reservoir computer that uses a recurrent neural network with a sparsely connected hidden layer (with typically 1% connectivity). The connectivity and weights of hidden neurons are fixed and randomly assigned.\nFor time series concept drift detection\n\n### Detector\n\nFor time series, we select two adjacent time window and compare the features of the two window data to determine whether concept drift has occurred. For feature extraction, we choose to use the ESN network. The input of the ESN network is a certain window data, and the output is also the window data (like an auto-encoder). In this way, the ESN network is equivalent to a feature extractor. Features are represented by model parameters (weights and bias) of the ESN network. Finally, by comparing the difference of model parameters, we can determine whether the data has concept drift. It should be noted that the two windows are constantly sliding forward.\n\n### Dataset\n\nDownload dataset https://www.kaggle.com/camnugent/sandp500.\n\n```bash\n├── archive\n  ├── all_stocks_5yr.csv\n  ├── getSandP.py\n  ├── merge.sh\n  ├── individual_stocks_5yr\n        ├──__MACOSX\n        ├──individual_stocks_5yr\n```\n\nPlease use the data in archive/individual_stocks_5yr/individual_stocks_5yr/XX.csv.  \nIn each csv file, there are 'date','open','high','low','close','volume','Name' columns, please choose one column to begin your code. 'date' and 'Name' are non-data column.  \n\n### Environment Requirements\n\n- Hardware(CPU/Ascend/GPU)\n    - Prepare hardware environment with CPU, Ascend or GPU processor.\n- Framework\n    - MindSpore\n- For more information, please check the resources below：\n    - MindSpore Tutorials\n    - MindSpore Python API\n\n### Quick Start\n\n#### Initialization\n\n```python\nfrom mindarmour.reliability.concept_drift.concept_drift_check_time_series import ConceptDriftCheckTimeSeries\n\nconcept = ConceptDriftCheckTimeSeries(window_size=100, rolling_window=10, step=10, threshold_index=1.5,\n                                      need_label=False)\n```\n\n>`window_size(int)`: Size of a concept window, no less than 10. If given the input data, window_size belongs to [10, 1/3*len(input data)]. If the data is periodic, usually window_size equals 2-5 periods, such as, for monthly/weekly data, the data volume of 30/7 days is a period. Default: 100.\n`rolling_window(int)`: Smoothing window size, belongs to [1, window_size]. Default:10.  \n`step(int)`: The jump length of the sliding window, belongs to [1,window_size]. Default:10.  \n`threshold_index(float)`: The threshold index. Default: 1.5.  \n`need_label(bool)`: False or True. If need_label=True, concept drift labels are needed. Default: False.  \n\n#### Data\n\n```python\nimport numpy as np\nfile = r'archive/individual_stocks_5yr/individual_stocks_5yr/AAP_data.csv'\ndata = np.loadtxt(file, str, delimiter=\",\")\ndata = data[1:, 2].astype('float64')  # here we choose one column or multiple columns data[1:, 2:5].\n```\n\n>`data(numpy.ndarray)`: Input data. The shape of data could be (n,1) or (n,m).\n\n#### Drift check\n\n```python\ndrift_score, threshold, concept_drift_location = concept.concept_check(data)\n# the result is saved as pdf named 'concept_drift_check.pdf'\n```\n\n>`drift_score(numpy.ndarray)`: The concept drift score of the example series.  \n`threshold(float)`: The threshold to judge concept drift.  \n`concept_drift_location(list)`: The location of the concept drift.  \n\n\n## Method for images\n\nGenerally, neural networks are used to process images. Therefore, we use algorithms based on neural networks to detect concept drifts of images. \nFor image data, there is a special term that describes the concept drift in detail, Out-of-Distribution(`OOD`). \nHereinafter, we will use the term `OOD` to describe concept drifts in images. As for non-drift images, we use the term In-Distribution(`ID`).\n \n### Model Architecture\n \nThe model structure can be any neural network structure, such as DNN, CNN, and RNN. \nHere, we select LeNet and ResNet as examples.\n \n### Detector\n \nFirstly, obtain the features of the training data, the features are the outputs of a selected neural layer. \nSecondly, the features are clustered to obtain the clustering centers. \nFinally, the features of the testing data in the same neural network layer are obtained, and the distance between the testing data features and the clustering center is calculated. \nWhen the distance exceeds the threshold, the image is determined as an out-of-distribution(OOD) image.\n \n### DataSet\n \nWe prepared two pairs of dataset for LeNet and ResNet separately. \nFor LeNet, the training data is Mnist as ID data. The testing data is Mnist + Cifar10. Cifar10 is OOD data.\nFor ResNet, the training data is Cifar10 as ID data. The testing data is Cifar10 + ImageNet. ImageNet is OOD data.\n \n \n### Environment Requirements\n \n- Hardware\n    - Prepare hardware environment with Ascend, CPU and GPU.\n- Framework\n    - MindSpore\n- For more information, please check the resources below：\n    - MindSpore Tutorials\n    - MindSpore Python API\n\n### Quick Start\n\n#### Import\n\n```python\nimport numpy as np\nfrom mindspore import Tensor\nfrom mindspore.train.model import Model\nfrom mindspore import Model, nn, context\nfrom examples.common.networks.lenet5.lenet5_net_for_fuzzing import LeNet5\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nfrom mindarmour.reliability.concept_drift.concept_drift_check_images import OodDetectorFeatureCluster\n```\n\n#### Load Classification Model\n\nFor convenience, we use a pre-trained model file `checkpoint_lenet-10_1875.ckpt` \nin 'mindarmour/tests/ut/python/dataset/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'. \n\n```python\nckpt_path = 'checkpoint_lenet-10_1875.ckpt'\nnet = LeNet5()\nload_dict = load_checkpoint(ckpt_path)\nload_param_into_net(net, load_dict)\nmodel = Model(net)\n```\n\n>`ckpt_path(str)`: the model path.  \n\n\nWe can also use self-constructed model.  \nIt is important that we need to name the model layer, and get the layer outputs.  \nTake LeNet as an example.\nFirstly, we import `TensorSummary` module.   \nSecondly, we initialize it as `self.summary = TensorSummary()`.  \nFinally, we add `self.summary('name', x)` after each layer we pay attention to. Here,  `name` of each layer is given by users.  \nAfter the above process, we can train the model and load it.  \n\n\n```python\nfrom mindspore import nn\nfrom mindspore.common.initializer import TruncatedNormal\nfrom mindspore.ops import TensorSummary\n\ndef conv(in_channels, out_channels, kernel_size, stride=1, padding=0):\n    \"\"\"Wrap conv.\"\"\"\n    weight = weight_variable()\n    return nn.Conv2d(in_channels, out_channels, kernel_size=kernel_size, stride=stride, padding=padding,\n                     weight_init=weight, has_bias=False, pad_mode=\"valid\")\n\ndef fc_with_initialize(input_channels, out_channels):\n    \"\"\"Wrap initialize method of full connection layer.\"\"\"\n    weight = weight_variable()\n    bias = weight_variable()\n    return nn.Dense(input_channels, out_channels, weight, bias)\n\ndef weight_variable():\n    \"\"\"Wrap initialize variable.\"\"\"\n    return TruncatedNormal(0.05)\n\nclass LeNet5(nn.Cell):\n    \"\"\"\n    Lenet network\n    \"\"\"\n    def __init__(self):\n        super(LeNet5, self).__init__()\n        self.conv1 = conv(1, 6, 5)\n        self.conv2 = conv(6, 16, 5)\n        self.fc1 = fc_with_initialize(16*5*5, 120)\n        self.fc2 = fc_with_initialize(120, 84)\n        self.fc3 = fc_with_initialize(84, 10)\n        self.relu = nn.ReLU()\n        self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.flatten = nn.Flatten()\n        self.summary = TensorSummary()\n\n    def construct(self, x):\n        \"\"\"\n        construct the network architecture\n        Returns:\n            x (tensor): network output\n        \"\"\"\n        x = self.conv1(x)\n        self.summary('1', x)\n\n        x = self.relu(x)\n        self.summary('2', x)\n\n        x = self.max_pool2d(x)\n        self.summary('3', x)\n\n        x = self.conv2(x)\n        self.summary('4', x)\n\n        x = self.relu(x)\n        self.summary('5', x)\n\n        x = self.max_pool2d(x)\n        self.summary('6', x)\n\n        x = self.flatten(x)\n        self.summary('7', x)\n\n        x = self.fc1(x)\n        self.summary('8', x)\n\n        x = self.relu(x)\n        self.summary('9', x)\n\n        x = self.fc2(x)\n        self.summary('10', x)\n\n        x = self.relu(x)\n        self.summary('11', x)\n\n        x = self.fc3(x)\n        self.summary('output', x)\n        return x\n\n```\n#### Load Data\n\nWe prepare three datasets. The training dataset, that is the same as the dataset to train the Lenet. Two testing datasets, the first testing dataset is with OOD label(0 for non-ood, and 1 for ood) for finding an optimal threshold for ood detection.\nThe second testing dataset is for ood validation. The first testing dataset is not necessary if we would like to set threshold by ourselves\n\n```python\nds_train = np.load('../../dataset/concept_train_lenet.npy')\nds_eval = np.load('../../dataset/concept_test_lenet1.npy')\nds_test = np.load('../../dataset/concept_test_lenet2.npy')\n```\n\n> `ds_train(numpy.ndarray)`: the train data.  \n> `ds_eval(numpy.ndarray)`: the data for finding an optimal threshold. This dataset is not necessary.  \n> `ds_test(numpy.ndarray)`: the test data for ood detection.  \n\n\n#### OOD detector initialization\n\nOOD detector for Lenet.\n\n\n```python\n# ood detector initialization\ndetector = OodDetectorFeatureCluster(model, ds_train, n_cluster=10, layer='output[:Tensor]')\n```\n> `model(Model)`: the model trained by the `ds_train`.  \n> `ds_train(numpy.ndarray)`: the training data.  \n> `n_cluster(int)`: the feature cluster number.  \n> `layer(str)`: the name of the feature extraction layer.\n\nIn our example, we input the layer name `output[:Tensor]`, which can also be`9[:Tensor]`, `10[:Tensor]`, `11[:Tensor]` for LeNet. \n\n\n#### Optimal Threshold\n\nThis step is optional. If we have a labeled dataset, named `ds_eval`, we can use the following code to find the optimal detection threshold.\n\n```python\n# get optimal threshold with ds_eval\nnum = int(len(ds_eval) / 2)\nlabel = np.concatenate((np.zeros(num), np.ones(num)), axis=0)  # ID data = 0, OOD data = 1\noptimal_threshold = detector.get_optimal_threshold(label, ds_eval)\n```\n\n> `ds_eval(numpy.ndarray)`: the data for finding an optimal threshold.  \n> `label(numpy.ndarray)`: the ood label of ds_eval. 0 means non-ood data, and 1 means ood data.\n\n#### Detection result\n\n```python\nresult = detector.ood_predict(optimal_threshold, ds_test)\n```\n\n> `ds_test(numpy.ndarray)`: the testing data for ood detection.  \n> `optimal_threshold(float)`: the optimal threshold to judge out-of-distribution data. We can also set the threshold value by ourselves.\n\n## Script Description\n\n```bash\n├── mindarmour\n  ├── reliability\n    ├──concept_drift\n        ├──__init__.py\n        ├──concept_drift_check_images.py\n        ├──concept_drift_check_time_series.py\n        ├──README.md\n```\n\n"
  },
  {
    "path": "mindarmour/reliability/concept_drift/__init__.py",
    "content": ""
  },
  {
    "path": "mindarmour/reliability/concept_drift/concept_drift_check_images.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nOut-of-Distribution detection module for images.\n\"\"\"\n\nimport heapq\nimport time\nimport numpy as np\nfrom sklearn.cluster import KMeans\n\nimport mindspore as ms\nfrom mindspore import Tensor\nfrom mindspore.train.summary.summary_record import _get_summary_tensor_data\nfrom mindarmour.utils._check_param import check_param_type, check_param_in_range\n\n\nclass OodDetector:\n    \"\"\"\n    The abstract class of the out-of-distribution detector.\n\n    Args:\n        model (Model):The training model.\n        ds_train (numpy.ndarray): The training dataset.\n    \"\"\"\n\n    def __init__(self, model, ds_train):\n        mode = ms.get_context('mode')\n        if mode == \"PYNATIVE_MODE\":\n            raise ValueError(f\"OodDetector Currently only supports GRAPH_MODE.\")\n        self.model = model\n        self.ds_train = check_param_type('ds_train', ds_train, np.ndarray)\n\n    def _feature_extract(self, model, data, layer='output[:Tensor]'):\n        \"\"\"\n        Extract features.\n        Args:\n            model (Model): The model for extracting features.\n            data (numpy.ndarray): Input data.\n            layer (str): The name of the feature layer. layer (str) is represented as\n                'name[:Tensor]', where 'name' is given by users when training the model.\n                Please see more details about how to name the model layer in 'README.md'.\n\n        Returns:\n            numpy.ndarray, the data feature extracted by a certain neural layer.\n        \"\"\"\n        model.predict(Tensor(data))\n        time.sleep(0.01)\n        layer_out = _get_summary_tensor_data()\n        return layer_out[layer].asnumpy()\n\n    def get_optimal_threshold(self, label, ds_eval):\n        \"\"\"\n        Get the optimal threshold. Try to find an optimal threshold value to\n        detect OOD examples. The optimal threshold is calculated by a labeled\n        dateset `ds_eval`.\n\n        Args:\n            label (numpy.ndarray): The label whether an image is in-distribution and out-of-distribution.\n            ds_eval (numpy.ndarray): The testing dataset to help find the threshold.\n\n        Returns:\n            - float, the optimal threshold.\n        \"\"\"\n\n    def ood_predict(self, threshold, ds_test):\n        \"\"\"\n        The out-of-distribution detection. This function aims to detect whether images,\n        regarded as `ds_test`, are OOD examples or not. If the prediction score of one\n        image is larger than `threshold`, this image is out-of-distribution.\n\n        Args:\n            threshold (float): the threshold to judge ood data. One can set value by experience\n                or use function get_optimal_threshold.\n            ds_test (numpy.ndarray): The testing dataset.\n\n        Returns:\n           - numpy.ndarray, the detection result. ``0`` means the data is not ood, ``1`` means the data is ood.\n        \"\"\"\n\n\nclass OodDetectorFeatureCluster(OodDetector):\n    \"\"\"\n    Train the OOD detector. Extract the training data features, and obtain the clustering centers. The distance between\n    the testing data features and the clustering centers determines whether an image is an out-of-distribution(OOD)\n    image or not.\n\n    For details, please check `Implementing the Concept Drift Detection Application of Image Data\n    <https://mindspore.cn/mindarmour/docs/en/master/concept_drift_images.html>`_.\n\n    Args:\n        model (Model):The training model.\n        ds_train (numpy.ndarray): The training dataset.\n        n_cluster (int): The cluster number. Belonging to [2,100].\n            Usually, n_cluster equals to the class number of the training dataset.\n            If the OOD detector performs poor in the testing dataset, we can increase the value of n_cluster\n            appropriately.\n        layer (str): The name of the feature layer. layer (str) is represented by\n            'name[:Tensor]', where 'name' is given by users when training the model.\n            Please see more details about how to name the model layer in 'README.md'.\n\n    Examples:\n        >>> from mindspore import Model\n        >>> from mindspore.ops import TensorSummary\n        >>> import mindspore.ops.operations as P\n        >>> from mindarmour.reliability.concept_drift.concept_drift_check_images import OodDetectorFeatureCluster\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...         self._Dense = nn.Dense(10,10)\n        ...         self._squeeze = P.Squeeze(1)\n        ...         self._summary = TensorSummary()\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         out = self._Dense(out)\n        ...         self._summary('output', out)\n        ...         return self._squeeze(out)\n        >>> net = Net()\n        >>> model = Model(net)\n        >>> batch_size = 16\n        >>> batches = 1\n        >>> ds_train = np.random.randn(batches * batch_size, 1, 10).astype(np.float32)\n        >>> ds_eval = np.random.randn(batches * batch_size, 1, 10).astype(np.float32)\n        >>> detector = OodDetectorFeatureCluster(model, ds_train, n_cluster=10, layer='output[:Tensor]')\n        >>> num = int(len(ds_eval) / 2)\n        >>> ood_label = np.concatenate((np.zeros(num), np.ones(num)), axis=0)\n        >>> optimal_threshold = detector.get_optimal_threshold(ood_label, ds_eval)\n    \"\"\"\n\n    def __init__(self, model, ds_train, n_cluster, layer):\n        super(OodDetectorFeatureCluster, self).__init__(model, ds_train)\n        self.model = model\n        self.ds_train = check_param_type('ds_train', ds_train, np.ndarray)\n        self.n_cluster = check_param_type('n_cluster', n_cluster, int)\n        self.n_cluster = check_param_in_range('n_cluster', n_cluster, 2, 100)\n        self.layer = check_param_type('layer', layer, str)\n        self.feature = self._feature_extract(model, ds_train, layer=self.layer)\n\n    def _feature_cluster(self):\n        \"\"\"\n        Get the feature cluster.\n\n        Returns:\n            - numpy.ndarray, the feature cluster.\n        \"\"\"\n        clf = KMeans(n_clusters=self.n_cluster)\n        clf.fit_predict(self.feature)\n        feature_cluster = clf.cluster_centers_\n        return feature_cluster\n\n    def _get_ood_score(self, ds_test):\n        \"\"\"\n        Get the ood score.\n\n        Args:\n            ds_test (numpy.ndarray): The testing dataset.\n\n        Returns:\n            - float, the optimal threshold.\n        \"\"\"\n        feature_cluster = self._feature_cluster()\n        ds_test = self._feature_extract(self.model, ds_test, layer=self.layer)\n        score = []\n        for i in range(len(ds_test)):\n            dis = []\n            for j in range(len(feature_cluster)):\n                loc = list(\n                    map(list(feature_cluster[j]).index, heapq.nlargest(self.n_cluster, list(feature_cluster[j]))))\n                diff = sum(abs((feature_cluster[j][loc] - ds_test[i][loc]))) / sum(abs((feature_cluster[j][loc])))\n                dis.append(diff)\n            score.append(min(dis))\n        score = np.array(score)\n        return score\n\n    def get_optimal_threshold(self, label, ds_eval):\n        \"\"\"\n        Get the optimal threshold. Try to find an optimal threshold value to\n        detect OOD examples. The optimal threshold is calculated by a labeled\n        dateset `ds_eval`.\n\n        Args:\n            label (numpy.ndarray): The label whether an image is in-distribution and out-of-distribution.\n            ds_eval (numpy.ndarray): The testing dataset to help find the threshold.\n\n        Returns:\n            - float, the optimal threshold.\n        \"\"\"\n        check_param_type('label', label, np.ndarray)\n        check_param_type('ds_eval', ds_eval, np.ndarray)\n        score = self._get_ood_score(ds_eval)\n        acc = []\n        threshold = []\n        for threshold_change in np.arange(0.0, 1.0, 0.01):\n            count = 0\n            for i in range(len(score)):\n                if score[i] < threshold_change and label[i] == 0:\n                    count = count + 1\n                if score[i] >= threshold_change and label[i] == 1:\n                    count = count + 1\n            acc.append(count / len(score))\n            threshold.append(threshold_change)\n        acc = np.array(acc)\n        threshold = np.array(threshold)\n        optimal_threshold = threshold[np.where(acc == np.max(acc))[0]][0]\n        return optimal_threshold\n\n    def ood_predict(self, threshold, ds_test):\n        \"\"\"\n        The out-of-distribution detection. This function aims to detect whether images,\n        regarded as `ds_test`, are OOD examples or not. If the prediction score of one\n        image is larger than `threshold`, this image is out-of-distribution.\n\n        Args:\n            threshold (float): the threshold to judge ood data. One can set value by experience\n                or use function get_optimal_threshold.\n            ds_test (numpy.ndarray): The testing dataset.\n\n        Returns:\n           - numpy.ndarray, the detection result. ``0`` means the data is not ood, ``1`` means the data is ood.\n        \"\"\"\n        score = self._get_ood_score(ds_test)\n        result = []\n        for i in range(len(score)):\n            if score[i] < threshold:\n                result.append(0)\n            if score[i] >= threshold:\n                result.append(1)\n        result = np.array(result)\n        return result\n"
  },
  {
    "path": "mindarmour/reliability/concept_drift/concept_drift_check_time_series.py",
    "content": "# -*- coding: utf-8 -*-\n# Copyright 2021 Huawei Technologies Co., Ltd\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n# http://www.apache.org/licenses/LICENSE-2.0\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nConcpt drift module\n\"\"\"\n\nfrom itertools import groupby\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom mindarmour.utils._check_param import _check_array_not_empty\nfrom mindarmour.utils._check_param import check_param_type, check_param_in_range\n\n\nclass ConceptDriftCheckTimeSeries:\n    r\"\"\"\n    ConceptDriftCheckTimeSeries is used for example series distribution change detection.\n    For details, please check `Implementing the Concept Drift Detection Application of Time Series Data\n    <https://mindspore.cn/mindarmour/docs/en/master/concept_drift_time_series.html>`_.\n\n    Args:\n        window_size(int): Size of a concept window, no less than 10. If given the input data,\n            window_size belongs to [10, 1/3*len(input data)]. If the data is periodic, usually\n            window_size equals 2-5 periods, such as, for monthly/weekly data, the data volume\n            of 30/7 days is a period. Default: ``100``.\n        rolling_window(int): Smoothing window size, belongs to [1, window_size]. Default: ``10``.\n        step(int): The jump length of the sliding window, belongs to [1, window_size]. Default: ``10``.\n        threshold_index(float): The threshold index, :math:`(-\\infty, +\\infty)`. Default: ``1.5``.\n        need_label(bool): If ``True``, concept drift labels are needed. Default: ``False``.\n\n    Examples:\n        >>> from mindarmour import ConceptDriftCheckTimeSeries\n        >>> concept = ConceptDriftCheckTimeSeries(window_size=100, rolling_window=10,\n        ...                                       step=10, threshold_index=1.5, need_label=False)\n        >>> data_example = 5*np.random.rand(1000)\n        >>> data_example[200: 800] = 20*np.random.rand(600)\n        >>> score, threshold, concept_drift_location = concept.concept_check(data_example)\n    \"\"\"\n\n    def __init__(self, window_size=100, rolling_window=10,\n                 step=10, threshold_index=1.5, need_label=False):\n        self.window_size = check_param_type('window_size', window_size, int)\n        self.rolling_window = check_param_type('rolling_window', rolling_window, int)\n        self.step = check_param_type('step', step, int)\n        self.threshold_index = check_param_type('threshold_index', threshold_index, float)\n        self.need_label = check_param_type('need_label', need_label, bool)\n        self._in_size = window_size\n        self._out_size = window_size\n        self._res_size = int(0.1*window_size)\n\n    def _reservoir_model_feature(self, window_data):\n        \"\"\"\n        Extract example features in reservoir model.\n\n        Args:\n            window_data(numpy.ndarray): The input data (in one window).\n\n        Returns:\n            - numpy.ndarray, the output weight of reservoir model.\n            - numpy.ndarray, the state of the reservoir model in the latent space.\n\n        Examples:\n            >>> input_data = np.random.rand(100)\n            >>> w, x = ConceptDriftCheckTimeSeries._reservoir_model_feature(window_data)\n        \"\"\"\n        # Initialize weights\n        res_size = self._res_size\n        x_state = _w_generate(res_size, len(window_data), window_data)\n        x_state_t = x_state.T\n        # Data reshape\n        data_channel = None\n        if window_data.ndim == 2:\n            data_channel = window_data.shape[1]\n        if window_data.ndim == 1:\n            data_channel = 1\n        y_t = window_data.reshape(len(window_data), data_channel)\n        reg = 1e-8\n        # Calculate w_out\n        w_out = np.dot(np.dot(y_t, x_state_t),\n                       np.linalg.inv(np.dot(x_state, x_state_t) + reg*np.eye(res_size)))\n        return w_out, x_state\n\n    def _concept_distance(self, data_x, data_y):\n        \"\"\"\n        Calculate the distance of two example blocks.\n\n        Args:\n            data_x(numpy.ndarray): Data x.\n            data_y(numpy.ndarray): Data y.\n\n        Returns:\n            - float, distance between data_x and data_y.\n\n        Examples:\n            >>> x = np.random.rand(100)\n            >>> y = np.random.rand(100)\n            >>> score = ConceptDriftCheckTimeSeries._concept_distance(x, y)\n        \"\"\"\n        # Feature extraction\n        feature_x = self._reservoir_model_feature(data_x)\n        feature_y = self._reservoir_model_feature(data_y)\n        # Calculate distance\n        distance_wx = sum(abs(np.dot(feature_x[0], feature_x[1])\n                              - np.dot(feature_y[0], feature_y[1])))/len(data_x)\n        statistic_feature = abs(data_x.mean() - data_y.mean()).mean()\n        distance_score = (distance_wx + statistic_feature) / (1 + distance_wx + statistic_feature)\n        distance_score_mean = distance_score.mean()\n        return distance_score_mean\n\n    def _data_process(self, data):\n        \"\"\"\n        Data processing.\n\n        Args:\n            data(numpy.ndarray): Input data.\n\n        Returns:\n            - numpy.ndarray, data after smoothing.\n\n        Examples:\n            >>> data_example = np.random.rand(100)\n            >>> data_example = ConceptDriftCheckTimeSeries._data_process(data_example)\n        \"\"\"\n        temp = []\n        data_channel = None\n        if data.ndim == 2:\n            data_channel = data.shape[1]\n        if data.ndim == 1:\n            data_channel = 1\n        data = data.reshape(len(data), data_channel)\n        # Moving average\n        for i in range(data_channel):\n            data_av = np.convolve(data[:, i],\n                                  np.ones((self.rolling_window,)) / self.rolling_window, 'valid')\n            data_av = np.append(data_av, np.ones(self.rolling_window - 1)*data_av[-1])\n            data_av = (data_av - data_av.min()) / (data_av.max() - data_av.min())\n            temp.append(data_av)\n        smooth_data = np.array(temp).T\n        return smooth_data\n\n    def concept_check(self, data):\n        \"\"\"\n        Find concept drift locations in a data series.\n\n        Args:\n            data(numpy.ndarray): Input data. The shape of data could be :math:`(n,1)` or :math:`(n,m)`.\n                Note that each column (m columns) is one data series.\n\n        Returns:\n            - numpy.ndarray, the concept drift score of the example series.\n            - float, the threshold to judge concept drift.\n            - list, the location of the concept drift.\n        \"\"\"\n        # data check\n        data = _check_array_not_empty('data', data)\n        data = check_param_type('data', data, np.ndarray)\n        check_param_in_range('window_size', self.window_size, 10, int((1 / 3)*len(data)))\n        check_param_in_range('rolling_window', self.rolling_window, 1, self.window_size)\n        check_param_in_range('step', self.step, 1, self.window_size)\n        original_data = data\n        data = self._data_process(data)\n        # calculate drift score\n        drift_score = np.zeros(len(data))\n        step_size = self.step\n        for i in range(0, len(data) - 2*self.window_size, step_size):\n            data_x = data[i: i + self.window_size]\n            data_y = data[i + self.window_size:i + 2*self.window_size]\n            drift_score[i + self.window_size] = self._concept_distance(data_x, data_y)\n        threshold = _cal_threshold(drift_score, self.threshold_index)\n        # original label\n        label, label_location = _original_label(data, threshold, drift_score,\n                                                self.window_size, step_size)\n        # label continue\n        label_continue = _label_continue_process(label)\n        # find drift blocks\n        concept_drift_location, drift_point = _drift_blocks(drift_score,\n                                                            label_continue, label_location)\n        # save result\n        _result_save(original_data, threshold, concept_drift_location, drift_point, drift_score)\n        return drift_score, threshold, concept_drift_location\n\n\ndef _result_save(original_data, threshold, concept_location, drift_point, drift_score):\n    \"\"\"\n    To save the result.\n\n    Args:\n        original_data(numpy.ndarray): The input data.\n        threshold(float): The concept drift threshold.\n        concept_location(list): The concept drift locations(x-axis).\n        drift_point(list): The precise drift point of a drift.\n        drift_score(numpy.ndarray): The drift score of input data.\n    \"\"\"\n    plt.figure(figsize=(20, 8))\n    plt.subplot(2, 1, 1)\n    # Plot input data and drift points\n    plt.plot(original_data, label=\"data\")\n    plt.title('concept drift check, threshold=' + str(threshold), fontsize=25)\n    plt.scatter(concept_location, np.ones(len(concept_location)),\n                marker='*', s=200, color=\"b\", label=\"concept drift occurred\")\n    for _, i in enumerate(drift_point):\n        plt.axvline(x=i, color='r', linestyle='--')\n    plt.legend(fontsize=15)\n    plt.subplot(2, 1, 2)\n    # Plot drift score\n    plt.plot(drift_score, label=\"drift_score\")\n    plt.axhline(y=threshold, color='r', linestyle='--', label=\"threshold\")\n    plt.legend(fontsize=15)\n    plt.savefig('concept_drift_check.pdf')\n\n\ndef _original_label(original_data, threshold, drift_score, window_size, step_size):\n    \"\"\"\n    To obtain a original drift label of time series.\n\n    Args:\n        original_data(numpy.ndarray): The input data.\n        threshold(float): The drift threshold.\n        drift_score(numpy.ndarray): The drift score of the input data.\n        window_size(int): Size of a concept window.\n            Usually 3 periods of the input data if it is periodic.\n        step_size(int): The jump length of the sliding window.\n\n    Returns:\n        - list, the drift label of input data.\n            0 means no drift, and 1 means drift happens.\n        - list, the locations of drifts(x-axis).\n    \"\"\"\n    label = []\n    label_location = []\n    # Label: label=0, no drifts; label=1, drift happens.\n    for i in range(0, len(original_data) - 2*window_size, step_size):\n        label_location.append(i + window_size)\n        if drift_score[i + window_size] >= threshold:\n            label.append(1)\n        else:\n            label.append(0)\n    return label, label_location\n\n\ndef _label_continue_process(label):\n    \"\"\"\n    To obtain a continual drift label of time series.\n\n    Args:\n        label(list): The original drift label.\n\n    Returns:\n        - numpy.ndarray, The continual drift label.\n            The drift may happen occasionally, we hope to avoid\n            frequent alarms, so label continue process is necessary.\n    \"\"\"\n    if label[-1] == 1 and label[-2] == 0 and label[-3] == 0 and label[-4] == 0:\n        label[-1] = 0\n    if label[0] == 1 and label[1] == 0 and label[2] == 0 and label[3] == 0:\n        label[0] = 0\n    label_continue = np.array(label)\n    # Label continue process\n    for i in range(1, len(label) - 1):\n        if label[i - 1] == 0 and label[i + 1] == 0:\n            label_continue[i - 1:i + 1] = 0\n    return label_continue\n\n\ndef _find_loc(label_location):\n    return label_location[1] - label_location[0]\n\n\ndef _continue_block(location):\n    \"\"\"\n    Find continue blocks of concept drift.\n\n    Args:\n        location(numpy.ndarray): The locations of concept drift.\n\n    Returns:\n        - list, continue blocks of concept drift.\n    \"\"\"\n    area = []\n    for _, loc in groupby(enumerate(location), _find_loc):\n        l_1 = [j for i, j in loc]\n        area.append(l_1)\n    return area\n\n\ndef _drift_blocks(drift_score, label_continue, label_location):\n    \"\"\"\n    Find the concept drift areas.\n\n    Args:\n        drift_score(numpy.ndarray): The drift score of the data series.\n        label_continue(numpy.ndarray):  The concept drift continual label.\n        label_location(numpy.ndarray):  The locations of concept drift(x-axis).\n\n    Returns:\n        - list, the concept drift locations(x-axis) after continual blocks finding.\n        - list, return a precise beginning location of a drift.\n    \"\"\"\n    # Find drift blocks\n    area = _continue_block(np.where(label_continue == 1)[0])\n    label_continue = np.array(label_continue)\n    label_location = np.array(label_location)\n    label_continue = label_continue[label_continue == 1]\n    concept_location = []\n    drift_point = []\n    # Find drift points\n    for _, lo_ in enumerate(area):\n        location = label_location[lo_]\n        concept_location.extend(location)\n        if label_continue.size > 0:\n            drift_point.append(location[np.where(drift_score[location]\n                                                 == np.max(drift_score[location]))[0]])\n        else:\n            drift_point.append(None)\n    return concept_location, drift_point\n\n\ndef _w_generate(res_size, in_size, input_data):\n    \"\"\"\n    Randomly generate weights of the reservoir model.\n\n    Args:\n        res_size(int): The number of reservoir nodes.\n        in_size(int): The input size of reservoir model.\n        input_data(numpy.ndarray): Input data.\n\n    Returns:\n        - numpy.ndarray, the state of reservoir.\n    \"\"\"\n    # Weight generates randomly\n    np.random.seed(42)\n    w_in = np.random.rand(res_size, in_size) - 0.5\n    w_0 = np.random.rand(res_size, res_size) - 0.5\n    w_0 *= 0.8\n    a_speed = 0.3\n    # Data reshape\n    data_channel = None\n    if input_data.ndim == 2:\n        data_channel = input_data.shape[1]\n    if input_data.ndim == 1:\n        data_channel = 1\n    # Reservoir state\n    x_state = np.zeros((res_size, data_channel))\n    u_input = input_data.reshape(len(input_data), data_channel)\n    for _ in range(50):\n        x_state = (1 - a_speed)*x_state + \\\n                  a_speed*np.tanh(np.dot(w_in, u_input) + np.dot(w_0, x_state))\n    return x_state\n\n\ndef _cal_distance(matrix1, matrix2):\n    \"\"\"\n    Calculate distance between two matrix.\n\n    Args:\n        matrix1(numpy.ndarray): Input array.\n        matrix2(numpy.ndarray): Input array.\n\n    Returns:\n        - numpy.ndarray, distance between two arrays.\n    \"\"\"\n    w_mean_x = np.mean(matrix1, axis=0)\n    w_mean_y = np.mean(matrix2, axis=0)\n    distance = sum(abs(w_mean_x - w_mean_y))\n    return distance\n\n\ndef _cal_threshold(distance, threshold_index):\n    \"\"\"\n    Calculate the threshold of concept drift.\n\n    Args:\n        distance(numpy.ndarray): The distance between two data series.\n        threshold_index(float): Threshold adjusted index, [-∞, +∞].\n\n    Returns:\n        - float, [0, 1].\n    \"\"\"\n    distance = distance[distance > 0]\n    # Threshold calculation\n    if distance.size > 0:\n        q_1 = np.percentile(distance, 25)\n        q_3 = np.percentile(distance, 75)\n        q_diff = q_3 - q_1\n        threshold = np.clip(0.1 + threshold_index*q_diff, 0, 1)\n    else:\n        threshold = 1\n    return threshold\n"
  },
  {
    "path": "mindarmour/reliability/model_fault_injection/README.md",
    "content": "# Demos of model fault injection\n\n## Introduction\n\nThis is a demo of fault injection for Mindspore applications written in Python.\n\n## Preparation\n\nFor the demo, we should prepare both datasets and pre-train models\n\n### Dateset\n\nFor example:\n\n`MINST`:Download MNIST dataset from: http://yann.lecun.com/exdb/mnist/ and extract as follows\n\n```test\nFile structure:\n    - data_path\n        - train\n            - train-images-idx3-ubyte\n            - train-labels-idx1-ubyte\n        - test\n            - t10k-images-idx3-ubyte\n            - t10k-labels-idx1-ubyte\n```\n\n`CIFAR10`:Download CIFAR10 dataset from: http://www.cs.toronto.edu/~kriz/cifar-10-binary.tar.gz and extract as follows\n\n```test\nFile structure:\n    - data_path\n        - train\n            - data_batch_1.bin\n            - data_batch_2.bin\n            - data_batch_3.bin\n            - data_batch_4.bin\n            - data_batch_5.bin\n        - test\n            - test_batch.bin\n```\n\n### CheckPoint file\n\nDownload checkpoint from: https://www.mindspore.cn/resources/hub or just trained your own checkpoint\n\n## Configuration\n\nThere are five parameters need to set up.\n\n```python\nDATA_FILE = '../common/dataset/MNIST_Data/test'\nckpt_path = '../common/networks/checkpoint_lenet_1-10_1875.ckpt'\n\n...\n\nfi_type = ['bitflips_random', 'bitflips_designated', 'random', 'zeros', 'nan', 'inf', 'anti_activation', 'precision_loss']\nfi_mode = ['single_layer', 'all_layer']\nfi_size = [1, 2, 3]\n```\n\n`DATA_FILE` is the directory where you store the data.\n\n`ckpt_path` is the directory where you store the checkpoint file.\n\n`fi_type` :\nEight types of faults can be injected. These are `bitflips_random`, `bitflips_designated`, `random`, `zeros`, `nan`, `inf`, `anti_activation` and `precision_loss`\n\nbitflips_random: Bits are flipped randomly in the chosen value.\n\nbitflips_designated: Specified bit is flipped in the chosen value.\n\nrandom: The chosen value are replaced with random value in the range [-1, 1]\n\nzeros: The chosen value are replaced with zero.\n\nnan: The chosen value are replaced with NaN.\n\ninf: The chosen value are replaced with Inf.\n\nanti_activation: Changing the sign of the chosen value.\n\nprecision_loss: Round the chosen value to 1 decimal place\n\n`fi_mode` :\nThere are twe kinds of injection modes can be specified, `single_layer` or `all_layer`.\n\n`fi_size` is usually the exact number of values to be injected with the specified fault. For `zeros`, `anti_activation` and `precision_loss` fault, `fi_size` is the percentage of total tensor values and varies from 0% to 100%\n\n### Example configuration\n\nSample 1:\n\n```python\nfi_type = ['bitflips_random', 'random', 'zeros', 'inf']\nfi_mode = ['single_layer']\nfi_size = [1]\n```\n\nSample 2:\n\n```python\nfi_type = ['bitflips_designated', 'random', 'inf', 'anti_activation', 'precision_loss']\nfi_mode = ['single_layer', 'all_layer']\nfi_size = [1, 2]\n```\n\n## Usage\n\nRun the test to observe the fault injection. For example:\n\n```bash\n#!/bin/bash\ncd examples/reliability/\npython  model_fault_injection.py --device_target GPU --device_id 2 --model lenet\n```\n\n`device_target`\n`model` is the target model need to be evaluation, choose from `lenet`, `vgg16` and `resnet`, or implement your own model.\n\n## Result\n\nFinally, there are three kinds of result will be return.\n\nSample:\n\n```test\noriginal_acc:0.979768\ntype:bitflips_random mode:single_layer size:1 acc:0.968950 SDC:0.010817\ntype:bitflips_random mode:single_layer size:2 acc:0.948017 SDC:0.031751\n...\ntype:precision_loss mode:all_layer size:2 acc:0.978966 SDC:0.000801\ntype:precision_loss mode:all_layer size:3 acc:0.979167 SDC:0.000601\nsingle_layer_acc_mean:0.819732 single_layer_acc_max:0.980068 single_layer_acc_min:0.192107\nsingle_layer_SDC_mean:0.160035 single_layer_SDC_max:0.787660 single_layer_SDC_min:-0.000300\nall_layer_acc_mean:0.697049 all_layer_acc_max:0.979167 all_layer_acc_min:0.089443\nall_layer_acc_mean:0.282719 all_layer_acc_max:0.890325 all_layer_acc_min:0.000601\n```\n\n### Original_acc\n\nThe original accuracy of model:\n\n```test\noriginal_acc:0.979768\n```\n\n### Specific result of each input parameter\n\nEach result including `type`, `mode`, `size`, `acc` and `SDC`. `type`, `mode` and `size` match along with `fi_type`, `fi_mode` and `fi_size`.\n\n```test\ntype:bitflips_random mode:single_layer size:1 acc:0.968950 SDC:0.010817\ntype:bitflips_random mode:single_layer size:2 acc:0.948017 SDC:0.031751\n...\ntype:precision_loss mode:all_layer size:2 acc:0.978966 SDC:0.000801\ntype:precision_loss mode:all_layer size:3 acc:0.979167 SDC:0.000601\n```\n\n### Summary of mode\n\nSummary of `single_layer` or `all_layer`.\n\n```test\nsingle_layer_acc_mean:0.819732 single_layer_acc_max:0.980068 single_layer_acc_min:0.192107\nsingle_layer_SDC_mean:0.160035 single_layer_SDC_max:0.787660 single_layer_SDC_min:-0.000300\nall_layer_acc_mean:0.697049 all_layer_acc_max:0.979167 all_layer_acc_min:0.089443\nall_layer_SDC_mean:0.282719 all_layer_SDC_max:0.890325 all_layer_SDC_min:0.000601\n```"
  },
  {
    "path": "mindarmour/reliability/model_fault_injection/__init__.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n# http://www.apache.org/licenses/LICENSE-2.0\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis module provides model fault injection to evaluate the reliability of given model.\n\"\"\"\nfrom .fault_injection import FaultInjector\nfrom .fault_type import FaultType\n\n__all__ = ['FaultInjector', 'FaultType']\n"
  },
  {
    "path": "mindarmour/reliability/model_fault_injection/fault_injection.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n# http://www.apache.org/licenses/LICENSE-2.0\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nFault injection module\n\"\"\"\n\nimport random\nimport numpy as np\n\nimport mindspore\nfrom mindspore import ops, Tensor\n\nfrom mindarmour.reliability.model_fault_injection.fault_type import FaultType\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.utils._check_param import check_int_positive, check_param_type, _check_array_not_empty\n\nLOGGER = LogUtil.get_instance()\nTAG = 'FaultInjector'\n\n\nclass FaultInjector:\n    \"\"\"\n    Fault injection module simulates various fault scenarios for deep neural networks and evaluates\n    performance and reliability of the model.\n\n    For details, please check `Implementing the Model Fault Injection and Evaluation\n    <https://mindspore.cn/mindarmour/docs/en/master/fault_injection.html>`_.\n\n    Args:\n        model (Model): The model need to be evaluated.\n        fi_type (list): The type of the fault injection which include ``bitflips_random`` (flip randomly),\n            ``bitflips_designated`` (flip the key bit), ``random``, ``zeros``, ``nan``, ``inf``,\n            ``anti_activation``, ``precision_loss`` etc.\n        fi_mode (list): The mode of fault injection. Fault inject on just ``single layer`` or ``all layers``.\n        fi_size (list): The number of fault injection. It mean that how many values need to be injected.\n\n    Examples:\n        >>> from mindspore import Model\n        >>> import mindspore.ops.operations as P\n        >>> from mindarmour.reliability.model_fault_injection.fault_injection import FaultInjector\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...         self._Dense = nn.Dense(10,10)\n        ...         self._squeeze = P.Squeeze(1)\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         out = self._Dense(out)\n        ...         return self._squeeze(out)\n        >>> def dataset_generator():\n        ...     batch_size = 16\n        ...     batches = 1\n        ...     data =  np.random.randn(batches * batch_size,1,10).astype(np.float32)\n        ...     label =  np.random.randint(0,10, batches * batch_size).astype(np.int32)\n        ...     for i in range(batches):\n        ...         yield data[i*batch_size:(i+1)*batch_size], label[i*batch_size:(i+1)*batch_size]\n        >>> net = Net()\n        >>> model = Model(net)\n        >>> ds_eval = ds.GeneratorDataset(dataset_generator, ['image', 'label'])\n        >>> fi_type = ['bitflips_random', 'bitflips_designated', 'random', 'zeros',\n        ...            'nan', 'inf', 'anti_activation', 'precision_loss']\n        >>> fi_mode = ['single_layer', 'all_layer']\n        >>> fi_size = [1]\n        >>> fi = FaultInjector(model, ds_eval, fi_type, fi_mode, fi_size)\n        >>> fi.kick_off()\n        >>> fi.metrics()\n    \"\"\"\n\n    def __init__(self, model, fi_type=None, fi_mode=None, fi_size=None):\n        \"\"\"FaultInjector initiated.\"\"\"\n        self.running_list = []\n        self.fi_type_map = {}\n        self._init_running_list(fi_type, fi_mode, fi_size)\n        self.model = model\n        self._fault_type = FaultType()\n        self._check_param()\n        self.result_list = []\n        self.original_acc = 0\n        self.original_parameter = {}\n        self.argmax = ops.Argmax()\n        self._reducesum = ops.ReduceSum(keep_dims=False)\n        self._frozen()\n\n    def _check_param(self):\n        \"\"\"Check input parameters.\"\"\"\n        ori_attr = self._fault_type.__dir__()\n        attr = []\n        for attr_ in ori_attr:\n            if not attr_.startswith('__') and attr_ not in ['_bitflip', '_fault_inject']:\n                attr.append(attr_)\n        if not isinstance(self.model, mindspore.Model):\n            msg = \"'Input model should be Mindspore Model', got {}.\".format(type(self.model))\n            LOGGER.error(TAG, msg)\n            raise TypeError(msg)\n        for param in self.running_list:\n            if param['fi_type'] not in attr:\n                msg = \"'Undefined fault type', got {}.\".format(self.fi_type_map[param['fi_type']])\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n            if param['fi_mode'] not in ['single_layer', 'all_layer']:\n                msg = \"'fault mode should be single_layer or all_layer', but got {}.\".format(param['fi_mode'])\n                LOGGER.error(TAG, msg)\n                raise ValueError(msg)\n            _ = check_int_positive('fi_size', param['fi_size'])\n\n    def _init_running_list(self, type_, mode_, size_):\n        \"\"\"Initiate fault injection parameters of this evaluation.\"\"\"\n        if type_ is None:\n            type_ = ['bitflips_random', 'bitflips_designated', 'random', 'zeros', 'nan', 'inf',\n                     'anti_activation', 'precision_loss']\n        if mode_ is None:\n            mode_ = ['single_layer', 'all_layer']\n        if size_ is None:\n            size_ = list(range(1, 4))\n        if not isinstance(type_, list):\n            msg = \"'fi_type should be list', got {}.\".format(type(type_))\n            LOGGER.error(TAG, msg)\n            raise TypeError(msg)\n        if not isinstance(mode_, list):\n            msg = \"'fi_mode should be list', got {}.\".format(type(mode_))\n            LOGGER.error(TAG, msg)\n            raise TypeError(msg)\n        if not isinstance(size_, list):\n            msg = \"'fi_size should be list', got {}.\".format(type(size_))\n            LOGGER.error(TAG, msg)\n            raise TypeError(msg)\n        for i in type_:\n            if not isinstance(i, str):\n                msg = \"'fi_type element should be str', got {} type {}.\".format(i, type(i))\n                LOGGER.error(TAG, msg)\n                raise TypeError(msg)\n            new_i = i if i.startswith('_') else '_' + i\n            self.fi_type_map[new_i] = i\n            for j in mode_:\n                for k in size_:\n                    dict_ = {'fi_type': new_i, 'fi_mode': j, 'fi_size': k}\n                    self.running_list.append(dict_)\n\n    def _frozen(self):\n        \"\"\"Store original parameters of model.\"\"\"\n        trainable_param = self.model.predict_network.trainable_params()\n        for param in trainable_param:\n            np_param = param.asnumpy().copy()\n            bytes_ = np_param.tobytes()\n            self.original_parameter[param.name] = {}\n            self.original_parameter[param.name]['datatype'] = np_param.dtype\n            self.original_parameter[param.name]['shape'] = np_param.shape\n            self.original_parameter[param.name]['data'] = bytes_.hex()\n\n    def _reset_model(self):\n        \"\"\"Reset model with original parameters.\"\"\"\n        for weight in self.model.predict_network.trainable_params():\n            name = weight.name\n            if name in self.original_parameter.keys():\n                bytes_w = bytes.fromhex(self.original_parameter[name]['data'])\n                datatype_w = self.original_parameter[name]['datatype']\n                shape_w = self.original_parameter[name]['shape']\n                np_w = np.frombuffer(bytes_w, dtype=datatype_w).reshape(shape_w)\n                weight.assign_value(Tensor.from_numpy(np_w))\n            else:\n                msg = \"Layer name not matched, got {}.\".format(name)\n                LOGGER.error(TAG, msg)\n                raise KeyError(msg)\n\n    @staticmethod\n    def _calculate_batch_size(num, iter_times):\n        \"\"\"Calculate batch size based on iter_times.\"\"\"\n        if num <= iter_times:\n            batch_list = [1] * num\n            idx_list = [0] * (num + 1)\n        else:\n            base_batch_size = num // iter_times\n            gt_num = num - iter_times * base_batch_size\n            le_num = iter_times - gt_num\n            batch_list = [base_batch_size + 1] * gt_num + [base_batch_size] * le_num\n            idx_list = [0] * (iter_times + 1)\n        for i, _ in enumerate(batch_list):\n            idx_list[i + 1] = idx_list[i] + batch_list[i]\n        return idx_list\n\n    @staticmethod\n    def _check_kick_off_param(ds_data, ds_label, iter_times):\n        \"\"\"check input data and label.\"\"\"\n        _ = check_int_positive('iter_times', iter_times)\n        _ = check_param_type('ds_data', ds_data, np.ndarray)\n        _ = _check_array_not_empty('ds_data', ds_data)\n        _ = check_param_type('ds_label', ds_label, np.ndarray)\n        _ = _check_array_not_empty('ds_label', ds_label)\n\n    def kick_off(self, ds_data, ds_label, iter_times=100):\n        \"\"\"\n        Startup and return final results after Fault Injection.\n\n        Args:\n            ds_data(np.ndarray): Input data for testing. The evaluation is based on this data.\n            ds_label(np.ndarray): The label of data, corresponding to the data.\n            iter_times(int): The number of evaluations, which will determine the batch size.\n\n        Returns:\n            - list, the result of fault injection.\n        \"\"\"\n        self._check_kick_off_param(ds_data, ds_label, iter_times)\n        num = ds_data.shape[0]\n        idx_list = self._calculate_batch_size(num, iter_times)\n        result_list = []\n        for i in range(-1, len(self.running_list)):\n            arg = self.running_list[i]\n            total = 0\n            correct = 0\n            for idx in range(len(idx_list) - 1):\n                a = ds_data[idx_list[idx]:idx_list[idx + 1], ...]\n                batch = Tensor.from_numpy(a)\n                label = Tensor.from_numpy(ds_label[idx_list[idx]:idx_list[idx + 1], ...])\n                if label.ndim == 2:\n                    label = self.argmax(label)\n                if i != -1:\n                    self._reset_model()\n                    self._layer_states(arg['fi_type'], arg['fi_mode'], arg['fi_size'])\n                output = self.model.predict(batch)\n                predict = self.argmax(output)\n                mask = predict == label\n                total += predict.size\n                correct += self._reducesum(mask.astype(mindspore.float32)).asnumpy()\n            acc = correct / total if total else 0\n            if i == -1:\n                self.original_acc = acc\n                result_list.append({'original_acc': self.original_acc})\n            else:\n                result_list.append({'type': arg['fi_type'][1:], 'mode': arg['fi_mode'], 'size': arg['fi_size'],\n                                    'acc': acc, 'SDC': self.original_acc - acc})\n        self._reset_model()\n        self.result_list = result_list\n        return result_list\n\n    def metrics(self):\n        \"\"\"\n        Metrics of final result.\n\n        Returns:\n            - list, the summary of result.\n        \"\"\"\n        result_summary = []\n        single_layer_acc = []\n        single_layer_sdc = []\n        all_layer_acc = []\n        all_layer_sdc = []\n        for result in self.result_list:\n            if 'mode' in result.keys():\n                if result['mode'] == 'single_layer':\n                    single_layer_acc.append(float(result['acc']))\n                    single_layer_sdc.append(float(result['SDC']))\n                else:\n                    all_layer_acc.append(float(result['acc']))\n                    all_layer_sdc.append(float(result['SDC']))\n        s_acc = np.array(single_layer_acc)\n        s_sdc = np.array(single_layer_sdc)\n        a_acc = np.array(all_layer_acc)\n        a_sdc = np.array(all_layer_sdc)\n        if single_layer_acc:\n            result_summary.append('single_layer_acc_mean:%f single_layer_acc_max:%f single_layer_acc_min:%f'\n                                  % (np.mean(s_acc), np.max(s_acc), np.min(s_acc)))\n            result_summary.append('single_layer_SDC_mean:%f single_layer_SDC_max:%f single_layer_SDC_min:%f'\n                                  % (np.mean(s_sdc), np.max(s_sdc), np.min(s_sdc)))\n        if all_layer_acc:\n            result_summary.append('all_layer_acc_mean:%f all_layer_acc_max:%f all_layer_acc_min:%f'\n                                  % (np.mean(a_acc), np.max(a_acc), np.min(a_acc)))\n            result_summary.append('all_layer_SDC_mean:%f all_layer_SDC_max:%f all_layer_SDC_min:%f'\n                                  % (np.mean(a_sdc), np.max(a_sdc), np.min(a_sdc)))\n        return result_summary\n\n    def _layer_states(self, fi_type, fi_mode, fi_size):\n        \"\"\"FI in layer states.\"\"\"\n        # Choose a random layer for injection\n        if fi_mode == \"single_layer\":\n            # Single layer fault injection mode\n            random_num = [random.randint(0, len(self.model.predict_network.trainable_params()) - 1)]\n        elif fi_mode == \"all_layer\":\n            # Multiple layer fault injection mode\n            random_num = list(range(len(self.model.predict_network.trainable_params()) - 1))\n        else:\n            msg = 'undefined fi_mode {}'.format(fi_mode)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n        for n in random_num:\n            # Get layer states info\n            w = self.model.predict_network.trainable_params()[n]\n            w_np = w.asnumpy().copy()\n            elem_shape = w_np.shape\n            w_np = w_np.reshape(-1)\n\n            # fault inject\n            new_w_np = self._fault_type._fault_inject(w_np, fi_type, fi_size)\n\n            # Reshape into original dimensions and store the faulty tensor\n            new_w_np = np.reshape(new_w_np, elem_shape)\n            w.set_data(Tensor.from_numpy(new_w_np))\n"
  },
  {
    "path": "mindarmour/reliability/model_fault_injection/fault_type.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n# http://www.apache.org/licenses/LICENSE-2.0\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nFault type module\n\"\"\"\n\nimport math\nimport random\nfrom struct import pack, unpack\nimport numpy as np\n\nfrom mindarmour.utils.logger import LogUtil\n\nLOGGER = LogUtil.get_instance()\nTAG = 'FaultType'\n\n\nclass FaultType:\n    \"\"\"Implementation of specified fault type.\"\"\"\n    @staticmethod\n    def _bitflip(value, pos):\n        \"\"\"\n        Implement of bitflip.\n        Args:\n            value (numpy.ndarray): Input data.\n            pos (list): The index of flip position.\n\n        Returns:\n            numpy.ndarray, bitflip data.\n        \"\"\"\n        bits = str(value.dtype)[-2:] if str(value.dtype)[-2].isdigit() else str(value.dtype)[-1]\n        value_format = 'B' * int(int(bits) / 8)\n        value_bytes = value.tobytes()\n        bytes_ = list(unpack(value_format, value_bytes))\n        for p in pos:\n            [q, r] = divmod(p, 8)\n            bytes_[q] ^= 1 << r\n        new_value_bytes = pack(value_format, *bytes_)\n        new_value = np.frombuffer(new_value_bytes, value.dtype)\n        return new_value[0]\n\n    def _fault_inject(self, value, fi_type, fi_size):\n        \"\"\"\n        Inject the specified fault into the randomly chosen values.\n        For zeros, anti_activation and precision_loss, fi_size is the percentage of\n        total number. And the others fault, fi_size is the exact number of values to\n        be injected.\n        Args:\n            value (numpy.ndarray): Input data.\n            fi_type (str): Fault type.\n            fi_size (int): The number of fault injection.\n\n        Returns:\n            numpy.ndarray, data after fault injection.\n        \"\"\"\n        num = value.size\n        if fi_type in ['zeros', 'anti_activation', 'precision_loss']:\n            change_size = (fi_size * num) / 100\n            change_size = math.floor(change_size)\n        else:\n            change_size = fi_size\n\n        if change_size > num:\n            change_size = num\n        # Choose the indices for FI\n        ind = random.sample(range(num), change_size)\n\n        # got specified fault type\n        try:\n            func = getattr(self, fi_type)\n            value = func(value, ind)\n            return value\n        except AttributeError:\n            msg = \"'Undefined fault type', got {}.\".format(fi_type)\n            LOGGER.error(TAG, msg)\n            raise AttributeError(msg)\n\n    def _bitflips_random(self, value, fi_indices):\n        \"\"\"\n        Flip bit randomly for specified value.\n        Args:\n            value (numpy.ndarray): Input data.\n            fi_indices (list): The index of injected data.\n\n        Returns:\n            numpy.ndarray, data after fault injection.\n        \"\"\"\n        for item in fi_indices:\n            val = value[item]\n            pos = random.sample(range(int(str(val.dtype)[-2:])),\n                                1 if np.random.random() < 0.618 else 2)\n            val_new = self._bitflip(val, pos)\n            value[item] = val_new\n        return value\n\n    def _bitflips_designated(self, value, fi_indices):\n        \"\"\"\n        Flip the key bit for specified value.\n\n        Args:\n            value (numpy.ndarray): Input data.\n            fi_indices (list): The index of injected data.\n\n        Returns:\n            numpy.ndarray, data after fault injection.\n        \"\"\"\n        for item in fi_indices:\n            val = value[item]\n            # uint8 uint16 uint32 uint64\n            bits = str(value.dtype)[-2:] if str(value.dtype)[-2].isdigit() else str(value.dtype)[-1]\n            if 'uint' in str(val.dtype):\n                pos = int(bits) - 1\n            # int8 int16 int32 int64 float16 float32 float64\n            else:\n                pos = int(bits) - 2\n            val_new = self._bitflip(val, [pos])\n            value[item] = val_new\n        return value\n\n    @staticmethod\n    def _random(value, fi_indices):\n        \"\"\"\n        Reset specified value randomly, range from -1 to 1.\n        Args:\n            value (numpy.ndarray): Input data.\n            fi_indices (list): The index of injected data.\n\n        Returns:\n            numpy.ndarray, data after fault injection.\n        \"\"\"\n        for item in fi_indices:\n            value[item] = np.random.random() * 2 - 1\n        return value\n\n    @staticmethod\n    def _zeros(value, fi_indices):\n        \"\"\"\n        Set specified value into zeros.\n        Args:\n            value (numpy.ndarray): Input data.\n            fi_indices (list): The index of injected data.\n\n        Returns:\n            numpy.ndarray, data after fault injection.\n        \"\"\"\n        value[fi_indices] = 0.\n        return value\n\n    @staticmethod\n    def _nan(value, fi_indices):\n        \"\"\"\n        Set specified value into nan.\n        Args:\n            value (numpy.ndarray): Input data.\n            fi_indices (list): The index of injected data.\n\n        Returns:\n            numpy.ndarray, data after fault injection.\n        \"\"\"\n        try:\n            value[fi_indices] = np.nan\n            return value\n        except ValueError:\n            return value\n\n    @staticmethod\n    def _inf(value, fi_indices):\n        \"\"\"\n        Set specified value into inf\n        Args:\n            value (numpy.ndarray): Input data.\n            fi_indices (list): The index of injected data.\n\n        Returns:\n            numpy.ndarray, data after fault injection.\n        \"\"\"\n        try:\n            value[fi_indices] = np.inf\n            return value\n        except OverflowError:\n            return value\n\n    @staticmethod\n    def _anti_activation(value, fi_indices):\n        \"\"\"\n        Minus specified value.\n        Args:\n            value (numpy.ndarray): Input data.\n            fi_indices (list): The index of injected data.\n\n        Returns:\n            numpy.ndarray, data after fault injection.\n        \"\"\"\n        value[fi_indices] = -value[fi_indices]\n        return value\n\n    @staticmethod\n    def _precision_loss(value, fi_indices):\n        \"\"\"\n        Round specified value, round to 1 decimal place.\n        Args:\n            value (numpy.ndarray): Input data.\n            fi_indices (list): The index of injected data.\n\n        Returns:\n            numpy.ndarray, data after fault injection.\n        \"\"\"\n        value[fi_indices] = np.around(value[fi_indices], decimals=1)\n        return value\n"
  },
  {
    "path": "mindarmour/utils/__init__.py",
    "content": "\"\"\"\nUtil methods of MindArmour.\n\"\"\"\nfrom .logger import LogUtil\nfrom .util import GradWrap\nfrom .util import GradWrapWithLoss\n\n__all__ = ['LogUtil', 'GradWrapWithLoss', 'GradWrap']\n"
  },
  {
    "path": "mindarmour/utils/_check_param.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\" check parameters for MindArmour. \"\"\"\n\nfrom collections.abc import Iterable\nimport numpy as np\n\nfrom .logger import LogUtil\n\nLOGGER = LogUtil.get_instance()\nTAG = 'check parameters'\n\n\nEQ = 1  # ==\nNE = 2  # !=\nLT = 3  # <\nLE = 4  # <=\nGT = 5  # >\nGE = 6  # >=\n# scalar range check\nINC_NEITHER = 7  # (), include neither\nINC_LEFT = 8  # [), include left\nINC_RIGHT = 9  # (], include right\nINC_BOTH = 10  # [], include both\n# collection in, not in\nIN = 11\nNOT_IN = 12\n\n\ndef _check_binary_rel(val1, val2, rel):\n    \"\"\"check binary relation\"\"\"\n    if rel == EQ:\n        return val1 == val2\n    if rel == NE:\n        return val1 != val2\n    if rel == LT:\n        return val1 < val2\n    if rel == LE:\n        return val1 <= val2\n    if rel == GT:\n        return val1 > val2\n    if rel == GE:\n        return val1 >= val2\n    if rel == IN:\n        return val1 in val2\n    if rel == NOT_IN:\n        return val1 not in val2\n\n    return False\n\n\ndef _format_str_one_value(value, rel):\n    \"\"\"format string\"\"\"\n    if rel == EQ:\n        return \"= {}\".format(value)\n    if rel == NE:\n        return \"!= {}\".format(value)\n    if rel == LT:\n        return \"< {}\".format(value)\n    if rel == LE:\n        return \"<= {}\".format(value)\n    if rel == GT:\n        return \"> {}\".format(value)\n    if rel == GE:\n        return \">= {}\".format(value)\n    if rel == IN:\n        return \"in {}\".format(value)\n    if rel == NOT_IN:\n        return \"not in {}\".format(value)\n\n    return \"\"\n\n\ndef _check_array_not_empty(arg_name, arg_value):\n    \"\"\"Check parameter is empty or not.\"\"\"\n    if isinstance(arg_value, (tuple, list)):\n        if not arg_value:\n            msg = '{} must not be empty'.format(arg_name)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n    if isinstance(arg_value, np.ndarray):\n        if arg_value.size <= 0:\n            msg = '{} must not be empty'.format(arg_name)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n    return arg_value\n\n\ndef check_param_type(arg_name, arg_value, valid_type):\n    \"\"\"Check parameter type.\"\"\"\n    if not isinstance(arg_value, valid_type):\n        msg = '{} must be {}, but got {}'.format(arg_name, valid_type, type(arg_value).__name__)\n        LOGGER.error(TAG, msg)\n        raise TypeError(msg)\n\n    return arg_value\n\n\ndef check_param_multi_types(arg_name, arg_value, valid_types):\n    \"\"\"Check parameter multi types.\"\"\"\n    if not isinstance(arg_value, tuple(valid_types)):\n        msg = 'type of {} must be in {}, but got {}'.format(arg_name, valid_types, type(arg_value).__name__)\n        LOGGER.error(TAG, msg)\n        raise TypeError(msg)\n\n    return arg_value\n\n\ndef check_int_positive(arg_name, arg_value):\n    \"\"\"Check positive integer.\"\"\"\n    # 'True' is treated as int(1) in python, which is a bug.\n    if isinstance(arg_value, bool):\n        msg = '{} should not be bool value, but got {}'.format(arg_name, arg_value)\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n    arg_value = check_param_type(arg_name, arg_value, int)\n    if arg_value <= 0:\n        msg = '{} must be greater than 0, but got {}'.format(arg_name, arg_value)\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n    return arg_value\n\n\ndef check_value_non_negative(arg_name, arg_value):\n    \"\"\"Check non negative value.\"\"\"\n    arg_value = check_param_multi_types(arg_name, arg_value, (int, float))\n    if float(arg_value) < 0.0:\n        msg = '{} must not be less than 0, but got {}'.format(arg_name, arg_value)\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n    return arg_value\n\n\ndef check_value_positive(arg_name, arg_value):\n    \"\"\"Check positive value.\"\"\"\n    arg_value = check_param_multi_types(arg_name, arg_value, (int, float))\n    if float(arg_value) <= 0.0:\n        msg = '{} must be greater than zero, but got {}'.format(arg_name, arg_value)\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n    return arg_value\n\n\ndef check_param_in_range(arg_name, arg_value, lower, upper):\n    \"\"\"\n    Check range of parameter.\n    \"\"\"\n    if arg_value <= lower or arg_value >= upper:\n        msg = '{} must be between {} and {}, but got {}'.format(arg_name, lower, upper, arg_value)\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n\n    return arg_value\n\n\ndef check_model(model_name, model, model_type):\n    \"\"\"\n    Check the type of input `model` .\n\n    Args:\n        model_name (str): Name of model.\n        model (Object): Model object.\n        model_type (Class): Class of model.\n\n    Returns:\n        Object, if the type of `model` is `model_type`, return `model` itself.\n\n    Raises:\n        ValueError: If model is not an instance of `model_type` .\n    \"\"\"\n    if isinstance(model, model_type):\n        return model\n    msg = '{} should be an instance of {}, but got {}'.format(model_name, model_type, type(model).__name__)\n    LOGGER.error(TAG, msg)\n    raise TypeError(msg)\n\n\ndef check_numpy_param(arg_name, arg_value):\n    \"\"\"\n    None-check and Numpy-check for `value` .\n\n    Args:\n        arg_name (str): Name of parameter.\n        arg_value (numpy.ndarray): Value for check.\n\n    Returns:\n        numpy.ndarray, if `value` is not empty, return `value` with type of\n        numpy.ndarray.\n\n    Raises:\n        ValueError: If value is empty.\n        ValueError: If value type is not numpy.ndarray.\n    \"\"\"\n    _ = _check_array_not_empty(arg_name, arg_value)\n    if isinstance(arg_value, np.ndarray):\n        arg_value = np.copy(arg_value)\n    else:\n        msg = 'type of {} must be numpy.ndarray, but got {}'.format(\n            arg_name, type(arg_value))\n        LOGGER.error(TAG, msg)\n        raise TypeError(msg)\n    return arg_value\n\n\ndef check_pair_numpy_param(inputs_name, inputs, labels_name, labels):\n    \"\"\"\n    Dimension-equivalence check for `inputs` and `labels`.\n\n    Args:\n        inputs_name (str): Name of inputs.\n        inputs (numpy.ndarray): Inputs.\n        labels_name (str): Name of labels.\n        labels (numpy.ndarray): Labels of `inputs`.\n\n    Returns:\n        - numpy.ndarray, if `inputs` 's dimension equals to `labels`, return inputs with type of numpy.ndarray.\n\n        - numpy.ndarray, if `inputs` 's dimension equals to `labels` , return labels with type of numpy.ndarray.\n\n    Raises:\n        ValueError: If inputs.shape[0] is not equal to labels.shape[0].\n    \"\"\"\n    inputs = check_numpy_param(inputs_name, inputs)\n    labels = check_numpy_param(labels_name, labels)\n    if inputs.shape[0] != labels.shape[0]:\n        msg = '{} shape[0] must equal {} shape[0], bot got shape of ' \\\n              'inputs {}, shape of labels {}'.format(inputs_name, labels_name, inputs.shape, labels.shape)\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n    return inputs, labels\n\n\ndef check_equal_length(para_name1, value1, para_name2, value2):\n    \"\"\"Check weather the two parameters have equal length.\"\"\"\n    if len(value1) != len(value2):\n        msg = 'The dimension of {0} must equal to the {1}, but got {0} is {2}, {1} is {3}'\\\n            .format(para_name1, para_name2, len(value1), len(value2))\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n    return value1, value2\n\n\ndef check_equal_shape(para_name1, value1, para_name2, value2):\n    \"\"\"Check weather the two parameters have equal shape.\"\"\"\n    if value1.shape != value2.shape:\n        msg = 'The shape of {0} must equal to the {1}, but got {0} is {2},  {1} is {3}'.\\\n            format(para_name1, para_name2, value1.shape, value2.shape)\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n    return value1, value2\n\n\ndef check_norm_level(norm_level):\n    \"\"\"Check norm_level of regularization.\"\"\"\n    if not isinstance(norm_level, (int, str)):\n        msg = 'Type of norm_level must be in [int, str], but got {}'.format(type(norm_level))\n    accept_norm = [1, 2, '1', '2', 'l1', 'l2', 'inf', 'linf', 'np.inf', np.inf]\n    if norm_level not in accept_norm:\n        msg = 'norm_level must be in {}, but got {}'.format(accept_norm, norm_level)\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n    return norm_level\n\n\ndef normalize_value(value, norm_level):\n    \"\"\"\n    Normalize gradients for gradient attacks.\n\n    Args:\n        value (numpy.ndarray): Inputs.\n        norm_level (Union[int, str]): Normalized level. Option: [1, 2, '1', '2', 'l1', 'l2', np.inf, 'np.inf',\n            'linf', 'inf'].\n\n    Returns:\n        numpy.ndarray, normalized value.\n\n    Raises:\n        NotImplementedError: If norm_level is not in [1, 2, '1', '2', 'l1', 'l2', np.inf, 'np.inf', 'linf', 'inf'].\n    \"\"\"\n    norm_level = check_norm_level(norm_level)\n    ori_shape = value.shape\n    value_reshape = value.reshape((value.shape[0], -1))\n    avoid_zero_div = 1e-12\n    if norm_level in (1, '1', 'l1'):\n        norm = np.linalg.norm(value_reshape, ord=1, axis=1, keepdims=True) + avoid_zero_div\n        norm_value = value_reshape / norm\n    elif norm_level in (2, '2', 'l2'):\n        norm = np.linalg.norm(value_reshape, ord=2, axis=1, keepdims=True) + avoid_zero_div\n        norm_value = value_reshape / norm\n    elif norm_level in (np.inf, 'inf', 'np.inf', 'linf'):\n        norm = np.max(abs(value_reshape), axis=1, keepdims=True) + avoid_zero_div\n        norm_value = value_reshape / norm\n    else:\n        accept_norm = [1, 2, '1', '2', 'l1', 'l2', 'inf', 'linf', 'np.inf', np.inf]\n        msg = 'Values of `norm_level`, must be in {}, but got {}'.format(accept_norm, norm_level)\n        LOGGER.error(TAG, msg)\n        raise NotImplementedError(msg)\n    return norm_value.reshape(ori_shape)\n\n\ndef check_detection_inputs(inputs, labels):\n    \"\"\"\n    Check the inputs for detection model attacks.\n\n    Args:\n        inputs (Union[numpy.ndarray, tuple]): Images and other auxiliary inputs for detection model.\n        labels (tuple): Ground-truth boxes and ground-truth labels of inputs.\n\n    Returns:\n        - numpy.ndarray, images data.\n\n        - tuple, auxiliary inputs, such as image shape.\n\n        - numpy.ndarray, ground-truth boxes.\n\n        - numpy.ndarray, ground-truth labels.\n    \"\"\"\n    if isinstance(inputs, tuple):\n        has_images = False\n        auxiliary_inputs = tuple()\n        for item in inputs:\n            check_numpy_param('item', item)\n            if len(item.shape) == 4:\n                images = item\n                has_images = True\n            else:\n                auxiliary_inputs += (item,)\n        if not has_images:\n            msg = 'Inputs should contain images whose dimension is 4.'\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n    else:\n        check_numpy_param('inputs', inputs)\n        images = inputs\n        auxiliary_inputs = ()\n\n    check_param_type('labels', labels, tuple)\n    if len(labels) != 2:\n        msg = 'Labels should contain two arrays (boxes-confidences array and ground-truth labels array), ' \\\n              'but got {} arrays.'.format(len(labels))\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n    has_boxes = False\n    has_labels = False\n    for item in labels:\n        check_numpy_param('item', item)\n        if len(item.shape) == 3:\n            gt_boxes = item\n            has_boxes = True\n        elif len(item.shape) == 2:\n            gt_labels = item\n            has_labels = True\n    if (not has_boxes) or (not has_labels):\n        msg = 'The shape of boxes array should be (N, M, 5) or (N, M, 4), and the shape of ground-truth' \\\n              'labels array should be (N, M). But got {} and {}.'.format(labels[0].shape, labels[1].shape)\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n    return images, auxiliary_inputs, gt_boxes, gt_labels\n\n\ndef check_inputs_labels(inputs, labels):\n    \"\"\"Check inputs and labels is valid for white box method.\"\"\"\n    _ = check_param_multi_types('inputs', inputs, (tuple, np.ndarray))\n    _ = check_param_multi_types('labels', labels, (tuple, np.ndarray))\n    inputs_image = inputs[0] if isinstance(inputs, tuple) else inputs\n    if isinstance(inputs, tuple):\n        for i, inputs_item in enumerate(inputs):\n            _ = check_pair_numpy_param('inputs_image', inputs_image, 'inputs[{}]'.format(i), inputs_item)\n    if isinstance(labels, tuple):\n        for i, labels_item in enumerate(labels):\n            _ = check_pair_numpy_param('inputs', inputs_image, 'labels[{}]'.format(i), labels_item)\n    else:\n        _ = check_pair_numpy_param('inputs', inputs_image, 'labels', labels)\n    return inputs_image, inputs, labels\n\n\ndef check_param_bounds(arg_name, arg_value):\n    \"\"\"Check bounds is valid\"\"\"\n    arg_value = check_param_multi_types(arg_name, arg_value, [tuple, list])\n    if len(arg_value) != 2:\n        msg = 'length of {0} must be 2, but got length of {0} is {1}'.format(arg_name, len(arg_value))\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n    for i, b in enumerate(arg_value):\n        if not isinstance(b, (float, int)):\n            msg = 'each value in {} must be int or float, but got the {}th value is {}'.format(arg_name, i, b)\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n    if arg_value[0] >= arg_value[1]:\n        msg = \"lower boundary must be less than upper boundary, corresponding values in {} are {} and {}\". \\\n            format(arg_name, arg_value[0], arg_value[1])\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n    return arg_value\n\n\ndef check_value_type(arg_name, arg_value, valid_types, prim_name=None):\n    \"\"\"Checks whether a value is instance of some types.\"\"\"\n    valid_types = valid_types if isinstance(valid_types, Iterable) else (valid_types,)\n\n    def raise_error_msg(cond, arg_value):\n        \"\"\"func for raising error message when check failed\"\"\"\n        if not cond:\n            return\n        type_names = [t.__name__ if hasattr(t, '__name__') else str(t) for t in valid_types]\n        num_types = len(valid_types)\n        msg_prefix = f\"For '{prim_name}', the\" if prim_name else \"The\"\n        raise TypeError(f'{msg_prefix} type of \\'{arg_name}\\' should be {\"one of \" if num_types > 1 else \"\"}' \\\n                        f'\\'{type_names if num_types > 1 else type_names[0]}\\', ' \\\n                        f'but got type \\'{type(arg_value).__name__}\\'.')\n\n    # Notice: bool is subclass of int, so `check_value_type('x', True, [int])` will check fail, and\n    #         `check_value_type('x', True, [bool, int])` will check pass\n    cond = isinstance(arg_value, bool) and bool not in tuple(valid_types)\n    raise_error_msg(cond, arg_value)\n    if isinstance(arg_value, float) and float not in tuple(valid_types):\n        arg_value = round(arg_value, 6)\n    cond = not isinstance(arg_value, tuple(valid_types))\n    raise_error_msg(cond, arg_value)\n    return arg_value\n\n\ndef check(arg_name, arg_value, value_name, value, rel=EQ, prim_name=None, excp_cls=ValueError):\n    \"\"\"\n    Method for judging relation between two int values or list/tuple made up of ints.\n    This method is not suitable for judging relation between floats, since it does not consider float error.\n    \"\"\"\n    def _check():\n        if not _check_binary_rel(arg_value, value, rel):\n            rel_str = _format_str_one_value(f'{value_name}: {value}', rel)\n            msg_prefix = f'For \\'{prim_name}\\', the' if prim_name else \"The\"\n            msg_subject = f\"{msg_prefix} \\'{arg_name}\\'\" if \" \" not in arg_name else f\"{msg_prefix} {arg_name}\"\n            raise excp_cls(f'{msg_subject} should be {rel_str}, but got {arg_value}.')\n    _check()\n    return arg_value\n"
  },
  {
    "path": "mindarmour/utils/logger.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\" Util for log module. \"\"\"\nimport logging\n\n_LOGGER = logging.getLogger('MA')\n\n\ndef _find_caller():\n    \"\"\"\n    Bind findCaller() method, which is used to find the stack frame of the\n    caller so that we can note the source file name, line number and\n    function name.\n    \"\"\"\n    return _LOGGER.findCaller()\n\n\nclass LogUtil:\n    \"\"\"\n    Logging module.\n\n    Recording the logging statistics over time in long-running scripts.\n\n    Raises:\n        SyntaxError: If create this class.\n    \"\"\"\n    _instance = None\n    _logger = None\n    _extra_fmt = ' [{}] [{}] '\n\n    def __init__(self):\n        raise SyntaxError('can not instance, please use get_instance.')\n\n    @staticmethod\n    def get_instance():\n        \"\"\"\n        Get instance of class `LogUtil`.\n\n        Returns:\n            Object, instance of class `LogUtil`.\n        \"\"\"\n        if LogUtil._instance is None:\n            LogUtil._instance = object.__new__(LogUtil)\n            LogUtil._logger = _LOGGER\n            LogUtil._init_logger()\n        return LogUtil._instance\n\n    @staticmethod\n    def _init_logger():\n        \"\"\"\n        Initialize logger.\n        \"\"\"\n        LogUtil._logger.setLevel(logging.WARNING)\n\n        log_fmt = '[%(levelname)s] %(name)s(%(process)d:%(thread)d,' \\\n                  '%(processName)s):%(asctime)s%(message)s'\n        log_fmt = logging.Formatter(log_fmt)\n\n        # create console handler with a higher log level\n        console_handler = logging.StreamHandler()\n        console_handler.setFormatter(log_fmt)\n\n        # add the handlers to the logger\n        LogUtil._logger.handlers = []\n        LogUtil._logger.addHandler(console_handler)\n\n        LogUtil._logger.propagate = False\n\n    def set_level(self, level):\n        \"\"\"\n        Set the logging level of this logger, level must be an integer or a\n        string. Supported levels are ``'NOTSET'(integer: 0)``, ``'ERROR'(integer: 1-40)``,\n        ``'WARNING'('WARN', integer: 1-30)``, ``'INFO'(integer: 1-20)`` and ``'DEBUG'(integer: 1-10)``.\n        For example, if logger.set_level('WARNING') or logger.set_level(21), then\n        logger.warn() and logger.error() in scripts would be printed while running,\n        while logger.info() or logger.debug() would not be printed.\n\n        Args:\n            level (Union[int, str]): Level of logger.\n        \"\"\"\n        self._logger.setLevel(level)\n\n    def add_handler(self, handler):\n        \"\"\"\n        Add other handler supported by logging module.\n\n        Args:\n            handler (logging.Handler): Other handler supported by logging module.\n\n        Raises:\n            ValueError: If handler is not an instance of logging.Handler.\n        \"\"\"\n        if isinstance(handler, logging.Handler):\n            self._logger.addHandler(handler)\n        else:\n            raise ValueError('handler must be an instance of logging.Handler,'\n                             ' but got {}'.format(type(handler)))\n\n    def debug(self, tag, msg, *args):\n        \"\"\"\n        Log '[tag] msg' with severity 'DEBUG'.\n\n        Args:\n            tag (str): Logger tag.\n            msg (str): Logger message.\n            args (Any): Auxiliary value.\n        \"\"\"\n        caller_info = _find_caller()\n        file_info = ':'.join([caller_info[0], str(caller_info[1])])\n        formatted_msg = self._extra_fmt.format(file_info, tag) + str(msg)\n        if args:\n            self._logger.debug(formatted_msg, *args)\n        else:\n            self._logger.debug(formatted_msg)\n\n    def info(self, tag, msg, *args):\n        \"\"\"\n        Log '[tag] msg' with severity 'INFO'.\n\n        Args:\n            tag (str): Logger tag.\n            msg (str): Logger message.\n            args (Any): Auxiliary value.\n        \"\"\"\n        caller_info = _find_caller()\n        file_info = ':'.join([caller_info[0], str(caller_info[1])])\n        formatted_msg = self._extra_fmt.format(file_info, tag) + str(msg)\n        if args:\n            self._logger.info(formatted_msg, *args)\n        else:\n            self._logger.info(formatted_msg)\n\n    def warn(self, tag, msg, *args):\n        \"\"\"\n        Log '[tag] msg' with severity 'WARNING'.\n\n        Args:\n            tag (str): Logger tag.\n            msg (str): Logger message.\n            args (Any): Auxiliary value.\n        \"\"\"\n        caller_info = _find_caller()\n        file_info = ':'.join([caller_info[0], str(caller_info[1])])\n        formatted_msg = self._extra_fmt.format(file_info, tag) + str(msg)\n        if args:\n            self._logger.warning(formatted_msg, *args)\n        else:\n            self._logger.warning(formatted_msg)\n\n    def error(self, tag, msg, *args):\n        \"\"\"\n        Log '[tag] msg' with severity 'ERROR'.\n\n        Args:\n            tag (str): Logger tag.\n            msg (str): Logger message.\n            args (Any): Auxiliary value.\n        \"\"\"\n        caller_info = _find_caller()\n        file_info = ':'.join([caller_info[0], str(caller_info[1])])\n        formatted_msg = self._extra_fmt.format(file_info, tag) + str(msg)\n        if args:\n            self._logger.error(formatted_msg, *args)\n        else:\n            self._logger.error(formatted_msg)\n"
  },
  {
    "path": "mindarmour/utils/util.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\" Util for MindArmour. \"\"\"\nimport numpy as np\nfrom scipy.ndimage import uniform_filter\n\nfrom mindspore import Tensor\nfrom mindspore.nn import Cell\nfrom mindspore.ops.composite import GradOperation\n\nfrom mindarmour.utils._check_param import check_numpy_param, check_param_multi_types, check_equal_shape\n\nfrom .logger import LogUtil\n\nLOGGER = LogUtil.get_instance()\nTAG = 'util'\n\n\ndef jacobian_matrix(grad_wrap_net, inputs, num_classes):\n    \"\"\"\n    Calculate the Jacobian matrix for inputs.\n\n    Args:\n        grad_wrap_net (Cell): A network wrapped by GradWrap.\n        inputs (numpy.ndarray): Input samples.\n        num_classes (int): Number of labels of model output.\n\n    Returns:\n        numpy.ndarray, the Jacobian matrix of inputs. (labels, batch_size, ...)\n\n    Raises:\n        ValueError: If `grad_wrap_net` is not a instance of class `GradWrap`.\n    \"\"\"\n    if not isinstance(grad_wrap_net, GradWrap):\n        msg = 'grad_wrap_net be and instance of class `GradWrap`.'\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n    grad_wrap_net.set_train()\n    grads_matrix = []\n    for idx in range(num_classes):\n        sens = np.zeros((inputs.shape[0], num_classes)).astype(np.float32)\n        sens[:, idx] = 1.0\n        grads = grad_wrap_net(Tensor(inputs), Tensor(sens))\n        grads_matrix.append(grads.asnumpy())\n    return np.asarray(grads_matrix)\n\n\ndef jacobian_matrix_for_detection(grad_wrap_net, inputs, num_boxes, num_classes):\n    \"\"\"\n    Calculate the Jacobian matrix for inputs, specifically for object detection model.\n\n    Args:\n        grad_wrap_net (Cell): A network wrapped by GradWrap.\n        inputs (numpy.ndarray): Input samples.\n        num_boxes (int): Number of boxes inferred by each image.\n        num_classes (int): Number of labels of model output.\n\n    Returns:\n        numpy.ndarray, the Jacobian matrix of inputs. (labels, batch_size, ...)\n\n    Raises:\n        ValueError: If `grad_wrap_net` is not a instance of class `GradWrap`.\n    \"\"\"\n    if not isinstance(grad_wrap_net, GradWrap):\n        msg = 'grad_wrap_net be and instance of class `GradWrap`.'\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n    grad_wrap_net.set_train()\n    grads_matrix = []\n    inputs_tensor = tuple()\n    if isinstance(inputs, tuple):\n        for item in inputs:\n            inputs_tensor += (Tensor(item),)\n    else:\n        inputs_tensor += (Tensor(inputs),)\n    for idx in range(num_classes):\n        batch_size = inputs[0].shape[0] if isinstance(inputs, tuple) else inputs.shape[0]\n        sens = np.zeros((batch_size, num_boxes, num_classes), np.float32)\n        sens[:, :, idx] = 1.0\n        grads = grad_wrap_net(*(inputs_tensor), Tensor(sens))\n        grads_matrix.append(grads.asnumpy())\n    return np.asarray(grads_matrix)\n\n\nclass WithLossCell(Cell):\n    \"\"\"\n    Wrap the network with loss function.\n\n    Args:\n        network (Cell): The target network to wrap.\n        loss_fn (Function): The loss function is used for computing loss.\n\n    Examples:\n        >>> from mindspore import Tensor\n        >>> from mindarmour.utils.util import WithLossCell\n        >>> import mindspore.ops.operations as P\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...         self._Dense = nn.Dense(10,10)\n        ...         self._squeeze = P.Squeeze(1)\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         out = self._Dense(out)\n        ...         return self._squeeze(out)\n        >>> data = Tensor(np.ones([2, 1, 10]).astype(np.float32)*0.01)\n        >>> labels = Tensor(np.ones([2, 10]).astype(np.float32))\n        >>> net = Net()\n        >>> loss_fn = nn.SoftmaxCrossEntropyWithLogits()\n        >>> loss_net = WithLossCell(net, loss_fn)\n    \"\"\"\n    def __init__(self, network, loss_fn):\n        super(WithLossCell, self).__init__()\n        self._network = network\n        self._loss_fn = loss_fn\n\n    def construct(self, data, label):\n        \"\"\"\n        Compute loss based on the wrapped loss cell.\n\n        Args:\n            data (Tensor): Tensor data to train.\n            label (Tensor): Tensor label data.\n\n        Returns:\n            Tensor, compute result.\n        \"\"\"\n        out = self._network(data)\n        return self._loss_fn(out, label)\n\n\nclass GradWrapWithLoss(Cell):\n    \"\"\"\n    Construct a network to compute the gradient of loss function in input space\n    and weighted by `weight`.\n\n    Args:\n        network (Cell): The target network to wrap.\n\n    Examples:\n        >>> from mindspore import Tensor\n        >>> from mindarmour.utils import GradWrapWithLoss\n        >>> from mindarmour.utils.util import WithLossCell\n        >>> import mindspore.ops.operations as P\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...         self._Dense = nn.Dense(10,10)\n        ...         self._squeeze = P.Squeeze(1)\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         out = self._Dense(out)\n        ...         return self._squeeze(out)\n        >>> data = Tensor(np.ones([2, 1, 10]).astype(np.float32)*0.01)\n        >>> labels = Tensor(np.ones([2, 10]).astype(np.float32))\n        >>> net = Net()\n        >>> loss_fn = nn.SoftmaxCrossEntropyWithLogits()\n        >>> loss_net = WithLossCell(net, loss_fn)\n        >>> grad_all = GradWrapWithLoss(loss_net)\n        >>> out_grad = grad_all(data, labels)\n    \"\"\"\n\n    def __init__(self, network):\n        super(GradWrapWithLoss, self).__init__()\n        self._grad_all = GradOperation(get_all=True, sens_param=False)\n        self._network = network\n\n    def construct(self, inputs, labels):\n        \"\"\"\n        Compute gradient of `inputs` with labels and weight.\n\n        Args:\n            inputs (Tensor): Inputs of network.\n            labels (Tensor): Labels of inputs.\n\n        Returns:\n            Tensor, gradient matrix.\n        \"\"\"\n        gout = self._grad_all(self._network)(inputs, labels)\n        return gout[0]\n\n\nclass GradWrap(Cell):\n    \"\"\"\n    Construct a network to compute the gradient of network outputs in input\n    space and weighted by `weight`, expressed as a jacobian matrix.\n\n    Args:\n        network (Cell): The target network to wrap.\n\n    Examples:\n        >>> from mindspore import Tensor\n        >>> from mindarmour.utils import GradWrap\n        >>> from mindarmour.utils.util import WithLossCell\n        >>> import mindspore.ops.operations as P\n        >>> class Net(nn.Cell):\n        ...     def __init__(self):\n        ...         super(Net, self).__init__()\n        ...         self._softmax = P.Softmax()\n        ...         self._Dense = nn.Dense(10,10)\n        ...         self._squeeze = P.Squeeze(1)\n        ...     def construct(self, inputs):\n        ...         out = self._softmax(inputs)\n        ...         out = self._Dense(out)\n        ...         return self._squeeze(out)\n        >>> net = Net()\n        >>> data = Tensor(np.ones([2, 1, 10]).astype(np.float32)*0.01)\n        >>> labels = Tensor(np.ones([2, 10]).astype(np.float32))\n        >>> num_classes = 10\n        >>> sens = np.zeros((data.shape[0], num_classes)).astype(np.float32)\n        >>> sens[:, 1] = 1.0\n        >>> wrap_net = GradWrap(net)\n        >>> wrap_net(data, Tensor(sens))\n    \"\"\"\n\n    def __init__(self, network):\n        super(GradWrap, self).__init__()\n        self.grad = GradOperation(get_all=False, sens_param=True)\n        self.network = network\n\n    def construct(self, *data):\n        \"\"\"\n        Compute jacobian matrix.\n\n        Args:\n            data (Tensor): Data consists of inputs and weight.\n\n                - inputs: Inputs of network.\n\n                - weight: Weight of each gradient, 'weight' has the same shape with labels.\n\n        Returns:\n            Tensor, Jacobian matrix.\n        \"\"\"\n        gout = self.grad(self.network)(*data)\n        return gout\n\n\ndef calculate_iou(box_i, box_j):\n    \"\"\"\n    Calculate the intersection over union (iou) of two boxes.\n\n    Args:\n        box_i (numpy.ndarray): Coordinates of the first box, with the format as (x1, y1, x2, y2).\n            (x1, y1) and (x2, y2) are coordinates of the lower left corner and the upper right corner,\n            respectively.\n        box_j (numpy.ndarray): Coordinates of the second box, with the format as (x1, y1, x2, y2).\n\n    Returns:\n        float, iou of two input boxes.\n    \"\"\"\n    check_numpy_param('box_i', box_i)\n    check_numpy_param('box_j', box_j)\n    if box_i.shape[-1] != 4 or box_j.shape[-1] != 4:\n        msg = 'The length of both coordinate arrays should be 4, bug got {} and {}.'.format(box_i.shape, box_j.shape)\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n    i_x1, i_y1, i_x2, i_y2 = box_i\n    j_x1, j_y1, j_x2, j_y2 = box_j\n    s_i = (i_x2 - i_x1)*(i_y2 - i_y1)\n    s_j = (j_x2 - j_x1)*(j_y2 - j_y1)\n    inner_left_line = max(i_x1, j_x1)\n    inner_right_line = min(i_x2, j_x2)\n    inner_top_line = min(i_y2, j_y2)\n    inner_bottom_line = max(i_y1, j_y1)\n    if inner_left_line >= inner_right_line or inner_top_line <= inner_bottom_line:\n        return 0\n    inner_area = (inner_right_line - inner_left_line)*(inner_top_line - inner_bottom_line)\n    return inner_area / (s_i + s_j - inner_area)\n\n\ndef to_tensor_tuple(inputs_ori):\n    \"\"\"Transfer inputs data into tensor type.\"\"\"\n    inputs_ori = check_param_multi_types('inputs_ori', inputs_ori, [np.ndarray, tuple])\n    if isinstance(inputs_ori, tuple):\n        inputs_tensor = tuple()\n        for item in inputs_ori:\n            inputs_tensor += (Tensor(item),)\n    else:\n        inputs_tensor = (Tensor(inputs_ori),)\n    return inputs_tensor\n\n\ndef calculate_lp_distance(original_image, compared_image):\n    \"\"\"\n    Calculate l0, l2 and linf distance for two images with the same shape.\n\n    Args:\n        original_image (np.ndarray): Original image.\n        compared_image (np.ndarray): Another image for comparison.\n\n    Returns:\n        - float, l0 distances between two images.\n\n        - float, l2 distances between two images.\n\n        - float, linf distances between two images.\n\n    Raises:\n        TypeError: If type of `original_image` or type of `compared_image` is not numpy.ndarray.\n        ValueError: If the shape of `original_image` and `compared_image` are not the same.\n    \"\"\"\n    check_numpy_param('original_image', original_image)\n    check_numpy_param('compared_image', compared_image)\n    check_equal_shape('original_image', original_image, 'compared_image', compared_image)\n    avoid_zero_div = 1e-14\n    diff = (original_image - compared_image).flatten()\n    data = original_image.flatten()\n    l0_dist = np.linalg.norm(diff, ord=0) \\\n               / (np.linalg.norm(data, ord=0) + avoid_zero_div)\n    l2_dist = np.linalg.norm(diff, ord=2) \\\n               / (np.linalg.norm(data, ord=2) + avoid_zero_div)\n    linf_dist = np.linalg.norm(diff, ord=np.inf) \\\n                 / (np.linalg.norm(data, ord=np.inf) + avoid_zero_div)\n    return l0_dist, l2_dist, linf_dist\n\n\ndef _crop(arr, crop_width):\n    \"\"\"Crop arr by crop_width along each dimension.\"\"\"\n    arr = np.array(arr, copy=False)\n\n    if isinstance(crop_width, int):\n        crops = [[crop_width, crop_width]]*arr.ndim\n    elif isinstance(crop_width[0], int):\n        if len(crop_width) == 1:\n            crops = [[crop_width[0], crop_width[0]]]*arr.ndim\n        else:\n            crops = [crop_width]*arr.ndim\n    elif len(crop_width) == 1:\n        crops = [crop_width[0]]*arr.ndim\n    elif len(crop_width) == arr.ndim:\n        crops = crop_width\n    else:\n        msg = 'crop_width should be a sequence of N pairs, ' \\\n              'a single pair, or a single integer'\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n\n    slices = tuple(slice(a, arr.shape[i] - b) for i, (a, b) in enumerate(crops))\n\n    cropped = arr[slices]\n    return cropped\n\n\ndef compute_ssim(original_image, compared_image):\n    \"\"\"\n    compute structural similarity between two images.\n\n    Args:\n        original_image (numpy.ndarray): The first image to be compared.\n        compared_image (numpy.ndarray): The second image to be compared.\n\n    Returns:\n        float, structural similarity.\n    \"\"\"\n    if not original_image.shape == compared_image.shape:\n        msg = 'Input images must have the same dimensions, but got ' \\\n              'original_image.shape: {} and compared_image.shape: {}' \\\n            .format(original_image.shape, compared_image.shape)\n        LOGGER.error(TAG, msg)\n        raise ValueError()\n    if len(original_image.shape) == 3:  # rgb mode\n        if original_image.shape[0] in [1, 3]:  # from nhw to hwn\n            original_image = np.array(original_image).transpose(1, 2, 0)\n            compared_image = np.array(compared_image).transpose(1, 2, 0)\n        # loop over channels\n        n_channels = original_image.shape[-1]\n        total_ssim = np.empty(n_channels)\n        for ch in range(n_channels):\n            ch_result = compute_ssim(original_image[..., ch], compared_image[..., ch])\n            total_ssim[..., ch] = ch_result\n        return total_ssim.mean()\n\n    k1 = 0.01\n    k2 = 0.03\n    win_size = 7\n\n    if np.any((np.asarray(original_image.shape) - win_size) < 0):\n        msg = 'Size of each dimension must be larger win_size:7, ' \\\n              'but got image.shape:{}.' \\\n            .format(original_image.shape)\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n\n    original_image = original_image.astype(np.float64)\n    compared_image = compared_image.astype(np.float64)\n\n    ndim = original_image.ndim\n    tmp = win_size ** ndim\n    cov_norm = tmp / (tmp - 1)\n\n    # compute means\n    ux = uniform_filter(original_image, size=win_size)\n    uy = uniform_filter(compared_image, size=win_size)\n\n    # compute variances and covariances\n    uxx = uniform_filter(original_image*original_image, size=win_size)\n    uyy = uniform_filter(compared_image*compared_image, size=win_size)\n    uxy = uniform_filter(original_image*compared_image, size=win_size)\n\n    vx = cov_norm*(uxx - ux*ux)\n    vy = cov_norm*(uyy - uy*uy)\n    vxy = cov_norm*(uxy - ux*uy)\n\n    data_range = 2\n    c1 = (k1*data_range)**2\n    c2 = (k2*data_range)**2\n\n    a1 = 2*ux*uy + c1\n    a2 = 2*vxy + c2\n    b1 = ux**2 + uy**2 + c1\n    b2 = vx + vy + c2\n\n    d = b1*b2\n    s = (a1*a2) / d\n\n    # padding\n    pad = (win_size - 1) // 2\n    mean_ssim = _crop(s, pad).mean()\n    return mean_ssim\n\n\ndef compute_psnr(original_image, compared_image, data_range=None):\n    \"\"\"\n    Compute the peak signal to noise ratio (PSNR) for an image.\n\n    Args:\n        original_image : ndarray\n            Ground-truth image, same shape as im_test.\n        compared_image : ndarray\n            Test image.\n        data_range : int, optional\n            The data range of the input image (distance between minimum and\n            maximum possible values).  By default, this is estimated from the\n            image data-type.\n\n    Returns\n        psnr : float\n            The PSNR metric.\n    References\n    ----------\n    .. [1] https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio\n\n    \"\"\"\n    dtype_range = {\n        bool: (False, True),\n        np.bool_: (False, True),\n        float: (-1, 1),\n        np.float16: (-1, 1),\n        np.float32: (-1, 1),\n        np.float64: (-1, 1),\n    }\n    original_image = original_image.astype(np.float64)\n    compared_image = compared_image.astype(np.float64)\n    if not original_image.shape == compared_image.shape:\n        msg = 'Input images must have the same dimensions, but got ' \\\n              'original_image.shape: {} and compared_image.shape: {}' \\\n            .format(original_image.shape, compared_image.shape)\n        LOGGER.error(TAG, msg)\n        raise ValueError(msg)\n\n    if data_range is None:\n        dmin, dmax = dtype_range.get(original_image.dtype.type, [None, None])\n        if dmin is None or dmax is None:\n            msg = 'Input image dtype error, the type should in {} ' \\\n                    .format(list(dtype_range.keys()))\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n        true_min, true_max = np.min(original_image), np.max(compared_image)\n        if true_max > dmax or true_min < dmin:\n            msg = 'original_image has intensity values outside the range expected' \\\n                   'for its data type. Please manually specify the data_range.'\n            LOGGER.error(TAG, msg)\n            raise ValueError(msg)\n\n        if true_min >= 0:\n            # most common case (255 for uint8, 1 for float)\n            data_range = dmax\n        else:\n            data_range = dmax - dmin\n\n    err = np.mean((original_image - compared_image)**2, dtype=np.float64)\n    if err != 0:\n        return 10 * np.log10((data_range**2) / err)\n    return float('inf')\n"
  },
  {
    "path": "mindarmour/version.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Version of MindArmour\"\"\"\n__version__ = '2.1.0'\n"
  },
  {
    "path": "package.sh",
    "content": "#!/bin/bash\n# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nset -e\n\nBASEPATH=$(cd \"$(dirname $0)\"; pwd)\nOUTPUT_PATH=\"${BASEPATH}/output\"\nPYTHON=$(which python3)\n\nmk_new_dir() {\n    local create_dir=\"$1\"  # the target to make\n\n    if [[ -d \"${create_dir}\" ]];then\n        rm -rf \"${create_dir}\"\n    fi\n\n    mkdir -pv \"${create_dir}\"\n}\n\nwrite_checksum() {\n    cd \"$OUTPUT_PATH\" || exit\n    PACKAGE_LIST=$(ls mindarmour-*.whl) || exit\n    for PACKAGE_NAME in $PACKAGE_LIST; do\n        echo $PACKAGE_NAME\n        sha256sum -b \"$PACKAGE_NAME\" >\"$PACKAGE_NAME.sha256\"\n    done\n}\n\nmk_new_dir \"${OUTPUT_PATH}\"\n\n${PYTHON} ${BASEPATH}/setup.py bdist_wheel\n\nmv ${BASEPATH}/dist/*whl ${OUTPUT_PATH}\n\nwrite_checksum\n\n\necho \"------Successfully created mindarmour package------\"\n"
  },
  {
    "path": "requirements.txt",
    "content": "numpy >= 1.20.0,<2.0.0\nscipy >= 1.5.4\nmatplotlib >= 3.2.1\npillow >= 9.3.0\npytest >= 5.4.3\nwheel >= 0.32.0\nsetuptools >= 78.1.1\nscikit-learn >= 0.23.1\neasydict >= 1.9\nopencv-python >= 4.1.2.30"
  },
  {
    "path": "setup.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nsetup script\n\"\"\"\nimport os\nimport stat\nimport shlex\nimport shutil\nimport subprocess\nfrom setuptools import find_packages\nfrom setuptools import setup\nfrom setuptools.command.egg_info import egg_info\nfrom setuptools.command.build_py import build_py\n\nversion = '2.1.0'\ncur_dir = os.path.dirname(os.path.realpath(__file__))\npkg_dir = os.path.join(cur_dir, 'build')\n\n\ndef clean():\n    \"\"\"clean\"\"\"\n    def readonly_handler(func, path, execinfo):\n        os.chmod(path, stat.S_IWRITE)\n        func(path)\n    if os.path.exists(os.path.join(cur_dir, 'build')):\n        shutil.rmtree(os.path.join(cur_dir, 'build'), onerror=readonly_handler)\n    if os.path.exists(os.path.join(cur_dir, 'mindarmour.egg-info')):\n        shutil.rmtree(os.path.join(cur_dir, 'mindarmour.egg-info'), onerror=readonly_handler)\n\n\ndef write_version(file):\n    \"\"\"write version\"\"\"\n    file.write(\"__version__ = '{}'\\n\".format(version))\n\n\ndef build_depends():\n    \"\"\"generate python file\"\"\"\n    version_file = os.path.join(cur_dir, 'mindarmour/', 'version.py')\n    with open(version_file, 'w') as f:\n        write_version(f)\n\n\nclean()\nbuild_depends()\n\n\ndef update_permissions(path):\n    \"\"\"\n    Update permissions.\n\n    Args:\n        path (str): Target directory path.\n    \"\"\"\n    for dirpath, dirnames, filenames in os.walk(path):\n        for dirname in dirnames:\n            dir_fullpath = os.path.join(dirpath, dirname)\n            os.chmod(dir_fullpath, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC | stat.S_IRGRP | stat.S_IXGRP)\n        for filename in filenames:\n            file_fullpath = os.path.join(dirpath, filename)\n            os.chmod(file_fullpath, stat.S_IREAD)\n\n\ndef get_description():\n    \"\"\"\n    Get description.\n\n    Returns:\n        str, wheel package description.\n    \"\"\"\n    cmd = \"git log --format='[sha1]:%h, [branch]:%d' -1\"\n    process = subprocess.Popen(\n        shlex.split(cmd),\n        shell=False,\n        stdin=subprocess.PIPE,\n        stdout=subprocess.PIPE,\n        stderr=subprocess.PIPE\n    )\n    stdout, _ = process.communicate()\n    if not process.returncode:\n        git_version = stdout.decode().strip()\n        return \"A smart AI security and trustworthy tool box. Git version: %s\" % (git_version)\n    return \"A smart AI security and trustworthy tool box.\"\n\n\nclass EggInfo(egg_info):\n    \"\"\"Egg info.\"\"\"\n    def run(self):\n        super().run()\n        egg_info_dir = os.path.join(cur_dir, 'mindarmour.egg-info')\n        update_permissions(egg_info_dir)\n\n\nclass BuildPy(build_py):\n    \"\"\"BuildPy.\"\"\"\n    def run(self):\n        super().run()\n        mindarmour_dir = os.path.join(pkg_dir, 'lib', 'mindarmour')\n        update_permissions(mindarmour_dir)\n\n\nsetup(\n    name='mindarmour',\n    version=version,\n    author='The MindSpore Authors',\n    author_email='contact@mindspore.cn',\n    url='https://www.mindspore.cn/',\n    download_url='https://gitee.com/mindspore/mindarmour/tags',\n    project_urls={\n        'Sources': 'https://gitee.com/mindspore/mindarmour',\n        'Issue Tracker': 'https://gitee.com/mindspore/mindarmour/issues',\n    },\n    description=get_description(),\n    license='Apache 2.0',\n    packages=find_packages(),\n    include_package_data=True,\n    cmdclass={\n        'egg_info': EggInfo,\n        'build_py': BuildPy,\n    },\n    install_requires=[\n        'scipy >= 1.5.4',\n        'numpy >= 1.20.0,<2.0.0',\n        'matplotlib >= 3.2.1',\n        'pillow >= 9.3.0',\n        'scikit-learn >= 0.23.1',\n        'easydict >= 1.9',\n        'opencv-python >= 4.1.2.30',\n    ],\n    classifiers=[\n        'License :: OSI Approved :: Apache Software License'\n    ]\n)\nprint(find_packages())\n"
  },
  {
    "path": "tests/__init__.py",
    "content": ""
  },
  {
    "path": "tests/ut/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis package includes unit tests for developed features of MindArmour.\n\"\"\"\n"
  },
  {
    "path": "tests/ut/python/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis package includes python unit tests for developed features of MindArmour.\n\"\"\"\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis package includes unit tests for model attacks, model defenses and\ntheir evaluation functions.\n\"\"\"\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/attacks/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis package includes unit tests for white-box attack algorithms.\n\"\"\"\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/attacks/black/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis package includes unit tests for black-box attack algorithms.\n\"\"\"\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/attacks/black/test_genetic_attack.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nGenetic-Attack test.\n\"\"\"\nimport gc\nimport numpy as np\nimport pytest\n\nimport mindspore.ops.operations as M\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.nn import Cell\n\nfrom mindarmour import BlackModel\nfrom mindarmour.adv_robustness.attacks import GeneticAttack\n\n\n# for user\nclass ModelToBeAttacked(BlackModel):\n    \"\"\"model to be attack\"\"\"\n\n    def __init__(self, network):\n        super(ModelToBeAttacked, self).__init__()\n        self._network = network\n\n    def predict(self, inputs):\n        \"\"\"predict\"\"\"\n        result = self._network(Tensor(inputs.astype(np.float32)))\n        return result.asnumpy()\n\n\nclass DetectionModel(BlackModel):\n    \"\"\"model to be attack\"\"\"\n\n    def predict(self, inputs):\n        \"\"\"predict\"\"\"\n        # Adapt to the input shape requirements of the target network if inputs is only one image.\n        if len(inputs.shape) == 3:\n            inputs_num = 1\n        else:\n            inputs_num = inputs.shape[0]\n        box_and_confi = []\n        pred_labels = []\n        gt_number = np.random.randint(1, 128)\n\n        for _ in range(inputs_num):\n            boxes_i = np.random.random((gt_number, 5))\n            labels_i = np.random.randint(0, 10, gt_number)\n            box_and_confi.append(boxes_i)\n            pred_labels.append(labels_i)\n        return np.array(box_and_confi), np.array(pred_labels)\n\n\nclass SimpleNet(Cell):\n    \"\"\"\n    Construct the network of target model.\n\n    Examples:\n        >>> net = SimpleNet()\n    \"\"\"\n\n    def __init__(self):\n        \"\"\"\n        Introduce the layers used for network construction.\n        \"\"\"\n        super(SimpleNet, self).__init__()\n        self._softmax = M.Softmax()\n\n    def construct(self, inputs):\n        \"\"\"\n        Construct network.\n\n        Args:\n            inputs (Tensor): Input data.\n        \"\"\"\n        out = self._softmax(inputs)\n        return out\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_genetic_attack():\n    \"\"\"\n    Genetic_Attack test\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    batch_size = 6\n\n    net = SimpleNet()\n    inputs = np.random.rand(batch_size, 10)\n\n    model = ModelToBeAttacked(net)\n    labels = np.random.randint(low=0, high=10, size=batch_size)\n    labels = np.eye(10)[labels]\n    labels = labels.astype(np.float32)\n\n    attack = GeneticAttack(model, pop_size=6, mutation_rate=0.05,\n                           per_bounds=0.1, step_size=0.25, temp=0.1,\n                           sparse=False)\n    _, adv_data, _ = attack.generate(inputs, labels)\n    assert np.any(inputs != adv_data)\n    del inputs, labels, adv_data\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_supplement():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    batch_size = 6\n\n    net = SimpleNet()\n    inputs = np.random.rand(batch_size, 10)\n\n    model = ModelToBeAttacked(net)\n    labels = np.random.randint(low=0, high=10, size=batch_size)\n    labels = np.eye(10)[labels]\n    labels = labels.astype(np.float32)\n\n    attack = GeneticAttack(model, pop_size=6, mutation_rate=0.05,\n                           per_bounds=0.1, step_size=0.25, temp=0.1,\n                           adaptive=True,\n                           sparse=False)\n    # raise error\n    _, _, _ = attack.generate(inputs, labels)\n    del inputs, labels\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_value_error():\n    \"\"\"test that exception is raised for invalid labels\"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    batch_size = 6\n\n    net = SimpleNet()\n    inputs = np.random.rand(batch_size, 10)\n\n    model = ModelToBeAttacked(net)\n    labels = np.random.randint(low=0, high=10, size=batch_size)\n    # labels = np.eye(10)[labels]\n    labels = labels.astype(np.float32)\n\n    attack = GeneticAttack(model, pop_size=6, mutation_rate=0.05,\n                           per_bounds=0.1, step_size=0.25, temp=0.1,\n                           adaptive=True,\n                           sparse=False)\n    # raise error\n    with pytest.raises(ValueError):\n        assert attack.generate(inputs, labels)\n    del inputs, labels\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_genetic_attack_detection_cpu():\n    \"\"\"\n    Genetic_Attack test\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    batch_size = 2\n    inputs = np.random.random((batch_size, 100, 100, 3))\n    model = DetectionModel()\n    attack = GeneticAttack(model, model_type='detection', pop_size=6, mutation_rate=0.05,\n                           per_bounds=0.1, step_size=0.25, temp=0.1,\n                           sparse=False, max_steps=50)\n\n    # generate adversarial samples\n    adv_imgs = []\n    for i in range(batch_size):\n        img_data = np.expand_dims(inputs[i], axis=0)\n        pre_gt_boxes, pre_gt_labels = model.predict(inputs)\n        _, adv_img, _ = attack.generate(img_data, (pre_gt_boxes, pre_gt_labels))\n        adv_imgs.append(adv_img)\n    assert np.any(inputs != np.array(adv_imgs))\n    del inputs, adv_imgs\n    gc.collect()\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/attacks/black/test_hsja.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\nimport gc\nimport numpy as np\nimport pytest\n\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\n\nfrom mindarmour import BlackModel\nfrom mindarmour.adv_robustness.attacks import HopSkipJumpAttack\nfrom mindarmour.utils.logger import LogUtil\n\nfrom tests.ut.python.utils.mock_net import Net\n\ncontext.set_context(mode=context.GRAPH_MODE)\n\nLOGGER = LogUtil.get_instance()\nTAG = 'HopSkipJumpAttack'\n\n\nclass ModelToBeAttacked(BlackModel):\n    \"\"\"model to be attack\"\"\"\n\n    def __init__(self, network):\n        super(ModelToBeAttacked, self).__init__()\n        self._network = network\n\n    def predict(self, inputs):\n        \"\"\"predict\"\"\"\n        if len(inputs.shape) == 3:\n            inputs = inputs[np.newaxis, :]\n        result = self._network(Tensor(inputs.astype(np.float32)))\n        return result.asnumpy()\n\n\ndef random_target_labels(true_labels):\n    target_labels = []\n    for label in true_labels:\n        while True:\n            target_label = np.random.randint(0, 10)\n            if target_label != label:\n                target_labels.append(target_label)\n                break\n    return target_labels\n\n\ndef create_target_images(dataset, data_labels, target_labels):\n    res = []\n    for label in target_labels:\n        for i, data_label in enumerate(data_labels):\n            if data_label == label:\n                res.append(dataset[i])\n                break\n    return np.array(res)\n\n\n# public variable\ndef get_model():\n    # upload trained network\n    current_dir = os.path.dirname(os.path.abspath(__file__))\n    ckpt_path = os.path.join(current_dir,\n                             '../../../dataset/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt')\n    net = Net()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n    net.set_train(False)\n    model = ModelToBeAttacked(net)\n    return model\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_hsja_mnist_attack_ascend():\n    \"\"\"\n    Feature: test HSJA attack for ascend\n    Description: make sure the HSJA attack works properly\n    Expectation: predict without any bugs\n    \"\"\"\n    context.set_context(device_target=\"Ascend\")\n    current_dir = os.path.dirname(os.path.abspath(__file__))\n\n\n    # get test data\n    test_images_set = np.load(os.path.join(current_dir,\n                                           '../../../dataset/test_images.npy'))\n    test_labels_set = np.load(os.path.join(current_dir,\n                                           '../../../dataset/test_labels.npy'))\n    # prediction accuracy before attack\n    model = get_model()\n    batch_num = 1  # the number of batches of attacking samples\n    predict_labels = []\n    i = 0\n\n    for img in test_images_set:\n        i += 1\n        pred_labels = np.argmax(model.predict(img), axis=1)\n        predict_labels.append(pred_labels)\n        if i >= batch_num:\n            break\n    predict_labels = np.concatenate(predict_labels)\n    true_labels = test_labels_set[:batch_num]\n    accuracy = np.mean(np.equal(predict_labels, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %s\",\n                accuracy)\n    test_images = test_images_set[:batch_num]\n\n    # attacking\n    norm = 'l2'\n    search = 'grid_search'\n    target = False\n\n    attack = HopSkipJumpAttack(model, constraint=norm, stepsize_search=search)\n    if target:\n        target_labels = random_target_labels(true_labels)\n        target_images = create_target_images(test_images_set, test_labels_set,\n                                             target_labels)\n        LOGGER.info(TAG, 'len target labels : %s', len(target_labels))\n        LOGGER.info(TAG, 'len target_images : %s', len(target_images))\n        LOGGER.info(TAG, 'len test_images : %s', len(test_images))\n        attack.set_target_images(target_images)\n        success_list, adv_data, _ = attack.generate(test_images, target_labels)\n    else:\n        success_list, adv_data, _ = attack.generate(test_images, None)\n    assert (adv_data != test_images).any()\n\n    adv_datas = []\n    gts = []\n    for success, adv, gt in zip(success_list, adv_data, true_labels):\n        if success:\n            adv_datas.append(adv)\n            gts.append(gt)\n    if gts:\n        adv_datas = np.concatenate(np.asarray(adv_datas), axis=0)\n        gts = np.asarray(gts)\n        pred_logits_adv = model.predict(adv_datas)\n        pred_lables_adv = np.argmax(pred_logits_adv, axis=1)\n        accuracy_adv = np.mean(np.equal(pred_lables_adv, gts))\n        LOGGER.info(TAG, 'mis-classification rate of adversaries is : %s',\n                    accuracy_adv)\n    del pred_labels, adv_data, predict_labels, true_labels\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_hsja_mnist_attack_cpu():\n    \"\"\"\n    Feature: test HSJA attack for cpu\n    Description: make sure the HSJA attack works properly\n    Expectation: predict without any bugs\n    \"\"\"\n    context.set_context(device_target=\"CPU\")\n    current_dir = os.path.dirname(os.path.abspath(__file__))\n\n\n    # get test data\n    test_images_set = np.load(os.path.join(current_dir,\n                                           '../../../dataset/test_images.npy'))\n    test_labels_set = np.load(os.path.join(current_dir,\n                                           '../../../dataset/test_labels.npy'))\n    # prediction accuracy before attack\n    model = get_model()\n    batch_num = 1  # the number of batches of attacking samples\n    predict_labels = []\n    i = 0\n\n    for img in test_images_set:\n        i += 1\n        pred_labels = np.argmax(model.predict(img), axis=1)\n        predict_labels.append(pred_labels)\n        if i >= batch_num:\n            break\n    predict_labels = np.concatenate(predict_labels)\n    true_labels = test_labels_set[:batch_num]\n    accuracy = np.mean(np.equal(predict_labels, true_labels))\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %s\",\n                accuracy)\n    test_images = test_images_set[:batch_num]\n\n    # attacking\n    norm = 'l2'\n    search = 'grid_search'\n    target = False\n\n    attack = HopSkipJumpAttack(model, constraint=norm, stepsize_search=search)\n    if target:\n        target_labels = random_target_labels(true_labels)\n        target_images = create_target_images(test_images_set, test_labels_set,\n                                             target_labels)\n        LOGGER.info(TAG, 'len target labels : %s', len(target_labels))\n        LOGGER.info(TAG, 'len target_images : %s', len(target_images))\n        LOGGER.info(TAG, 'len test_images : %s', len(test_images))\n        attack.set_target_images(target_images)\n        success_list, adv_data, _ = attack.generate(test_images, target_labels)\n    else:\n        success_list, adv_data, _ = attack.generate(test_images, None)\n    assert (adv_data != test_images).any()\n\n    adv_datas = []\n    gts = []\n    for success, adv, gt in zip(success_list, adv_data, true_labels):\n        if success:\n            adv_datas.append(adv)\n            gts.append(gt)\n    if gts:\n        adv_datas = np.concatenate(np.asarray(adv_datas), axis=0)\n        gts = np.asarray(gts)\n        pred_logits_adv = model.predict(adv_datas)\n        pred_lables_adv = np.argmax(pred_logits_adv, axis=1)\n        accuracy_adv = np.mean(np.equal(pred_lables_adv, gts))\n        LOGGER.info(TAG, 'mis-classification rate of adversaries is : %s',\n                    accuracy_adv)\n    del pred_labels, adv_data, predict_labels, true_labels\n    gc.collect()\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_value_error_ascend():\n    context.set_context(device_target=\"Ascend\")\n    model = get_model()\n    norm = 'l2'\n    with pytest.raises(ValueError):\n        assert HopSkipJumpAttack(model, constraint=norm, stepsize_search='bad-search')\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_value_error_cpu():\n    context.set_context(device_target=\"CPU\")\n    model = get_model()\n    norm = 'l2'\n    with pytest.raises(ValueError):\n        assert HopSkipJumpAttack(model, constraint=norm, stepsize_search='bad-search')\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/attacks/black/test_nes.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport os\n\nimport numpy as np\nimport pytest\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\n\nfrom mindarmour import BlackModel\nfrom mindarmour.adv_robustness.attacks import NES\nfrom mindarmour.utils.logger import LogUtil\n\nfrom tests.ut.python.utils.mock_net import Net\n\ncontext.set_context(mode=context.GRAPH_MODE)\n\nLOGGER = LogUtil.get_instance()\nTAG = 'NaturalEvolutionaryStrategy'\n\n\nclass ModelToBeAttacked(BlackModel):\n    \"\"\"model to be attack\"\"\"\n\n    def __init__(self, network):\n        super(ModelToBeAttacked, self).__init__()\n        self._network = network\n\n    def predict(self, inputs):\n        \"\"\"predict\"\"\"\n        if len(inputs.shape) == 3:\n            inputs = inputs[np.newaxis, :]\n        result = self._network(Tensor(inputs.astype(np.float32)))\n        return result.asnumpy()\n\n\ndef random_target_labels(true_labels):\n    target_labels = []\n    for label in true_labels:\n        while True:\n            target_label = np.random.randint(0, 10)\n            if target_label != label:\n                target_labels.append(target_label)\n                break\n    return target_labels\n\n\ndef _pseudorandom_target(index, total_indices, true_class):\n    \"\"\" pseudo random_target \"\"\"\n    rng = np.random.RandomState(index)\n    target = true_class\n    while target == true_class:\n        target = rng.randint(0, total_indices)\n    return target\n\n\ndef create_target_images(dataset, data_labels, target_labels):\n    res = []\n    for label in target_labels:\n        for i, data_label in enumerate(data_labels):\n            if data_label == label:\n                res.append(dataset[i])\n                break\n    return np.array(res)\n\n\ndef get_model(current_dir):\n    ckpt_path = os.path.join(current_dir,\n                             '../../../dataset/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt')\n    net = Net()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n    net.set_train(False)\n    model = ModelToBeAttacked(net)\n    return model\n\n\ndef get_dataset(current_dir):\n    # upload trained network\n\n    # get test data\n    test_images = np.load(os.path.join(current_dir,\n                                       '../../../dataset/test_images.npy'))\n    test_labels = np.load(os.path.join(current_dir,\n                                       '../../../dataset/test_labels.npy'))\n    return test_images, test_labels\n\n\ndef nes_mnist_attack(scene, top_k):\n    \"\"\"\n    nes-Attack test\n    \"\"\"\n    current_dir = os.path.dirname(os.path.abspath(__file__))\n    test_images, test_labels = get_dataset(current_dir)\n    model = get_model(current_dir)\n    # prediction accuracy before attack\n    batch_num = 5  # the number of batches of attacking samples\n    predict_labels = []\n    i = 0\n    for img in test_images:\n        i += 1\n        pred_labels = np.argmax(model.predict(img), axis=1)\n        predict_labels.append(pred_labels)\n        if i >= batch_num:\n            break\n    predict_labels = np.concatenate(predict_labels)\n    true_labels = test_labels\n    accuracy = np.mean(np.equal(predict_labels, true_labels[:batch_num]))\n    LOGGER.info(TAG, \"prediction accuracy before attacking is : %s\",\n                accuracy)\n    test_images = test_images\n\n    # attacking\n    if scene == 'Query_Limit':\n        top_k = -1\n    elif scene == 'Partial_Info':\n        top_k = top_k\n    elif scene == 'Label_Only':\n        top_k = top_k\n\n    success = 0\n    queries_num = 0\n\n    nes_instance = NES(model, scene, top_k=top_k)\n    test_length = 1\n    advs = []\n    for img_index in range(test_length):\n        # INITIAL IMAGE AND CLASS SELECTION\n        initial_img = test_images[img_index]\n        orig_class = true_labels[img_index]\n        initial_img = [initial_img]\n        target_class = random_target_labels([orig_class])\n        target_image = create_target_images(test_images, true_labels,\n                                            target_class)\n\n        nes_instance.set_target_images(target_image)\n        tag, adv, queries = nes_instance.generate(np.array(initial_img), np.array(target_class))\n        if tag[0]:\n            success += 1\n        queries_num += queries[0]\n        advs.append(adv)\n\n    advs = np.reshape(advs, (len(advs), 1, 32, 32))\n    assert (advs != test_images[:batch_num]).any()\n\n    adv_pred = np.argmax(model.predict(advs), axis=1)\n    _ = np.mean(np.equal(adv_pred, true_labels[:test_length]))\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_nes_query_limit_ascend():\n    \"\"\"\n    Feature: nes query limited for ascend\n    Description: make sure the attck in query limit scene works properly\n    Expectation: attack without any bugs\n    \"\"\"\n    # scene is in ['Query_Limit', 'Partial_Info', 'Label_Only']\n    context.set_context(device_target=\"Ascend\")\n    scene = 'Query_Limit'\n    nes_mnist_attack(scene, top_k=-1)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_nes_query_limit_cpu():\n    \"\"\"\n    Feature: nes query limited for cpu\n    Description: make sure the attck in query limit scene works properly\n    Expectation: attack without any bugs\n    \"\"\"\n    # scene is in ['Query_Limit', 'Partial_Info', 'Label_Only']\n    context.set_context(device_target=\"CPU\")\n    scene = 'Query_Limit'\n    nes_mnist_attack(scene, top_k=-1)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_nes_partial_info_ascend():\n    \"\"\"\n    Feature: nes partial info for ascend\n    Description: make sure the attck in partial info scene works properly\n    Expectation: attack without any bugs\n    \"\"\"\n    # scene is in ['Query_Limit', 'Partial_Info', 'Label_Only']\n    context.set_context(device_target=\"Ascend\")\n    scene = 'Partial_Info'\n    nes_mnist_attack(scene, top_k=5)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_nes_partial_info_cpu():\n    \"\"\"\n    Feature: nes partial info for cpu\n    Description: make sure the attck in partial info scene works properly\n    Expectation: attack without any bugs\n    \"\"\"\n    # scene is in ['Query_Limit', 'Partial_Info', 'Label_Only']\n    context.set_context(device_target=\"CPU\")\n    scene = 'Partial_Info'\n    nes_mnist_attack(scene, top_k=5)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_nes_label_only_ascend():\n    \"\"\"\n    Feature: nes label only for ascend\n    Description: make sure the attck in label only scene works properly\n    Expectation: attack without any bugs\n    \"\"\"\n    # scene is in ['Query_Limit', 'Partial_Info', 'Label_Only']\n    context.set_context(device_target=\"Ascend\")\n    scene = 'Label_Only'\n    nes_mnist_attack(scene, top_k=5)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_nes_label_only_cpu():\n    \"\"\"\n    Feature: nes label only for cpu\n    Description: make sure the attck in label only scene works properly\n    Expectation: attack without any bugs\n    \"\"\"\n    # scene is in ['Query_Limit', 'Partial_Info', 'Label_Only']\n    context.set_context(device_target=\"CPU\")\n    scene = 'Label_Only'\n    nes_mnist_attack(scene, top_k=5)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_value_error_ascend():\n    \"\"\"test that exception is raised for invalid labels\"\"\"\n    context.set_context(device_target=\"Ascend\")\n    with pytest.raises(ValueError):\n        assert nes_mnist_attack('Label_Only', -1)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_value_error_cpu():\n    \"\"\"test that exception is raised for invalid labels\"\"\"\n    context.set_context(device_target=\"CPU\")\n    with pytest.raises(ValueError):\n        assert nes_mnist_attack('Label_Only', -1)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_none_ascend():\n    \"\"\"\n    Feature: nes none for ascend\n    Description: detect error or works properly\n    Expectation: detect error or works properly\n    \"\"\"\n    context.set_context(device_target=\"Ascend\")\n    current_dir = os.path.dirname(os.path.abspath(__file__))\n    model = get_model(current_dir)\n    test_images, test_labels = get_dataset(current_dir)\n    nes = NES(model, 'Partial_Info')\n    with pytest.raises(ValueError):\n        assert nes.generate(test_images, test_labels)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_none_cpu():\n    \"\"\"\n    Feature: nes none for cpu\n    Description: detect error or works properly\n    Expectation: detect error or works properly\n    \"\"\"\n    context.set_context(device_target=\"CPU\")\n    current_dir = os.path.dirname(os.path.abspath(__file__))\n    model = get_model(current_dir)\n    test_images, test_labels = get_dataset(current_dir)\n    nes = NES(model, 'Partial_Info')\n    with pytest.raises(ValueError):\n        assert nes.generate(test_images, test_labels)\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/attacks/black/test_pointwise_attack.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nPointWise Attack test\n\"\"\"\nimport os\nimport gc\n\nimport numpy as np\nimport pytest\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\n\nfrom mindarmour import BlackModel\nfrom mindarmour.adv_robustness.attacks import PointWiseAttack\nfrom mindarmour.utils.logger import LogUtil\n\nfrom tests.ut.python.utils.mock_net import Net\n\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Pointwise_Test'\nLOGGER.set_level('INFO')\n\n\nclass ModelToBeAttacked(BlackModel):\n    \"\"\"model to be attack\"\"\"\n\n    def __init__(self, network):\n        super(ModelToBeAttacked, self).__init__()\n        self._network = network\n\n    def predict(self, inputs):\n        \"\"\"predict\"\"\"\n        result = self._network(Tensor(inputs.astype(np.float32)))\n        return result.asnumpy()\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_pointwise_attack_method_ascend():\n    \"\"\"\n    Feature: Pointwise attack method unit test for ascend\n    Description: Given a image, we want to make sure the adversarial example\n                 generated is different from the image\n    Expectation: input_np != adv_data\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    np.random.seed(123)\n    # upload trained network\n    current_dir = os.path.dirname(os.path.abspath(__file__))\n    ckpt_path = os.path.join(current_dir,\n                             '../../../dataset/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt')\n    net = Net()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get one mnist image\n    input_np = np.load(os.path.join(current_dir,\n                                    '../../../dataset/test_images.npy'))[:3]\n    labels = np.load(os.path.join(current_dir,\n                                  '../../../dataset/test_labels.npy'))[:3]\n    model = ModelToBeAttacked(net)\n    pre_label = np.argmax(model.predict(input_np), axis=1)\n    LOGGER.info(TAG, 'original sample predict labels are :{}'.format(pre_label))\n    LOGGER.info(TAG, 'true labels are: {}'.format(labels))\n    attack = PointWiseAttack(model, sparse=True, is_targeted=False)\n    is_adv, adv_data, _ = attack.generate(input_np, pre_label)\n    LOGGER.info(TAG, 'adv sample predict labels are: {}'\n                .format(np.argmax(model.predict(adv_data), axis=1)))\n\n    assert np.any(adv_data[is_adv][0] != input_np[is_adv][0]), 'Pointwise attack method: ' \\\n                                             'generate value must not be equal' \\\n                                             ' to original value.'\n    del input_np, labels, adv_data\n    gc.collect()\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_pointwise_attack_method_cpu():\n    \"\"\"\n    Feature: Pointwise attack method unit test for cpu\n    Description: Given a image, we want to make sure the adversarial example\n                 generated is different from the image\n    Expectation: input_np != adv_data\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    np.random.seed(123)\n    # upload trained network\n    current_dir = os.path.dirname(os.path.abspath(__file__))\n    ckpt_path = os.path.join(current_dir,\n                             '../../../dataset/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt')\n    net = Net()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get one mnist image\n    input_np = np.load(os.path.join(current_dir,\n                                    '../../../dataset/test_images.npy'))[:3]\n    labels = np.load(os.path.join(current_dir,\n                                  '../../../dataset/test_labels.npy'))[:3]\n    model = ModelToBeAttacked(net)\n    pre_label = np.argmax(model.predict(input_np), axis=1)\n    LOGGER.info(TAG, 'original sample predict labels are :{}'.format(pre_label))\n    LOGGER.info(TAG, 'true labels are: {}'.format(labels))\n    attack = PointWiseAttack(model, sparse=True, is_targeted=False)\n    is_adv, adv_data, _ = attack.generate(input_np, pre_label)\n    LOGGER.info(TAG, 'adv sample predict labels are: {}'\n                .format(np.argmax(model.predict(adv_data), axis=1)))\n\n    assert np.any(adv_data[is_adv][0] != input_np[is_adv][0]), 'Pointwise attack method: ' \\\n                                             'generate value must not be equal' \\\n                                             ' to original value.'\n    del input_np, labels, adv_data\n    gc.collect()\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/attacks/black/test_pso_attack.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nPSO-Attack test.\n\"\"\"\nimport gc\nimport numpy as np\nimport pytest\n\nfrom mindspore import Tensor\nimport mindspore.nn as nn\nfrom mindspore.nn import Cell\nfrom mindspore import context\n\nfrom mindarmour.adv_robustness.attacks import PSOAttack\nfrom mindarmour import BlackModel\n\n\n# for user\nclass ModelToBeAttacked(BlackModel):\n    \"\"\"model to be attack\"\"\"\n\n    def __init__(self, network):\n        super(ModelToBeAttacked, self).__init__()\n        self._network = network\n\n    def predict(self, inputs):\n        \"\"\"predict\"\"\"\n        # Adapt to the input shape requirements of the target network if inputs is only one image.\n        if len(inputs.shape) == 1:\n            inputs = np.expand_dims(inputs, axis=0)\n        result = self._network(Tensor(inputs.astype(np.float32)))\n        return result.asnumpy()\n\n\nclass DetectionModel(BlackModel):\n    \"\"\"model to be attack\"\"\"\n\n    def predict(self, inputs):\n        \"\"\"predict\"\"\"\n        # Adapt to the input shape requirements of the target network if inputs is only one image.\n        if len(inputs.shape) == 3:\n            inputs_num = 1\n        else:\n            inputs_num = inputs.shape[0]\n        box_and_confi = []\n        pred_labels = []\n        gt_number = np.random.randint(1, 128)\n\n        for _ in range(inputs_num):\n            boxes_i = np.random.random((gt_number, 5))\n            labels_i = np.random.randint(0, 10, gt_number)\n            box_and_confi.append(boxes_i)\n            pred_labels.append(labels_i)\n        return np.array(box_and_confi), np.array(pred_labels)\n\n\nclass SimpleNet(Cell):\n    \"\"\"\n    Construct the network of target model.\n\n    Examples:\n        >>> net = SimpleNet()\n    \"\"\"\n\n    def __init__(self):\n        \"\"\"\n        Introduce the layers used for network construction.\n        \"\"\"\n        super(SimpleNet, self).__init__()\n\n        self._relu = nn.ReLU()\n\n    def construct(self, inputs):\n        \"\"\"\n        Construct network.\n\n        Args:\n            inputs (Tensor): Input data.\n        \"\"\"\n        out = self._relu(inputs)\n        return out\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_pso_attack():\n    \"\"\"\n    PSO_Attack test\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    batch_size = 6\n\n    net = SimpleNet()\n    inputs = np.random.rand(batch_size, 10)\n\n    model = ModelToBeAttacked(net)\n    labels = np.random.randint(low=0, high=10, size=batch_size)\n    labels = np.eye(10)[labels]\n    labels = labels.astype(np.float32)\n\n    attack = PSOAttack(model, bounds=(0.0, 1.0), pm=0.5, sparse=False)\n    _, adv_data, _ = attack.generate(inputs, labels)\n    assert np.any(inputs != adv_data)\n    del inputs, labels, adv_data\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_pso_attack_targeted():\n    \"\"\"\n    PSO_Attack test\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    batch_size = 6\n\n    net = SimpleNet()\n    inputs = np.random.rand(batch_size, 10)\n\n    model = ModelToBeAttacked(net)\n    labels = np.random.randint(low=0, high=10, size=batch_size)\n    labels = np.eye(10)[labels]\n    labels = labels.astype(np.float32)\n\n    attack = PSOAttack(model, bounds=(0.0, 1.0), pm=0.5, targeted=True,\n                       sparse=False)\n    _, adv_data, _ = attack.generate(inputs, labels)\n    assert np.any(inputs != adv_data)\n    del inputs, labels, adv_data\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_gpu_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_pso_attack_gpu():\n    \"\"\"\n    PSO_Attack test\n    \"\"\"\n    context.set_context(device_target=\"GPU\")\n    batch_size = 6\n\n    net = SimpleNet()\n    inputs = np.random.rand(batch_size, 10)\n\n    model = ModelToBeAttacked(net)\n    labels = np.random.randint(low=0, high=10, size=batch_size)\n    labels = np.eye(10)[labels]\n    labels = labels.astype(np.float32)\n\n    attack = PSOAttack(model, bounds=(0.0, 1.0), pm=0.5, sparse=False)\n    _, adv_data, _ = attack.generate(inputs, labels)\n    assert np.any(inputs != adv_data)\n    del inputs, labels, adv_data\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_pso_attack_cpu():\n    \"\"\"\n    PSO_Attack test\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    batch_size = 6\n\n    net = SimpleNet()\n    inputs = np.random.rand(batch_size, 10)\n\n    model = ModelToBeAttacked(net)\n    labels = np.random.randint(low=0, high=10, size=batch_size)\n    labels = np.eye(10)[labels]\n    labels = labels.astype(np.float32)\n\n    attack = PSOAttack(model, bounds=(0.0, 1.0), pm=0.5, sparse=False)\n    _, adv_data, _ = attack.generate(inputs, labels)\n    assert np.any(inputs != adv_data)\n    del inputs, labels, adv_data\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_pso_attack_detection_cpu():\n    \"\"\"\n    PSO_Attack test\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    batch_size = 2\n    inputs = np.random.random((batch_size, 100, 100, 3))\n    model = DetectionModel()\n    attack = PSOAttack(model, t_max=30, pm=0.5, model_type='detection', reserve_ratio=0.5)\n\n    # generate adversarial samples\n    adv_imgs = []\n    for i in range(batch_size):\n        img_data = np.expand_dims(inputs[i], axis=0)\n        pre_gt_boxes, pre_gt_labels = model.predict(inputs)\n        _, adv_img, _ = attack.generate(img_data, (pre_gt_boxes, pre_gt_labels))\n        adv_imgs.append(adv_img)\n    assert np.any(inputs != np.array(adv_imgs))\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/attacks/black/test_salt_and_pepper_attack.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nSaltAndPepper Attack Test\n\"\"\"\nimport os\nimport gc\nimport numpy as np\nimport pytest\n\nfrom mindspore import Tensor\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nfrom mindspore import context\n\nfrom mindarmour import BlackModel\nfrom mindarmour.adv_robustness.attacks import SaltAndPepperNoiseAttack\nfrom tests.ut.python.utils.mock_net import Net\n\ncontext.set_context(mode=context.GRAPH_MODE)\n\n\nclass ModelToBeAttacked(BlackModel):\n    \"\"\"model to be attack\"\"\"\n\n    def __init__(self, network):\n        super(ModelToBeAttacked, self).__init__()\n        self._network = network\n\n    def predict(self, inputs):\n        \"\"\"predict\"\"\"\n        result = self._network(Tensor(inputs.astype(np.float32)))\n        return result.asnumpy()\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_salt_and_pepper_attack_method_ascend():\n    \"\"\"\n    Feature: Salt and pepper attack method unit test for ascend\n    Description: Given a image, we want to make sure the adversarial example\n                 generated is different from the image\n    Expectation: inputs != adv_data\n    \"\"\"\n    context.set_context(device_target=\"Ascend\")\n    np.random.seed(123)\n    # upload trained network\n    current_dir = os.path.dirname(os.path.abspath(__file__))\n    ckpt_path = os.path.join(current_dir,\n                             '../../../dataset/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt')\n    net = Net()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get one mnist image\n    inputs = np.load(os.path.join(current_dir, '../../../dataset/test_images.npy'))[:3]\n    labels = np.load(os.path.join(current_dir, '../../../dataset/test_labels.npy'))[:3]\n    model = ModelToBeAttacked(net)\n\n    attack = SaltAndPepperNoiseAttack(model, sparse=True)\n    _, adv_data, _ = attack.generate(inputs, labels)\n    assert np.any(adv_data[0] != inputs[0]), 'Salt and pepper attack method:  generate value must not be equal' \\\n                                             ' to original value.'\n    del inputs, labels, adv_data\n    gc.collect()\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_salt_and_pepper_attack_method_cpu():\n    \"\"\"\n    Feature: Salt and pepper attack method unit test for cpu\n    Description: Given a image, we want to make sure the adversarial example\n                 generated is different from the image\n    Expectation: inputs != adv_data\n    \"\"\"\n    context.set_context(device_target=\"CPU\")\n    np.random.seed(123)\n    # upload trained network\n    current_dir = os.path.dirname(os.path.abspath(__file__))\n    ckpt_path = os.path.join(current_dir,\n                             '../../../dataset/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt')\n    net = Net()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get one mnist image\n    inputs = np.load(os.path.join(current_dir, '../../../dataset/test_images.npy'))[:3]\n    labels = np.load(os.path.join(current_dir, '../../../dataset/test_labels.npy'))[:3]\n    model = ModelToBeAttacked(net)\n\n    attack = SaltAndPepperNoiseAttack(model, sparse=True)\n    _, adv_data, _ = attack.generate(inputs, labels)\n    assert np.any(adv_data[0] != inputs[0]), 'Salt and pepper attack method:  generate value must not be equal' \\\n                                             ' to original value.'\n    del inputs, labels, adv_data\n    gc.collect()\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/attacks/test_batch_generate_attack.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nBatch-generate-attack test.\n\"\"\"\nimport gc\nimport numpy as np\nimport pytest\n\nimport mindspore.context as context\nimport mindspore.ops.operations as P\nfrom mindspore.ops.composite import GradOperation\nfrom mindspore.nn import Cell, SoftmaxCrossEntropyWithLogits\n\nfrom mindarmour.adv_robustness.attacks import FastGradientMethod\n\n\n\n# for user\nclass Net(Cell):\n    \"\"\"\n    Construct the network of target model.\n\n    Examples:\n        >>> net = Net()\n    \"\"\"\n\n    def __init__(self):\n        \"\"\"\n        Introduce the layers used for network construction.\n        \"\"\"\n        super(Net, self).__init__()\n        self._softmax = P.Softmax()\n\n    def construct(self, inputs):\n        \"\"\"\n        Construct network.\n\n        Args:\n            inputs (Tensor): Input data.\n        \"\"\"\n        out = self._softmax(inputs)\n        return out\n\n\nclass Net2(Cell):\n    \"\"\"\n    Construct the network of target model. A network with multiple input data.\n\n    Examples:\n        >>> net = Net2()\n    \"\"\"\n\n    def __init__(self):\n        super(Net2, self).__init__()\n        self._softmax = P.Softmax()\n\n    def construct(self, inputs1, inputs2):\n        out1 = self._softmax(inputs1)\n        out2 = self._softmax(inputs2)\n        return out1 + out2, out1 - out2\n\n\nclass LossNet(Cell):\n    \"\"\"\n    Loss function for test.\n    \"\"\"\n    def construct(self, loss1, loss2, labels1, labels2):\n        return loss1 + loss2 - labels1 - labels2\n\n\nclass WithLossCell(Cell):\n    \"\"\"Wrap the network with loss function\"\"\"\n    def __init__(self, backbone, loss_fn):\n        super(WithLossCell, self).__init__(auto_prefix=False)\n        self._backbone = backbone\n        self._loss_fn = loss_fn\n\n    def construct(self, inputs1, inputs2, labels1, labels2):\n        out = self._backbone(inputs1, inputs2)\n        return self._loss_fn(*out, labels1, labels2)\n\n\nclass GradWrapWithLoss(Cell):\n    \"\"\"\n    Construct a network to compute the gradient of loss function in \\\n    input space and weighted by 'weight'.\n    \"\"\"\n\n    def __init__(self, network):\n        super(GradWrapWithLoss, self).__init__()\n        self._grad_all = GradOperation(get_all=True, sens_param=False)\n        self._network = network\n\n    def construct(self, *inputs):\n        gout = self._grad_all(self._network)(*inputs)\n        return gout[0]\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_batch_generate_attack_ascend():\n    \"\"\"\n    Feature: Attack with batch-generate for ascend\n    Description: Given a image, we want to make sure the adversarial example\n                 generated is different from the image\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    input_np = np.random.random((128, 10)).astype(np.float32)\n    label = np.random.randint(0, 10, 128).astype(np.int32)\n    label = np.eye(10)[label].astype(np.float32)\n\n    attack = FastGradientMethod(Net(), loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n    ms_adv_x = attack.batch_generate(input_np, label, batch_size=32)\n\n    assert np.any(ms_adv_x != input_np), 'Fast gradient method: generate value' \\\n                                            ' must not be equal to original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_batch_generate_attack_cpu():\n    \"\"\"\n    Feature: Attack with batch-generate for cpu\n    Description: Given a image, we want to make sure the adversarial example\n                 generated is different from the image\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    input_np = np.random.random((128, 10)).astype(np.float32)\n    label = np.random.randint(0, 10, 128).astype(np.int32)\n    label = np.eye(10)[label].astype(np.float32)\n\n    attack = FastGradientMethod(Net(), loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n    ms_adv_x = attack.batch_generate(input_np, label, batch_size=32)\n\n    assert np.any(ms_adv_x != input_np), 'Fast gradient method: generate value' \\\n                                            ' must not be equal to original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_batch_generate_attack_multi_inputs_ascend():\n    \"\"\"\n    Feature: Attack with batch-generate by multi-inputs for ascend\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: inputs != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    inputs1 = np.random.random((128, 10)).astype(np.float32)\n    inputs2 = np.random.random((128, 10)).astype(np.float32)\n    labels1 = np.random.randint(0, 10, 128).astype(np.int32)\n    labels2 = np.random.randint(0, 10, 128).astype(np.int32)\n    labels1 = np.eye(10)[labels1].astype(np.float32)\n    labels2 = np.eye(10)[labels2].astype(np.float32)\n\n    with_loss_cell = WithLossCell(Net2(), LossNet())\n    grad_with_loss_net = GradWrapWithLoss(with_loss_cell)\n    attack = FastGradientMethod(grad_with_loss_net)\n    ms_adv_x = attack.batch_generate((inputs1, inputs2), (labels1, labels2), batch_size=32)\n\n    assert np.any(ms_adv_x != inputs1), 'Fast gradient method: generate value' \\\n                                         ' must not be equal to original value.'\n    del inputs1, inputs2, labels1, labels2, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_batch_generate_attack_multi_inputs_cpu():\n    \"\"\"\n    Feature: Attack with batch-generate by multi-inputs for cpu\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: inputs != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    inputs1 = np.random.random((128, 10)).astype(np.float32)\n    inputs2 = np.random.random((128, 10)).astype(np.float32)\n    labels1 = np.random.randint(0, 10, 128).astype(np.int32)\n    labels2 = np.random.randint(0, 10, 128).astype(np.int32)\n    labels1 = np.eye(10)[labels1].astype(np.float32)\n    labels2 = np.eye(10)[labels2].astype(np.float32)\n\n    with_loss_cell = WithLossCell(Net2(), LossNet())\n    grad_with_loss_net = GradWrapWithLoss(with_loss_cell)\n    attack = FastGradientMethod(grad_with_loss_net)\n    ms_adv_x = attack.batch_generate((inputs1, inputs2), (labels1, labels2), batch_size=32)\n\n    assert np.any(ms_adv_x != inputs1), 'Fast gradient method: generate value' \\\n                                         ' must not be equal to original value.'\n    del inputs1, inputs2, labels1, labels2, ms_adv_x\n    gc.collect()\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/attacks/test_cw.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nCW-Attack test.\n\"\"\"\nimport gc\nimport numpy as np\nimport pytest\n\nimport mindspore.ops.operations as M\nfrom mindspore.nn import Cell\nfrom mindspore import context\n\nfrom mindarmour.adv_robustness.attacks import CarliniWagnerL2Attack\n\n\n\n# for user\nclass Net(Cell):\n    \"\"\"\n    Construct the network of target model.\n\n    Examples:\n        >>> net = Net()\n    \"\"\"\n\n    def __init__(self):\n        \"\"\"\n        Introduce the layers used for network construction.\n        \"\"\"\n        super(Net, self).__init__()\n        self._softmax = M.Softmax()\n\n    def construct(self, inputs):\n        \"\"\"\n        Construct network.\n\n        Args:\n            inputs (Tensor): Input data.\n        \"\"\"\n        out = self._softmax(inputs)\n        return out\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_cw_attack_ascend():\n    \"\"\"\n    Feature: CW-Attack test for ascend\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    net = Net()\n    input_np = np.array([[0.1, 0.2, 0.7, 0.5, 0.4]]).astype(np.float32)\n    label_np = np.array([3]).astype(np.int64)\n    num_classes = input_np.shape[1]\n    attack = CarliniWagnerL2Attack(net, num_classes, targeted=False)\n    adv_data = attack.generate(input_np, label_np)\n    assert np.any(input_np != adv_data)\n    del input_np, label_np, adv_data\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_cw_attack_cpu():\n    \"\"\"\n    Feature: CW-Attack test for cpu\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    net = Net()\n    input_np = np.array([[0.1, 0.2, 0.7, 0.5, 0.4]]).astype(np.float32)\n    label_np = np.array([3]).astype(np.int64)\n    num_classes = input_np.shape[1]\n    attack = CarliniWagnerL2Attack(net, num_classes, targeted=False)\n    adv_data = attack.generate(input_np, label_np)\n    assert np.any(input_np != adv_data)\n    del input_np, label_np, adv_data\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_cw_attack_targeted_ascend():\n    \"\"\"\n    Feature: CW-Attack-Targeted test for ascend\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    net = Net()\n    input_np = np.array([[0.1, 0.2, 0.7, 0.5, 0.4]]).astype(np.float32)\n    target_np = np.array([1]).astype(np.int64)\n    num_classes = input_np.shape[1]\n    attack = CarliniWagnerL2Attack(net, num_classes, targeted=True)\n    adv_data = attack.generate(input_np, target_np)\n    assert np.any(input_np != adv_data)\n    del input_np, target_np, adv_data\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_cw_attack_targeted_cpu():\n    \"\"\"\n    Feature: CW-Attack-Targeted test for cpu\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    net = Net()\n    input_np = np.array([[0.1, 0.2, 0.7, 0.5, 0.4]]).astype(np.float32)\n    target_np = np.array([1]).astype(np.int64)\n    num_classes = input_np.shape[1]\n    attack = CarliniWagnerL2Attack(net, num_classes, targeted=True)\n    adv_data = attack.generate(input_np, target_np)\n    assert np.any(input_np != adv_data)\n    del input_np, target_np, adv_data\n    gc.collect()\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/attacks/test_deep_fool.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nDeepFool-Attack test.\n\"\"\"\nimport gc\nimport numpy as np\nimport pytest\n\nimport mindspore.ops.operations as P\nfrom mindspore.nn import Cell\nfrom mindspore import context\nfrom mindspore import Tensor\n\nfrom mindarmour.adv_robustness.attacks import DeepFool\n\n\n# for user\nclass Net(Cell):\n    \"\"\"\n    Construct the network of target model.\n\n    Examples:\n        >>> net = Net()\n    \"\"\"\n\n    def __init__(self):\n        \"\"\"\n        Introduce the layers used for network construction.\n        \"\"\"\n        super(Net, self).__init__()\n        self._softmax = P.Softmax()\n\n    def construct(self, inputs):\n        \"\"\"\n        Construct network.\n\n        Args:\n            inputs (Tensor): Input data.\n        \"\"\"\n        out = self._softmax(inputs)\n        return out\n\n\nclass Net2(Cell):\n    \"\"\"\n    Construct the network of target model, specifically for detection model test case.\n\n    Examples:\n        >>> net = Net2()\n    \"\"\"\n    def __init__(self):\n        super(Net2, self).__init__()\n        self._softmax = P.Softmax()\n\n    def construct(self, inputs1, inputs2):\n        out1 = self._softmax(inputs1)\n        out2 = self._softmax(inputs2)\n        return out2, out1\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_deepfool_attack_ascend():\n    \"\"\"\n    Feature: Deepfool-Attack test for ascend\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    net = Net()\n    input_shape = (1, 5)\n    _, classes = input_shape\n    input_np = np.array([[0.1, 0.2, 0.7, 0.5, 0.4]]).astype(np.float32)\n    input_me = Tensor(input_np)\n    true_labels = np.argmax(net(input_me).asnumpy(), axis=1)\n    attack = DeepFool(net, classes, max_iters=10, norm_level=2,\n                      bounds=(0.0, 1.0))\n    adv_data = attack.generate(input_np, true_labels)\n    # expected adv value\n    expect_value = np.asarray([[0.10300991, 0.20332647, 0.59308802, 0.59651263,\n                                0.40406296]])\n    assert np.allclose(adv_data, expect_value), 'mindspore deepfool_method' \\\n        ' implementation error, ms_adv_x != expect_value'\n\n    del input_np, true_labels, adv_data, expect_value\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_deepfool_attack_cpu():\n    \"\"\"\n   Feature: Deepfool-Attack test for cpu\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    net = Net()\n    input_shape = (1, 5)\n    _, classes = input_shape\n    input_np = np.array([[0.1, 0.2, 0.7, 0.5, 0.4]]).astype(np.float32)\n    input_me = Tensor(input_np)\n    true_labels = np.argmax(net(input_me).asnumpy(), axis=1)\n    attack = DeepFool(net, classes, max_iters=10, norm_level=2,\n                      bounds=(0.0, 1.0))\n    adv_data = attack.generate(input_np, true_labels)\n    # expected adv value\n    expect_value = np.asarray([[0.10300991, 0.20332647, 0.59308802, 0.59651263,\n                                0.40406296]])\n    assert np.allclose(adv_data, expect_value), 'mindspore deepfool_method' \\\n        ' implementation error, ms_adv_x != expect_value'\n    del input_np, true_labels, adv_data, expect_value\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_deepfool_attack_detection_ascend():\n    \"\"\"\n    Feature: Deepfool-Attack-Detection test for ascend\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    net = Net2()\n    inputs1_np = np.random.random((2, 10, 10)).astype(np.float32)\n    inputs2_np = np.random.random((2, 10, 5)).astype(np.float32)\n    gt_boxes, gt_logits = net(Tensor(inputs1_np), Tensor(inputs2_np))\n    gt_boxes, gt_logits = gt_boxes.asnumpy(), gt_logits.asnumpy()\n    gt_labels = np.argmax(gt_logits, axis=2)\n    num_classes = 10\n\n    attack = DeepFool(net, num_classes, model_type='detection', reserve_ratio=0.3,\n                      bounds=(0.0, 1.0))\n    adv_data = attack.generate((inputs1_np, inputs2_np), (gt_boxes, gt_labels))\n    assert np.any(adv_data != inputs1_np)\n    del inputs1_np, inputs2_np, gt_labels, adv_data\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_deepfool_attack_detection_cpu():\n    \"\"\"\n    Feature: Deepfool-Attack-Detection test for cpu\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    net = Net2()\n    inputs1_np = np.random.random((2, 10, 10)).astype(np.float32)\n    inputs2_np = np.random.random((2, 10, 5)).astype(np.float32)\n    gt_boxes, gt_logits = net(Tensor(inputs1_np), Tensor(inputs2_np))\n    gt_boxes, gt_logits = gt_boxes.asnumpy(), gt_logits.asnumpy()\n    gt_labels = np.argmax(gt_logits, axis=2)\n    num_classes = 10\n\n    attack = DeepFool(net, num_classes, model_type='detection', reserve_ratio=0.3,\n                      bounds=(0.0, 1.0))\n    adv_data = attack.generate((inputs1_np, inputs2_np), (gt_boxes, gt_labels))\n    assert np.any(adv_data != inputs1_np)\n    del inputs1_np, inputs2_np, gt_labels, adv_data\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_deepfool_attack_inf_ascend():\n    \"\"\"\n    Feature: Deepfool-Attack with inf-norm test for ascend\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    net = Net()\n    input_shape = (1, 5)\n    _, classes = input_shape\n    input_np = np.array([[0.1, 0.2, 0.7, 0.5, 0.4]]).astype(np.float32)\n    input_me = Tensor(input_np)\n    true_labels = np.argmax(net(input_me).asnumpy(), axis=1)\n    attack = DeepFool(net, classes, max_iters=10, norm_level=np.inf,\n                      bounds=(0.0, 1.0))\n    adv_data = attack.generate(input_np, true_labels)\n    assert np.any(input_np != adv_data)\n    del input_np, true_labels, adv_data\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_deepfool_attack_inf_cpu():\n    \"\"\"\n    Feature: Deepfool-Attack with inf-norm test for cpu\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    net = Net()\n    input_shape = (1, 5)\n    _, classes = input_shape\n    input_np = np.array([[0.1, 0.2, 0.7, 0.5, 0.4]]).astype(np.float32)\n    input_me = Tensor(input_np)\n    true_labels = np.argmax(net(input_me).asnumpy(), axis=1)\n    attack = DeepFool(net, classes, max_iters=10, norm_level=np.inf,\n                      bounds=(0.0, 1.0))\n    adv_data = attack.generate(input_np, true_labels)\n    assert np.any(input_np != adv_data)\n    del input_np, true_labels, adv_data\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_value_error_ascend():\n    \"\"\"\n    Feature: value error test for ascend\n    Description: value error for deep fool\n    Expectation: attack.generate works\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    net = Net()\n    input_shape = (1, 5)\n    _, classes = input_shape\n    input_np = np.array([[0.1, 0.2, 0.7, 0.5, 0.4]]).astype(np.float32)\n    input_me = Tensor(input_np)\n    true_labels = np.argmax(net(input_me).asnumpy(), axis=1)\n    with pytest.raises(NotImplementedError):\n        # norm_level=0 is not available\n        attack = DeepFool(net, classes, max_iters=10, norm_level=1,\n                          bounds=(0.0, 1.0))\n        assert attack.generate(input_np, true_labels)\n    del input_np, true_labels\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_value_error_cpu():\n    \"\"\"\n    Feature: value error test for cpu\n    Description: value error for deep fool\n    Expectation: attack.generate works\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    net = Net()\n    input_shape = (1, 5)\n    _, classes = input_shape\n    input_np = np.array([[0.1, 0.2, 0.7, 0.5, 0.4]]).astype(np.float32)\n    input_me = Tensor(input_np)\n    true_labels = np.argmax(net(input_me).asnumpy(), axis=1)\n    with pytest.raises(NotImplementedError):\n        # norm_level=0 is not available\n        attack = DeepFool(net, classes, max_iters=10, norm_level=1,\n                          bounds=(0.0, 1.0))\n        assert attack.generate(input_np, true_labels)\n    del input_np, true_labels\n    gc.collect()\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/attacks/test_gradient_method.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nGradient-Attack test.\n\"\"\"\nimport gc\nimport numpy as np\nimport pytest\n\nimport mindspore.nn as nn\nfrom mindspore.nn import Cell, SoftmaxCrossEntropyWithLogits\nimport mindspore.context as context\nfrom mindspore.ops.composite import GradOperation\n\nfrom mindarmour.adv_robustness.attacks import FastGradientMethod\nfrom mindarmour.adv_robustness.attacks import FastGradientSignMethod\nfrom mindarmour.adv_robustness.attacks import LeastLikelyClassMethod\nfrom mindarmour.adv_robustness.attacks import RandomFastGradientMethod\nfrom mindarmour.adv_robustness.attacks import RandomFastGradientSignMethod\nfrom mindarmour.adv_robustness.attacks import RandomLeastLikelyClassMethod\n\n\n# for user\nclass Net(Cell):\n    \"\"\"\n    Construct the network of target model.\n\n    Examples:\n        >>> net = Net()\n    \"\"\"\n\n    def __init__(self):\n        \"\"\"\n        Introduce the layers used for network construction.\n        \"\"\"\n        super(Net, self).__init__()\n        self._relu = nn.ReLU()\n\n    def construct(self, inputs):\n        \"\"\"\n        Construct network.\n\n        Args:\n            inputs (Tensor): Input data.\n        \"\"\"\n        out = self._relu(inputs)\n        return out\n\n\nclass Net2(Cell):\n    \"\"\"\n    Construct the network of target model. A network with multiple input data.\n\n    Examples:\n        >>> net = Net2()\n    \"\"\"\n\n    def __init__(self):\n        super(Net2, self).__init__()\n        self._relu = nn.ReLU()\n\n    def construct(self, inputs1, inputs2):\n        out1 = self._relu(inputs1)\n        out2 = self._relu(inputs2)\n        return out1 + out2, out1 - out2\n\n\nclass LossNet(Cell):\n    \"\"\"\n    Loss function for test.\n    \"\"\"\n    def construct(self, loss1, loss2, labels1, labels2):\n        return loss1 + loss2 - labels1 - labels2\n\n\nclass WithLossCell(Cell):\n    \"\"\"Wrap the network with loss function\"\"\"\n    def __init__(self, backbone, loss_fn):\n        super(WithLossCell, self).__init__(auto_prefix=False)\n        self._backbone = backbone\n        self._loss_fn = loss_fn\n\n    def construct(self, inputs1, inputs2, labels1, labels2):\n        out = self._backbone(inputs1, inputs2)\n        return self._loss_fn(*out, labels1, labels2)\n\n\nclass GradWrapWithLoss(Cell):\n    \"\"\"\n    Construct a network to compute the gradient of loss function in \\\n    input space and weighted by 'weight'.\n    \"\"\"\n\n    def __init__(self, network):\n        super(GradWrapWithLoss, self).__init__()\n        self._grad_all = GradOperation(get_all=True, sens_param=False)\n        self._network = network\n\n    def construct(self, *inputs):\n        gout = self._grad_all(self._network)(*inputs)\n        return gout[0]\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_fast_gradient_method():\n    \"\"\"\n    Fast gradient method unit test.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n    label = np.asarray([2], np.int32)\n    label = np.eye(3)[label].astype(np.float32)\n\n    attack = FastGradientMethod(Net(), loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n    ms_adv_x = attack.generate(input_np, label)\n\n    assert np.any(ms_adv_x != input_np), 'Fast gradient method: generate value' \\\n                                         ' must not be equal to original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_gpu_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_fast_gradient_method_gpu():\n    \"\"\"\n    Fast gradient method unit test.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"GPU\")\n    input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n    label = np.asarray([2], np.int32)\n    label = np.eye(3)[label].astype(np.float32)\n\n    attack = FastGradientMethod(Net(), loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n    ms_adv_x = attack.generate(input_np, label)\n\n    assert np.any(ms_adv_x != input_np), 'Fast gradient method: generate value' \\\n                                         ' must not be equal to original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_fast_gradient_method_cpu():\n    \"\"\"\n    Fast gradient method unit test.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n    label = np.asarray([2], np.int32)\n\n    loss = SoftmaxCrossEntropyWithLogits(sparse=True)\n    attack = FastGradientMethod(Net(), loss_fn=loss)\n    ms_adv_x = attack.generate(input_np, label)\n\n    assert np.any(ms_adv_x != input_np), 'Fast gradient method: generate value' \\\n                                         ' must not be equal to original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_random_fast_gradient_method():\n    \"\"\"\n    Random fast gradient method unit test.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n    label = np.asarray([2], np.int32)\n    label = np.eye(3)[label].astype(np.float32)\n\n    attack = RandomFastGradientMethod(Net(), loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n    ms_adv_x = attack.generate(input_np, label)\n\n    assert np.any(ms_adv_x != input_np), 'Random fast gradient method: ' \\\n                                         'generate value must not be equal to' \\\n                                         ' original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_fast_gradient_sign_method():\n    \"\"\"\n    Fast gradient sign method unit test.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n    label = np.asarray([2], np.int32)\n    label = np.eye(3)[label].astype(np.float32)\n\n    attack = FastGradientSignMethod(Net(), loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n    ms_adv_x = attack.generate(input_np, label)\n\n    assert np.any(ms_adv_x != input_np), 'Fast gradient sign method: generate' \\\n                                         ' value must not be equal to' \\\n                                        ' original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_random_fast_gradient_sign_method():\n    \"\"\"\n    Random fast gradient sign method unit test.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    input_np = np.random.random((1, 28)).astype(np.float32)\n    label = np.asarray([2], np.int32)\n    label = np.eye(28)[label].astype(np.float32)\n\n    attack = RandomFastGradientSignMethod(Net(), loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n    ms_adv_x = attack.generate(input_np, label)\n\n    assert np.any(ms_adv_x != input_np), 'Random fast gradient sign method: ' \\\n                                         'generate value must not be equal to' \\\n                                         ' original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_least_likely_class_method():\n    \"\"\"\n    Least likely class method unit test.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n    label = np.asarray([2], np.int32)\n    label = np.eye(3)[label].astype(np.float32)\n\n    attack = LeastLikelyClassMethod(Net(), loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n    ms_adv_x = attack.generate(input_np, label)\n\n    assert np.any(ms_adv_x != input_np), 'Least likely class method: generate' \\\n                                         ' value must not be equal to' \\\n                                         ' original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_random_least_likely_class_method():\n    \"\"\"\n    Random least likely class method unit test.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n    label = np.asarray([2], np.int32)\n    label = np.eye(3)[label].astype(np.float32)\n\n    attack = RandomLeastLikelyClassMethod(Net(), eps=0.1, alpha=0.01, \\\n        loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n    ms_adv_x = attack.generate(input_np, label)\n\n    assert np.any(ms_adv_x != input_np), 'Random least likely class method: ' \\\n                                         'generate value must not be equal to' \\\n                                         ' original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_fast_gradient_method_multi_inputs():\n    \"\"\"\n    Fast gradient method unit test.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    inputs1 = np.asarray([[0.1, 0.2, 0.7]]).astype(np.float32)\n    inputs2 = np.asarray([[0.4, 0.8, 0.5]]).astype(np.float32)\n    labels1 = np.expand_dims(np.eye(3)[1].astype(np.float32), axis=0)\n    labels2 = np.expand_dims(np.eye(3)[2].astype(np.float32), axis=0)\n\n    with_loss_cell = WithLossCell(Net2(), LossNet())\n    grad_with_loss_net = GradWrapWithLoss(with_loss_cell)\n    attack = FastGradientMethod(grad_with_loss_net)\n    ms_adv_x = attack.generate((inputs1, inputs2), (labels1, labels2))\n\n    assert np.any(ms_adv_x != inputs1), 'Fast gradient method: generate value' \\\n                                         ' must not be equal to original value.'\n    del inputs1, inputs2, labels1, labels2, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_assert_error():\n    \"\"\"\n    Random least likely class method unit test.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    with pytest.raises(ValueError) as e:\n        assert RandomLeastLikelyClassMethod(Net(), eps=0.05, alpha=0.21, \\\n            loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n    assert str(e.value) == 'eps must be larger than alpha!'\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/attacks/test_iterative_gradient_method.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nIterative-gradient Attack test.\n\"\"\"\nimport gc\nimport numpy as np\nimport pytest\n\nfrom mindspore.ops import operations as P\nfrom mindspore.nn import Cell\nfrom mindspore import context\nfrom mindspore.nn import SoftmaxCrossEntropyWithLogits\n\nfrom mindarmour.adv_robustness.attacks import BasicIterativeMethod\nfrom mindarmour.adv_robustness.attacks import MomentumIterativeMethod\nfrom mindarmour.adv_robustness.attacks import ProjectedGradientDescent\nfrom mindarmour.adv_robustness.attacks import IterativeGradientMethod\nfrom mindarmour.adv_robustness.attacks import DiverseInputIterativeMethod\nfrom mindarmour.adv_robustness.attacks import MomentumDiverseInputIterativeMethod\nfrom mindarmour.adv_robustness.attacks import VarianceTuningMomentumIterativeMethod\n\n\n# for user\nclass Net(Cell):\n    \"\"\"\n    Construct the network of target model.\n\n    Examples:\n        >>> net = Net()\n    \"\"\"\n\n    def __init__(self):\n        super(Net, self).__init__()\n        self._softmax = P.Softmax()\n\n    def construct(self, inputs):\n        \"\"\"\n        Construct network.\n\n        Args:\n            inputs (Tensor): Input data.\n        \"\"\"\n        out = self._softmax(inputs)\n        return out\n\n\nclass FlattenNet(Cell):\n    \"\"\"\n    Construct the network of target model.\n\n    Examples:\n        >>> net = FlattenNet()\n    \"\"\"\n\n    def __init__(self):\n        super(FlattenNet, self).__init__()\n        self._flatten = P.Flatten()\n        self._softmax = P.Softmax()\n\n    def construct(self, inputs):\n        \"\"\"\n        Construct flatten network.\n\n        Args:\n            inputs (Tensor): Input data.\n        \"\"\"\n        out = self._flatten(inputs)\n        out = self._softmax(out)\n        return out\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_basic_iterative_method_ascend():\n    \"\"\"\n    Feature: Basic iterative method unit test for ascend.\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n    label = np.asarray([2], np.int32)\n    label = np.eye(3)[label].astype(np.float32)\n\n    for i in range(5):\n        net = Net()\n        attack = BasicIterativeMethod(net, nb_iter=i + 1, loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n        ms_adv_x = attack.generate(input_np, label)\n        assert np.any(\n            ms_adv_x != input_np), 'Basic iterative method: generate value' \\\n                                   ' must not be equal to original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_basic_iterative_method_cpu():\n    \"\"\"\n    Feature: Basic iterative method unit test for cpu.\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n    label = np.asarray([2], np.int32)\n    label = np.eye(3)[label].astype(np.float32)\n\n    for i in range(5):\n        net = Net()\n        attack = BasicIterativeMethod(net, nb_iter=i + 1, loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n        ms_adv_x = attack.generate(input_np, label)\n        assert np.any(\n            ms_adv_x != input_np), 'Basic iterative method: generate value' \\\n                                   ' must not be equal to original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_momentum_iterative_method_ascend():\n    \"\"\"\n    Feature: Momentum iterative method unit test for ascend\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n    label = np.asarray([2], np.int32)\n    label = np.eye(3)[label].astype(np.float32)\n\n    for i in range(5):\n        attack = MomentumIterativeMethod(Net(), nb_iter=i + 1, loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n        ms_adv_x = attack.generate(input_np, label)\n        assert np.any(ms_adv_x != input_np), 'Momentum iterative method: generate' \\\n                                             ' value must not be equal to' \\\n                                             ' original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_momentum_iterative_method_cpu():\n    \"\"\"\n    Feature: Momentum iterative method unit test for cpu\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n    label = np.asarray([2], np.int32)\n    label = np.eye(3)[label].astype(np.float32)\n\n    for i in range(5):\n        attack = MomentumIterativeMethod(Net(), nb_iter=i + 1, loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n        ms_adv_x = attack.generate(input_np, label)\n        assert np.any(ms_adv_x != input_np), 'Momentum iterative method: generate' \\\n                                             ' value must not be equal to' \\\n                                             ' original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_projected_gradient_descent_method_ascend():\n    \"\"\"\n    Feature: Projected gradient descent method unit test for ascend\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n    label = np.asarray([2], np.int32)\n    label = np.eye(3)[label].astype(np.float32)\n\n    for i in range(5):\n        attack = ProjectedGradientDescent(Net(), nb_iter=i + 1, loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n        ms_adv_x = attack.generate(input_np, label)\n\n        assert np.any(\n            ms_adv_x != input_np), 'Projected gradient descent method: ' \\\n                                   'generate value must not be equal to' \\\n                                   ' original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_projected_gradient_descent_method_cpu():\n    \"\"\"\n    Feature: Projected gradient descent method unit test for cpu\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n    label = np.asarray([2], np.int32)\n    label = np.eye(3)[label].astype(np.float32)\n\n    for i in range(5):\n        attack = ProjectedGradientDescent(Net(), nb_iter=i + 1, loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n        ms_adv_x = attack.generate(input_np, label)\n\n        assert np.any(\n            ms_adv_x != input_np), 'Projected gradient descent method: ' \\\n                                   'generate value must not be equal to' \\\n                                   ' original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_diverse_input_iterative_method_ascend():\n    \"\"\"\n    Feature: Diverse input iterative method unit test for ascend\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n    label = np.asarray([2], np.int32)\n    label = np.eye(3)[label].astype(np.float32)\n\n    attack = DiverseInputIterativeMethod(Net(), loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n    ms_adv_x = attack.generate(input_np, label)\n    assert np.any(ms_adv_x != input_np), 'Diverse input iterative method: generate' \\\n                                             ' value must not be equal to' \\\n                                             ' original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_diverse_input_iterative_method_cpu():\n    \"\"\"\n    Feature: Diverse input iterative method unit test for cpu\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n    label = np.asarray([2], np.int32)\n    label = np.eye(3)[label].astype(np.float32)\n\n    attack = DiverseInputIterativeMethod(Net(), loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n    ms_adv_x = attack.generate(input_np, label)\n    assert np.any(ms_adv_x != input_np), 'Diverse input iterative method: generate' \\\n                                             ' value must not be equal to' \\\n                                             ' original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_momentum_diverse_input_iterative_method_ascend():\n    \"\"\"\n    Feature: Momentum diverse input iterative method unit test for ascend\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n    label = np.asarray([2], np.int32)\n    label = np.eye(3)[label].astype(np.float32)\n\n    attack = MomentumDiverseInputIterativeMethod(Net(), loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n    ms_adv_x = attack.generate(input_np, label)\n    assert np.any(ms_adv_x != input_np), 'Momentum diverse input iterative method: ' \\\n                                             'generate value must not be equal to' \\\n                                             ' original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_momentum_diverse_input_iterative_method_cpu():\n    \"\"\"\n    Feature: Momentum diverse input iterative method unit test for cpu\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n    label = np.asarray([2], np.int32)\n    label = np.eye(3)[label].astype(np.float32)\n\n    attack = MomentumDiverseInputIterativeMethod(Net(), loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n    ms_adv_x = attack.generate(input_np, label)\n    assert np.any(ms_adv_x != input_np), 'Momentum diverse input iterative method: ' \\\n                                             'generate value must not be equal to' \\\n                                             ' original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_error_ascend():\n    \"\"\"\n    Feature: test error for ascend\n    Description: test error\n    Expectation: error detected or attach.generate works properly\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    attack = IterativeGradientMethod(Net(), bounds=(0.0, 1.0), loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n    with pytest.raises(NotImplementedError):\n        input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n        label = np.asarray([2], np.int32)\n        label = np.eye(3)[label].astype(np.float32)\n        assert attack.generate(input_np, label)\n        del input_np, label\n        gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_error_cpu():\n    \"\"\"\n    Feature: test error for cpu\n    Description: test error\n    Expectation: error detected or attach.generate works properly\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    attack = IterativeGradientMethod(Net(), bounds=(0.0, 1.0), loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n    with pytest.raises(NotImplementedError):\n        input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n        label = np.asarray([2], np.int32)\n        label = np.eye(3)[label].astype(np.float32)\n        assert attack.generate(input_np, label)\n        del input_np, label\n        gc.collect()\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_variance_tuning_momentum_iterative_method_cpu():\n    \"\"\"\n    Feature: Variance Tuning Momentum iterative method unit test for cpu\n    Description: Given multiple images, we want to make sure the adversarial examples\n                 generated are different from the images\n    Expectation: input_np != ms_adv_x\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    input_np = np.asarray([[0.1, 0.2, 0.7]], np.float32)\n    label = np.asarray([2], np.int32)\n    label = np.eye(3)[label].astype(np.float32)\n\n    for i in range(5):\n        attack = VarianceTuningMomentumIterativeMethod(FlattenNet(), nb_iter=i + 1,\n                                                       loss_fn=SoftmaxCrossEntropyWithLogits(sparse=False))\n        ms_adv_x = attack.generate(input_np, label)\n        assert np.any(ms_adv_x != input_np), 'Variance Tuning Momentum iterative method: generate' \\\n                                             ' value must not be equal to' \\\n                                             ' original value.'\n    del input_np, label, ms_adv_x\n    gc.collect()\n    "
  },
  {
    "path": "tests/ut/python/adv_robustness/attacks/test_jsma.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nJSMA-Attack test.\n\"\"\"\nimport gc\nimport numpy as np\nimport pytest\n\nimport mindspore.nn as nn\nfrom mindspore.nn import Cell\nfrom mindspore import context\nfrom mindspore import Tensor\nfrom mindarmour.adv_robustness.attacks import JSMAAttack\n\n\n# for user\nclass Net(Cell):\n    \"\"\"\n    Construct the network of target model.\n\n    Examples:\n        >>> net = Net()\n    \"\"\"\n\n    def __init__(self):\n        \"\"\"\n        Introduce the layers used for network construction.\n        \"\"\"\n        super(Net, self).__init__()\n        self._relu = nn.ReLU()\n\n    def construct(self, inputs):\n        \"\"\"\n        Construct network.\n\n        Args:\n            inputs (Tensor): Input data.\n        \"\"\"\n        out = self._relu(inputs)\n        return out\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_jsma_attack():\n    \"\"\"\n    JSMA-Attack test\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    net = Net()\n    input_shape = (1, 5)\n    batch_size, classes = input_shape\n    np.random.seed(5)\n    input_np = np.random.random(input_shape).astype(np.float32)\n    label_np = np.random.randint(classes, size=batch_size)\n    ori_label = np.argmax(net(Tensor(input_np)).asnumpy(), axis=1)\n    for i in range(batch_size):\n        if label_np[i] == ori_label[i]:\n            if label_np[i] < classes - 1:\n                label_np[i] += 1\n            else:\n                label_np[i] -= 1\n    attack = JSMAAttack(net, classes, max_iteration=5)\n    adv_data = attack.generate(input_np, label_np)\n    assert np.any(input_np != adv_data)\n    del input_np, label_np, adv_data\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_jsma_attack_2():\n    \"\"\"\n    JSMA-Attack test\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    net = Net()\n    input_shape = (1, 5)\n    batch_size, classes = input_shape\n    np.random.seed(5)\n    input_np = np.random.random(input_shape).astype(np.float32)\n    label_np = np.random.randint(classes, size=batch_size)\n    ori_label = np.argmax(net(Tensor(input_np)).asnumpy(), axis=1)\n    for i in range(batch_size):\n        if label_np[i] == ori_label[i]:\n            if label_np[i] < classes - 1:\n                label_np[i] += 1\n            else:\n                label_np[i] -= 1\n    attack = JSMAAttack(net, classes, max_iteration=5, increase=False)\n    adv_data = attack.generate(input_np, label_np)\n    assert np.any(input_np != adv_data)\n    del input_np, label_np, adv_data\n    gc.collect()\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_gpu_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_jsma_attack_gpu():\n    \"\"\"\n    JSMA-Attack test\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"GPU\")\n    net = Net()\n    input_shape = (1, 5)\n    batch_size, classes = input_shape\n    np.random.seed(5)\n    input_np = np.random.random(input_shape).astype(np.float32)\n    label_np = np.random.randint(classes, size=batch_size)\n    ori_label = np.argmax(net(Tensor(input_np)).asnumpy(), axis=1)\n    for i in range(batch_size):\n        if label_np[i] == ori_label[i]:\n            if label_np[i] < classes - 1:\n                label_np[i] += 1\n            else:\n                label_np[i] -= 1\n    attack = JSMAAttack(net, classes, max_iteration=5)\n    adv_data = attack.generate(input_np, label_np)\n    assert np.any(input_np != adv_data)\n    del input_np, label_np, adv_data\n    gc.collect()\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_jsma_attack_cpu():\n    \"\"\"\n    JSMA-Attack test\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    net = Net()\n    input_shape = (1, 5)\n    batch_size, classes = input_shape\n    np.random.seed(5)\n    input_np = np.random.random(input_shape).astype(np.float32)\n    label_np = np.random.randint(classes, size=batch_size)\n    ori_label = np.argmax(net(Tensor(input_np)).asnumpy(), axis=1)\n    for i in range(batch_size):\n        if label_np[i] == ori_label[i]:\n            if label_np[i] < classes - 1:\n                label_np[i] += 1\n            else:\n                label_np[i] -= 1\n    attack = JSMAAttack(net, classes, max_iteration=5)\n    adv_data = attack.generate(input_np, label_np)\n    assert np.any(input_np != adv_data)\n    del input_np, label_np, adv_data\n    gc.collect()\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/attacks/test_lbfgs.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nLBFGS-Attack test.\n\"\"\"\nimport os\nimport gc\nimport numpy as np\nimport pytest\n\nfrom mindspore import context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\n\nfrom mindarmour.adv_robustness.attacks import LBFGS\nfrom mindarmour.utils.logger import LogUtil\n\nfrom tests.ut.python.utils.mock_net import Net\n\n\n\nLOGGER = LogUtil.get_instance()\nTAG = 'LBFGS_Test'\nLOGGER.set_level('DEBUG')\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_lbfgs_attack_ascend():\n    \"\"\"\n    Feature: LBFGS-Attack testfor ascend\n    Description: make sure that attack.generate works properly\n    Expectation: attack.generate works properly\n    \"\"\"\n\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    np.random.seed(123)\n    # upload trained network\n    current_dir = os.path.dirname(os.path.abspath(__file__))\n    ckpt_path = os.path.join(current_dir,\n                             '../../dataset/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt')\n    net = Net()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get one mnist image\n    input_np = np.load(os.path.join(current_dir,\n                                    '../../dataset/test_images.npy'))[:1]\n    label_np = np.load(os.path.join(current_dir,\n                                    '../../dataset/test_labels.npy'))[:1]\n    LOGGER.debug(TAG, 'true label is :{}'.format(label_np[0]))\n    classes = 10\n    target_np = np.random.randint(0, classes, 1)\n    while target_np == label_np[0]:\n        target_np = np.random.randint(0, classes)\n    target_np = np.eye(10)[target_np].astype(np.float32)\n\n    attack = LBFGS(net, is_targeted=True)\n    LOGGER.debug(TAG, 'target_np is :{}'.format(target_np[0]))\n    _ = attack.generate(input_np, target_np)\n\n    del input_np, label_np, target_np\n    gc.collect()\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_lbfgs_attack_cpu():\n    \"\"\"\n    Feature: LBFGS-Attack testfor cpu\n    Description: make sure that attack.generate works properly\n    Expectation: attack.generate works properly\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    np.random.seed(123)\n    # upload trained network\n    current_dir = os.path.dirname(os.path.abspath(__file__))\n    ckpt_path = os.path.join(current_dir,\n                             '../../dataset/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt')\n    net = Net()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n\n    # get one mnist image\n    input_np = np.load(os.path.join(current_dir,\n                                    '../../dataset/test_images.npy'))[:1]\n    label_np = np.load(os.path.join(current_dir,\n                                    '../../dataset/test_labels.npy'))[:1]\n    LOGGER.debug(TAG, 'true label is :{}'.format(label_np[0]))\n    classes = 10\n    target_np = np.random.randint(0, classes, 1)\n    while target_np == label_np[0]:\n        target_np = np.random.randint(0, classes)\n    target_np = np.eye(10)[target_np].astype(np.float32)\n\n    attack = LBFGS(net, is_targeted=True)\n    LOGGER.debug(TAG, 'target_np is :{}'.format(target_np[0]))\n    _ = attack.generate(input_np, target_np)\n    del input_np, label_np, target_np\n    gc.collect()\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/defenses/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis package includes unit tests for defense algorithms.\n\"\"\"\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/defenses/test_ad.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nAdversarial defense test.\n\"\"\"\nimport logging\n\nimport numpy as np\nimport pytest\nfrom mindspore import Tensor\nfrom mindspore import context\nfrom mindspore import nn\nfrom mindspore.nn.optim.momentum import Momentum\n\nfrom mindarmour.adv_robustness.defenses import AdversarialDefense\nfrom mindarmour.utils.logger import LogUtil\n\nfrom tests.ut.python.utils.mock_net import Net\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Ad_Test'\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_ad():\n    \"\"\"UT for adversarial defense.\"\"\"\n    num_classes = 10\n    batch_size = 32\n\n    sparse = False\n    context.set_context(mode=context.GRAPH_MODE)\n    context.set_context(device_target='Ascend')\n\n    # create test data\n    inputs = np.random.rand(batch_size, 1, 32, 32).astype(np.float32)\n    labels = np.random.randint(num_classes, size=batch_size).astype(np.int32)\n    if not sparse:\n        labels = np.eye(num_classes)[labels].astype(np.float32)\n\n    net = Net()\n    loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=sparse)\n    optimizer = Momentum(learning_rate=Tensor(np.array([0.001], np.float32)),\n                         momentum=0.9,\n                         params=net.trainable_params())\n\n    ad_defense = AdversarialDefense(net, loss_fn=loss_fn, optimizer=optimizer)\n    LOGGER.set_level(logging.DEBUG)\n    LOGGER.debug(TAG, '--start adversarial defense--')\n    loss = ad_defense.defense(inputs, labels)\n    LOGGER.debug(TAG, '--end adversarial defense--')\n    assert np.any(loss >= 0.0)\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/defenses/test_ead.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nensemble adversarial defense test.\n\"\"\"\nimport logging\n\nimport numpy as np\nimport pytest\nfrom mindspore import context\nfrom mindspore import nn\nfrom mindspore.nn.optim.momentum import Momentum\n\nfrom mindarmour.adv_robustness.attacks import FastGradientSignMethod\nfrom mindarmour.adv_robustness.attacks import \\\n    ProjectedGradientDescent\nfrom mindarmour.adv_robustness.defenses import EnsembleAdversarialDefense\nfrom mindarmour.utils.logger import LogUtil\n\nfrom tests.ut.python.utils.mock_net import Net\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Ead_Test'\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_ead():\n    \"\"\"UT for ensemble adversarial defense.\"\"\"\n    num_classes = 10\n    batch_size = 64\n\n    sparse = False\n    context.set_context(mode=context.GRAPH_MODE)\n    context.set_context(device_target='Ascend')\n\n    # create test data\n    inputs = np.random.rand(batch_size, 1, 32, 32).astype(np.float32)\n    labels = np.random.randint(num_classes, size=batch_size).astype(np.int32)\n    if not sparse:\n        labels = np.eye(num_classes)[labels].astype(np.float32)\n\n    net = Net()\n    loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=sparse)\n    optimizer = Momentum(net.trainable_params(), 0.001, 0.9)\n\n    net = Net()\n    fgsm = FastGradientSignMethod(net, loss_fn=loss_fn)\n    pgd = ProjectedGradientDescent(net, loss_fn=loss_fn)\n    ead = EnsembleAdversarialDefense(net, [fgsm, pgd], loss_fn=loss_fn,\n                                     optimizer=optimizer)\n    LOGGER.set_level(logging.DEBUG)\n    LOGGER.debug(TAG, '---start ensemble adversarial defense--')\n    loss = ead.defense(inputs, labels)\n    LOGGER.debug(TAG, '---end ensemble adversarial defense--')\n    assert np.any(loss >= 0.0)\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/defenses/test_nad.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nNatural adversarial defense test.\n\"\"\"\nimport logging\n\nimport numpy as np\nimport pytest\nfrom mindspore import context\nfrom mindspore import nn\nfrom mindspore.nn.optim.momentum import Momentum\n\nfrom mindarmour.adv_robustness.defenses import NaturalAdversarialDefense\nfrom mindarmour.utils.logger import LogUtil\n\nfrom tests.ut.python.utils.mock_net import Net\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Nad_Test'\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_nad():\n    \"\"\"UT for natural adversarial defense.\"\"\"\n    num_classes = 10\n    batch_size = 32\n\n    sparse = False\n    context.set_context(mode=context.GRAPH_MODE)\n    context.set_context(device_target='Ascend')\n\n    # create test data\n    inputs = np.random.rand(batch_size, 1, 32, 32).astype(np.float32)\n    labels = np.random.randint(num_classes, size=batch_size).astype(np.int32)\n    if not sparse:\n        labels = np.eye(num_classes)[labels].astype(np.float32)\n\n    net = Net()\n    loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=sparse)\n    optimizer = Momentum(net.trainable_params(), 0.001, 0.9)\n\n    # defense\n    nad = NaturalAdversarialDefense(net, loss_fn=loss_fn, optimizer=optimizer)\n    LOGGER.set_level(logging.DEBUG)\n    LOGGER.debug(TAG, '---start natural adversarial defense--')\n    loss = nad.defense(inputs, labels)\n    LOGGER.debug(TAG, '---end natural adversarial defense--')\n    assert np.any(loss >= 0.0)\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/defenses/test_pad.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nProjected adversarial defense test.\n\"\"\"\nimport logging\n\nimport numpy as np\nimport pytest\nfrom mindspore import context\nfrom mindspore import nn\nfrom mindspore.nn.optim.momentum import Momentum\n\nfrom mindarmour.adv_robustness.defenses import ProjectedAdversarialDefense\nfrom mindarmour.utils.logger import LogUtil\n\nfrom tests.ut.python.utils.mock_net import Net\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Pad_Test'\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_pad():\n    \"\"\"UT for projected adversarial defense.\"\"\"\n    num_classes = 10\n    batch_size = 32\n\n    sparse = False\n    context.set_context(mode=context.GRAPH_MODE)\n    context.set_context(device_target='Ascend')\n\n    # create test data\n    inputs = np.random.rand(batch_size, 1, 32, 32).astype(np.float32)\n    labels = np.random.randint(num_classes, size=batch_size).astype(np.int32)\n    if not sparse:\n        labels = np.eye(num_classes)[labels].astype(np.float32)\n\n    # construct network\n    net = Net()\n    loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=sparse)\n    optimizer = Momentum(net.trainable_params(), 0.001, 0.9)\n\n    # defense\n    pad = ProjectedAdversarialDefense(net, loss_fn=loss_fn, optimizer=optimizer)\n    LOGGER.set_level(logging.DEBUG)\n    LOGGER.debug(TAG, '---start projected adversarial defense--')\n    loss = pad.defense(inputs, labels)\n    LOGGER.debug(TAG, '---end projected adversarial defense--')\n    assert np.any(loss >= 0.0)\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/detectors/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis package includes unit tests for detection algorithms of white-box attacks.\n\"\"\"\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/detectors/black/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis package includes unit tests for detection algorithms of black-box attacks.\n\"\"\"\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/detectors/black/test_similarity_detector.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n\"\"\"\r\nSimilarity-detector test.\r\n\"\"\"\r\nimport numpy as np\r\nimport pytest\r\n\r\nfrom mindspore.nn import Cell\r\nfrom mindspore import Model\r\nfrom mindspore import context\r\nfrom mindspore.ops.operations import Add\r\n\r\nfrom mindarmour.adv_robustness.detectors import SimilarityDetector\r\n\r\n\r\nclass EncoderNet(Cell):\r\n    \"\"\"\r\n    Similarity encoder for input data\r\n    \"\"\"\r\n\r\n    def __init__(self, encode_dim):\r\n        super(EncoderNet, self).__init__()\r\n        self._encode_dim = encode_dim\r\n        self.add = Add()\r\n\r\n    def construct(self, inputs):\r\n        \"\"\"\r\n        construct the neural network\r\n        Args:\r\n            inputs (Tensor): input data to neural network.\r\n        Returns:\r\n            Tensor, output of neural network.\r\n        \"\"\"\r\n        return self.add(inputs, inputs)\r\n\r\n    def get_encode_dim(self):\r\n        \"\"\"\r\n        Get the dimension of encoded inputs\r\n\r\n        Returns:\r\n            int, dimension of encoded inputs.\r\n        \"\"\"\r\n        return self._encode_dim\r\n\r\n\r\n@pytest.mark.level0\r\n@pytest.mark.platform_arm_ascend_training\r\n@pytest.mark.platform_x86_ascend_training\r\n@pytest.mark.env_card\r\n@pytest.mark.component_mindarmour\r\ndef test_similarity_detector_ascend():\r\n    \"\"\"\r\n    Feature:  Similarity detector unit test for ascend\r\n    Description: make sure the similarity detector works as expected\r\n    Expectation: detected_res == expected_value\r\n    \"\"\"\r\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\r\n\r\n    # Prepare dataset\r\n    np.random.seed(5)\r\n    x_train = np.random.rand(1000, 32, 32, 3).astype(np.float32)\r\n    perm = np.random.permutation(x_train.shape[0])\r\n\r\n    # Generate query sequences\r\n    benign_queries = x_train[perm[:1000], :, :, :]\r\n    suspicious_queries = x_train[perm[-1], :, :, :] + np.random.normal(\r\n        0, 0.05, (1000,) + x_train.shape[1:])\r\n    suspicious_queries = suspicious_queries.astype(np.float32)\r\n\r\n    # explicit threshold not provided, calculate threshold for K\r\n    encoder = Model(EncoderNet(encode_dim=256))\r\n    detector = SimilarityDetector(max_k_neighbor=50, trans_model=encoder)\r\n    num_nearest_neighbors, thresholds = detector.fit(inputs=x_train)\r\n    detector.set_threshold(num_nearest_neighbors[-1], thresholds[-1])\r\n\r\n    detector.detect(benign_queries)\r\n    detections = detector.get_detection_interval()\r\n    # compare\r\n    expected_value = 0\r\n    assert len(detections) == expected_value\r\n\r\n    detector.clear_buffer()\r\n    detector.detect(suspicious_queries)\r\n\r\n    # compare\r\n    expected_value = [1051, 1102, 1153, 1204, 1255,\r\n                      1306, 1357, 1408, 1459, 1510,\r\n                      1561, 1612, 1663, 1714, 1765,\r\n                      1816, 1867, 1918, 1969]\r\n    assert np.all(detector.get_detected_queries() == expected_value)\r\n\r\n\r\n@pytest.mark.level0\r\n@pytest.mark.platform_x86_cpu\r\n@pytest.mark.env_card\r\n@pytest.mark.component_mindarmour\r\ndef test_similarity_detector_cpu():\r\n    \"\"\"\r\n    Feature:  Similarity detector unit test for cpu\r\n    Description: make sure the similarity detector works as expected\r\n    Expectation: detected_res == expected_value\r\n    \"\"\"\r\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\r\n\r\n    # Prepare dataset\r\n    np.random.seed(5)\r\n    x_train = np.random.rand(1000, 32, 32, 3).astype(np.float32)\r\n    perm = np.random.permutation(x_train.shape[0])\r\n\r\n    # Generate query sequences\r\n    benign_queries = x_train[perm[:1000], :, :, :]\r\n    suspicious_queries = x_train[perm[-1], :, :, :] + np.random.normal(\r\n        0, 0.05, (1000,) + x_train.shape[1:])\r\n    suspicious_queries = suspicious_queries.astype(np.float32)\r\n\r\n    # explicit threshold not provided, calculate threshold for K\r\n    encoder = Model(EncoderNet(encode_dim=256))\r\n    detector = SimilarityDetector(max_k_neighbor=50, trans_model=encoder)\r\n    num_nearest_neighbors, thresholds = detector.fit(inputs=x_train)\r\n    detector.set_threshold(num_nearest_neighbors[-1], thresholds[-1])\r\n\r\n    detector.detect(benign_queries)\r\n    detections = detector.get_detection_interval()\r\n    # compare\r\n    expected_value = 0\r\n    assert len(detections) == expected_value\r\n\r\n    detector.clear_buffer()\r\n    detector.detect(suspicious_queries)\r\n\r\n    # compare\r\n    expected_value = [1051, 1102, 1153, 1204, 1255,\r\n                      1306, 1357, 1408, 1459, 1510,\r\n                      1561, 1612, 1663, 1714, 1765,\r\n                      1816, 1867, 1918, 1969]\r\n    assert np.all(detector.get_detected_queries() == expected_value)\r\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/detectors/test_ensemble_detector.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nEnsembleDetector Test\n\"\"\"\nimport numpy as np\nimport pytest\n\nfrom mindspore.nn import Cell\nfrom mindspore.ops.operations import Add\nfrom mindspore.train.model import Model\nfrom mindspore import context\n\nfrom mindarmour.adv_robustness.detectors import ErrorBasedDetector\nfrom mindarmour.adv_robustness.detectors import RegionBasedDetector\nfrom mindarmour.adv_robustness.detectors import EnsembleDetector\n\n\n\nclass Net(Cell):\n    \"\"\"\n    Construct the network of target model.\n    \"\"\"\n    def __init__(self):\n        super(Net, self).__init__()\n        self.add = Add()\n\n    def construct(self, inputs):\n        \"\"\"\n        Construct network.\n\n        Args:\n            inputs (Tensor): Input data.\n        \"\"\"\n        return self.add(inputs, inputs)\n\n\nclass AutoNet(Cell):\n    \"\"\"\n    Construct the network of target model.\n    \"\"\"\n    def __init__(self):\n        super(AutoNet, self).__init__()\n        self.add = Add()\n\n    def construct(self, inputs):\n        \"\"\"\n        Construct network.\n\n        Args:\n            inputs (Tensor): Input data.\n        \"\"\"\n        return self.add(inputs, inputs)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_ensemble_detector_ascend():\n    \"\"\"\n    Feature:  Compute mindspore result for ascend\n    Description: make sure the ensemble detector works as expected\n    Expectation: detected_res == expected_value\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    np.random.seed(6)\n    adv = np.random.rand(4, 4).astype(np.float32)\n    model = Model(Net())\n    auto_encoder = Model(AutoNet())\n    random_label = np.random.randint(10, size=4)\n    labels = np.eye(10)[random_label]\n    magnet_detector = ErrorBasedDetector(auto_encoder)\n    region_detector = RegionBasedDetector(model)\n    # use this to enable radius in region_detector\n    region_detector.fit(adv, labels)\n    detectors = [magnet_detector, region_detector]\n    detector = EnsembleDetector(detectors)\n    detected_res = detector.detect(adv)\n    expected_value = np.array([0, 1, 0, 0])\n    assert np.all(detected_res == expected_value)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_ensemble_detector_cpu():\n    \"\"\"\n    Feature:  Compute mindspore result for ascend\n    Description: make sure the ensemble detector works as expected\n    Expectation: detected_res == expected_value\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    np.random.seed(6)\n    adv = np.random.rand(4, 4).astype(np.float32)\n    model = Model(Net())\n    auto_encoder = Model(AutoNet())\n    random_label = np.random.randint(10, size=4)\n    labels = np.eye(10)[random_label]\n    magnet_detector = ErrorBasedDetector(auto_encoder)\n    region_detector = RegionBasedDetector(model)\n    # use this to enable radius in region_detector\n    region_detector.fit(adv, labels)\n    detectors = [magnet_detector, region_detector]\n    detector = EnsembleDetector(detectors)\n    detected_res = detector.detect(adv)\n    expected_value = np.array([0, 1, 0, 0])\n    assert np.all(detected_res == expected_value)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_error_ascend():\n    \"\"\"\n    Feature: test error for ascend\n    Description: test error\n    Expectation: error detected or attach.generate works properly\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    np.random.seed(6)\n    adv = np.random.rand(4, 4).astype(np.float32)\n    model = Model(Net())\n    auto_encoder = Model(AutoNet())\n    random_label = np.random.randint(10, size=4)\n    labels = np.eye(10)[random_label]\n    magnet_detector = ErrorBasedDetector(auto_encoder)\n    region_detector = RegionBasedDetector(model)\n    # use this to enable radius in region_detector\n    detectors = [magnet_detector, region_detector]\n    detector = EnsembleDetector(detectors)\n    with pytest.raises(NotImplementedError):\n        assert detector.fit(adv, labels)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_error_cpu():\n    \"\"\"\n    Feature: test error for cpu\n    Description: test error\n    Expectation: error detected or attach.generate works properly\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    np.random.seed(6)\n    adv = np.random.rand(4, 4).astype(np.float32)\n    model = Model(Net())\n    auto_encoder = Model(AutoNet())\n    random_label = np.random.randint(10, size=4)\n    labels = np.eye(10)[random_label]\n    magnet_detector = ErrorBasedDetector(auto_encoder)\n    region_detector = RegionBasedDetector(model)\n    # use this to enable radius in region_detector\n    detectors = [magnet_detector, region_detector]\n    detector = EnsembleDetector(detectors)\n    with pytest.raises(NotImplementedError):\n        assert detector.fit(adv, labels)\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/detectors/test_mag_net.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nMag-net detector test.\n\"\"\"\nimport numpy as np\nimport pytest\n\nimport mindspore.ops.operations as P\nfrom mindspore.nn import Cell\nfrom mindspore.ops.operations import Add\nfrom mindspore import Model\nfrom mindspore import context\n\nfrom mindarmour.adv_robustness.detectors import ErrorBasedDetector\nfrom mindarmour.adv_robustness.detectors import DivergenceBasedDetector\n\n\n\nclass Net(Cell):\n    \"\"\"\n    Construct the network of target model.\n    \"\"\"\n\n    def __init__(self):\n        super(Net, self).__init__()\n        self.add = Add()\n\n    def construct(self, inputs):\n        \"\"\"\n        Construct network.\n\n        Args:\n            inputs (Tensor): Input data.\n        \"\"\"\n        return self.add(inputs, inputs)\n\n\nclass PredNet(Cell):\n    \"\"\"\n    Construct the network of target model.\n    \"\"\"\n\n    def __init__(self):\n        super(PredNet, self).__init__()\n        self.shape = P.Shape()\n        self.reshape = P.Reshape()\n        self._softmax = P.Softmax()\n\n    def construct(self, inputs):\n        \"\"\"\n        Construct network.\n\n        Args:\n            inputs (Tensor): Input data.\n        \"\"\"\n        data = self.reshape(inputs, (self.shape(inputs)[0], -1))\n        return self._softmax(data)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_mag_net_ascend():\n    \"\"\"\n    Feature:  Compute mindspore result for ascend\n    Description: make sure the error-based detector works as expected\n    Expectation: detected_res == expected_value\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    np.random.seed(5)\n    ori = np.random.rand(4, 4, 4).astype(np.float32)\n    np.random.seed(6)\n    adv = np.random.rand(4, 4, 4).astype(np.float32)\n    model = Model(Net())\n    detector = ErrorBasedDetector(model)\n    detector.fit(ori)\n    detected_res = detector.detect(adv)\n    expected_value = np.array([1, 1, 1, 1])\n    assert np.all(detected_res == expected_value)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_mag_net_cpu():\n    \"\"\"\n    Feature:  Compute mindspore result for cpu\n    Description: make sure the error-based detector works as expected\n    Expectation: detected_res == expected_value\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    np.random.seed(5)\n    ori = np.random.rand(4, 4, 4).astype(np.float32)\n    np.random.seed(6)\n    adv = np.random.rand(4, 4, 4).astype(np.float32)\n    model = Model(Net())\n    detector = ErrorBasedDetector(model)\n    detector.fit(ori)\n    detected_res = detector.detect(adv)\n    expected_value = np.array([1, 1, 1, 1])\n    assert np.all(detected_res == expected_value)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_mag_net_transform_ascend():\n    \"\"\"\n    Feature:  Compute mindspore result for ascend\n    Description: make sure the transform function works properly\n    Expectation: adv_trans != adv\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    np.random.seed(6)\n    adv = np.random.rand(4, 4, 4).astype(np.float32)\n    model = Model(Net())\n    detector = ErrorBasedDetector(model)\n    adv_trans = detector.transform(adv)\n    assert np.any(adv_trans != adv)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_mag_net_transform_cpu():\n    \"\"\"\n    Feature:  Compute mindspore result for cpu\n    Description: make sure the transform function works properly\n    Expectation: adv_trans != adv\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    np.random.seed(6)\n    adv = np.random.rand(4, 4, 4).astype(np.float32)\n    model = Model(Net())\n    detector = ErrorBasedDetector(model)\n    adv_trans = detector.transform(adv)\n    assert np.any(adv_trans != adv)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_mag_net_divergence_ascend():\n    \"\"\"\n    Feature:  Compute mindspore result for ascend\n    Description: make sure the divergence-based detector works as expected\n    Expectation: detected_res == expected_value\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    np.random.seed(5)\n    ori = np.random.rand(4, 4, 4).astype(np.float32)\n    np.random.seed(6)\n    adv = np.random.rand(4, 4, 4).astype(np.float32)\n    encoder = Model(Net())\n    model = Model(PredNet())\n    detector = DivergenceBasedDetector(encoder, model)\n    threshold = detector.fit(ori)\n    detector.set_threshold(threshold)\n    detected_res = detector.detect(adv)\n    expected_value = np.array([1, 0, 1, 1])\n    assert np.all(detected_res == expected_value)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_mag_net_divergence_cpu():\n    \"\"\"\n    Feature:  Compute mindspore result for cpu\n    Description: make sure the divergence-based detector works as expected\n    Expectation: detected_res == expected_value\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    np.random.seed(5)\n    ori = np.random.rand(4, 4, 4).astype(np.float32)\n    np.random.seed(6)\n    adv = np.random.rand(4, 4, 4).astype(np.float32)\n    encoder = Model(Net())\n    model = Model(PredNet())\n    detector = DivergenceBasedDetector(encoder, model)\n    threshold = detector.fit(ori)\n    detector.set_threshold(threshold)\n    detected_res = detector.detect(adv)\n    expected_value = np.array([1, 0, 1, 1])\n    assert np.all(detected_res == expected_value)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_mag_net_divergence_transform_ascend():\n    \"\"\"\n    Feature:  Compute mindspore result for ascend\n    Description: make sure the transform function works properly\n    Expectation: adv_trans != adv\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    np.random.seed(6)\n    adv = np.random.rand(4, 4, 4).astype(np.float32)\n    encoder = Model(Net())\n    model = Model(PredNet())\n    detector = DivergenceBasedDetector(encoder, model)\n    adv_trans = detector.transform(adv)\n    assert np.any(adv_trans != adv)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_mag_net_divergence_transform_cpu():\n    \"\"\"\n    Feature:  Compute mindspore result for cpu\n    Description: make sure the transform function works properly\n    Expectation: adv_trans != adv\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    np.random.seed(6)\n    adv = np.random.rand(4, 4, 4).astype(np.float32)\n    encoder = Model(Net())\n    model = Model(PredNet())\n    detector = DivergenceBasedDetector(encoder, model)\n    adv_trans = detector.transform(adv)\n    assert np.any(adv_trans != adv)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_value_error_ascend():\n    \"\"\"\n    Feature:  test error for ascend\n    Description: test error\n    Expectation: error detected or attach.generate works properly\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    np.random.seed(6)\n    adv = np.random.rand(4, 4, 4).astype(np.float32)\n    encoder = Model(Net())\n    model = Model(PredNet())\n    detector = DivergenceBasedDetector(encoder, model, option='bad_op')\n    with pytest.raises(NotImplementedError):\n        assert detector.detect_diff(adv)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_value_error_cpu():\n    \"\"\"\n    Feature:  test error for cpu\n    Description: test error\n    Expectation: error detected or attach.generate works properly\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    np.random.seed(6)\n    adv = np.random.rand(4, 4, 4).astype(np.float32)\n    encoder = Model(Net())\n    model = Model(PredNet())\n    detector = DivergenceBasedDetector(encoder, model, option='bad_op')\n    with pytest.raises(NotImplementedError):\n        assert detector.detect_diff(adv)\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/detectors/test_region_based_detector.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nRegion-based detector test.\n\"\"\"\nimport numpy as np\nimport pytest\n\nfrom mindspore.nn import Cell\nfrom mindspore import Model\nfrom mindspore import context\nfrom mindspore.ops.operations import Add\n\nfrom mindarmour.adv_robustness.detectors import RegionBasedDetector\n\n\n\nclass Net(Cell):\n    \"\"\"\n    Construct the network of target model.\n    \"\"\"\n    def __init__(self):\n        super(Net, self).__init__()\n        self.add = Add()\n\n    def construct(self, inputs):\n        \"\"\"\n        Construct network.\n\n        Args:\n            inputs (Tensor): Input data.\n        \"\"\"\n        return self.add(inputs, inputs)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_region_based_classification_ascend():\n    \"\"\"\n    Feature:  Compute mindspore result for ascend\n    Description: make sure the region-based detector works as expected\n    Expectation: detected_res == expected_value\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    np.random.seed(5)\n    ori = np.random.rand(4, 4).astype(np.float32)\n    labels = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 0, 1, 0],\n                       [0, 1, 0, 0]]).astype(np.int32)\n    np.random.seed(6)\n    adv = np.random.rand(4, 4).astype(np.float32)\n    model = Model(Net())\n    detector = RegionBasedDetector(model)\n    radius = detector.fit(ori, labels)\n    detector.set_radius(radius)\n    detected_res = detector.detect(adv)\n    expected_value = np.array([0, 0, 1, 0])\n    assert np.all(detected_res == expected_value)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_region_based_classification_cpu():\n    \"\"\"\n    Feature:  Compute mindspore result for cpu\n    Description: make sure the region-based detector works as expected\n    Expectation: detected_res == expected_value\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    np.random.seed(5)\n    ori = np.random.rand(4, 4).astype(np.float32)\n    labels = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 0, 1, 0],\n                       [0, 1, 0, 0]]).astype(np.int32)\n    np.random.seed(6)\n    adv = np.random.rand(4, 4).astype(np.float32)\n    model = Model(Net())\n    detector = RegionBasedDetector(model)\n    radius = detector.fit(ori, labels)\n    detector.set_radius(radius)\n    detected_res = detector.detect(adv)\n    expected_value = np.array([0, 0, 1, 0])\n    assert np.all(detected_res == expected_value)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_value_error_ascend():\n    \"\"\"\n    Feature:  test error for cpu\n    Description: test error\n    Expectation: error detected or attach.generate works properly\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    np.random.seed(5)\n    ori = np.random.rand(4, 4).astype(np.float32)\n    labels = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 0, 1, 0],\n                       [0, 1, 0, 0]]).astype(np.int32)\n    np.random.seed(6)\n    adv = np.random.rand(4, 4).astype(np.float32)\n    model = Model(Net())\n    # model should be mindspore model\n    with pytest.raises(TypeError):\n        assert RegionBasedDetector(Net())\n\n    with pytest.raises(ValueError):\n        assert RegionBasedDetector(model, number_points=-1)\n\n    with pytest.raises(ValueError):\n        assert RegionBasedDetector(model, initial_radius=-1)\n\n    with pytest.raises(ValueError):\n        assert RegionBasedDetector(model, max_radius=-2.2)\n\n    with pytest.raises(ValueError):\n        assert RegionBasedDetector(model, search_step=0)\n\n    with pytest.raises(TypeError):\n        assert RegionBasedDetector(model, sparse='False')\n\n    detector = RegionBasedDetector(model)\n    with pytest.raises(TypeError):\n        # radius must not empty\n        assert detector.detect(adv)\n\n    radius = detector.fit(ori, labels)\n    detector.set_radius(radius)\n    with pytest.raises(TypeError):\n        # adv type should be in (list, tuple, numpy.ndarray)\n        assert detector.detect(adv.tostring())\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_value_error_cpu():\n    \"\"\"\n    Feature:  test error for cpu\n    Description: test error\n    Expectation: error detected or attach.generate works properly\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    np.random.seed(5)\n    ori = np.random.rand(4, 4).astype(np.float32)\n    labels = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 0, 1, 0],\n                       [0, 1, 0, 0]]).astype(np.int32)\n    np.random.seed(6)\n    adv = np.random.rand(4, 4).astype(np.float32)\n    model = Model(Net())\n    # model should be mindspore model\n    with pytest.raises(TypeError):\n        assert RegionBasedDetector(Net())\n\n    with pytest.raises(ValueError):\n        assert RegionBasedDetector(model, number_points=-1)\n\n    with pytest.raises(ValueError):\n        assert RegionBasedDetector(model, initial_radius=-1)\n\n    with pytest.raises(ValueError):\n        assert RegionBasedDetector(model, max_radius=-2.2)\n\n    with pytest.raises(ValueError):\n        assert RegionBasedDetector(model, search_step=0)\n\n    with pytest.raises(TypeError):\n        assert RegionBasedDetector(model, sparse='False')\n\n    detector = RegionBasedDetector(model)\n    with pytest.raises(TypeError):\n        # radius must not empty\n        assert detector.detect(adv)\n\n    radius = detector.fit(ori, labels)\n    detector.set_radius(radius)\n    with pytest.raises(TypeError):\n        # adv type should be in (list, tuple, numpy.ndarray)\n        assert detector.detect(adv.tostring())\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/detectors/test_spatial_smoothing.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nSpatial-smoothing detector test.\n\"\"\"\nimport numpy as np\nimport pytest\n\nimport mindspore.ops.operations as P\nfrom mindspore import Model\nfrom mindspore.nn import Cell\nfrom mindspore import context\n\nfrom mindarmour.adv_robustness.detectors import SpatialSmoothing\n\n\n\n# for use\nclass Net(Cell):\n    \"\"\"\n    Construct the network of target model.\n    \"\"\"\n    def __init__(self):\n        super(Net, self).__init__()\n        self._softmax = P.Softmax()\n\n    def construct(self, inputs):\n        \"\"\"\n        Construct network.\n\n        Args:\n            inputs (Tensor): Input data.\n        \"\"\"\n        return self._softmax(inputs)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_spatial_smoothing_ascend():\n    \"\"\"\n    Feature:  Compute mindspore result for ascend\n    Description: make sure the spatial smoothing detector works properly\n    Expectation: detected_res == expected_value\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    input_shape = (50, 3)\n\n    np.random.seed(1)\n    input_np = np.random.randn(*input_shape).astype(np.float32)\n\n    np.random.seed(2)\n    adv_np = np.random.randn(*input_shape).astype(np.float32)\n\n    # mock user model\n    model = Model(Net())\n    detector = SpatialSmoothing(model)\n    # Training\n    threshold = detector.fit(input_np)\n    detector.set_threshold(threshold.item())\n    detected_res = np.array(detector.detect(adv_np))\n    idx = np.where(detected_res > 0)\n    expected_value = np.array([10, 39, 48])\n    assert np.all(idx == expected_value)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_spatial_smoothing_cpu():\n    \"\"\"\n    Feature:  Compute mindspore result for cpu\n    Description: make sure the spatial smoothing detector works properly\n    Expectation: detected_res == expected_value\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    input_shape = (50, 3)\n\n    np.random.seed(1)\n    input_np = np.random.randn(*input_shape).astype(np.float32)\n\n    np.random.seed(2)\n    adv_np = np.random.randn(*input_shape).astype(np.float32)\n\n    # mock user model\n    model = Model(Net())\n    detector = SpatialSmoothing(model)\n    # Training\n    threshold = detector.fit(input_np)\n    detector.set_threshold(threshold.item())\n    detected_res = np.array(detector.detect(adv_np))\n    idx = np.where(detected_res > 0)\n    expected_value = np.array([10, 39, 48])\n    assert np.all(idx == expected_value)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_spatial_smoothing_diff_ascend():\n    \"\"\"\n    Feature:  Compute mindspore result for ascend\n    Description: make sure the detect diff function works properly\n    Expectation: diffs == expected_value\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    input_shape = (50, 3)\n    np.random.seed(1)\n    input_np = np.random.randn(*input_shape).astype(np.float32)\n\n    np.random.seed(2)\n    adv_np = np.random.randn(*input_shape).astype(np.float32)\n\n    # mock user model\n    model = Model(Net())\n    detector = SpatialSmoothing(model)\n    # Training\n    detector.fit(input_np)\n    diffs = detector.detect_diff(adv_np)\n    expected_value = np.array([0.20959496, 0.69537306, 0.13034256, 0.7421039,\n                               0.41419053, 0.56346416, 0.4277994, 0.3240941,\n                               0.048190027, 0.6806958, 1.1405756, 0.587804,\n                               0.40533313, 0.2875523, 0.36801508, 0.61993587,\n                               0.49286827, 0.13222921, 0.68012404, 0.4164942,\n                               0.25758877, 0.6008735, 0.60623455, 0.34981924,\n                               0.3945489, 0.879787, 0.3934811, 0.23387678,\n                               0.63480926, 0.56435543, 0.16067612, 0.57489645,\n                               0.21772699, 0.55924356, 0.5186635, 0.7094835,\n                               0.0613693, 0.13305652, 0.11505881, 1.2404268,\n                               0.50948, 0.15797901, 0.44473758, 0.2495422,\n                               0.38254014, 0.543059, 0.06452079, 0.36902517,\n                               1.1845329, 0.3870097])\n    assert np.allclose(diffs, expected_value, 0.0001, 0.0001)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_spatial_smoothing_diff_cpu():\n    \"\"\"\n    Feature:  Compute mindspore result for cpu\n    Description: make sure the detect diff function works properly\n    Expectation: diffs == expected_value\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    input_shape = (50, 3)\n    np.random.seed(1)\n    input_np = np.random.randn(*input_shape).astype(np.float32)\n\n    np.random.seed(2)\n    adv_np = np.random.randn(*input_shape).astype(np.float32)\n\n    # mock user model\n    model = Model(Net())\n    detector = SpatialSmoothing(model)\n    # Training\n    detector.fit(input_np)\n    diffs = detector.detect_diff(adv_np)\n    expected_value = np.array([0.20959496, 0.69537306, 0.13034256, 0.7421039,\n                               0.41419053, 0.56346416, 0.4277994, 0.3240941,\n                               0.048190027, 0.6806958, 1.1405756, 0.587804,\n                               0.40533313, 0.2875523, 0.36801508, 0.61993587,\n                               0.49286827, 0.13222921, 0.68012404, 0.4164942,\n                               0.25758877, 0.6008735, 0.60623455, 0.34981924,\n                               0.3945489, 0.879787, 0.3934811, 0.23387678,\n                               0.63480926, 0.56435543, 0.16067612, 0.57489645,\n                               0.21772699, 0.55924356, 0.5186635, 0.7094835,\n                               0.0613693, 0.13305652, 0.11505881, 1.2404268,\n                               0.50948, 0.15797901, 0.44473758, 0.2495422,\n                               0.38254014, 0.543059, 0.06452079, 0.36902517,\n                               1.1845329, 0.3870097])\n    assert np.allclose(diffs, expected_value, 0.0001, 0.0001)\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/evaluations/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis package includes unit tests for the evaluations of white-box attack and defense.\n\"\"\"\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/evaluations/black/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis package includes unit tests for the evaluations of black-box attack and defense.\n\"\"\"\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/evaluations/black/test_black_defense_eval.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nBlack-box defense evaluation test.\n\"\"\"\nimport numpy as np\nimport pytest\n\nfrom mindarmour.adv_robustness.evaluations import BlackDefenseEvaluate\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_def_eval():\n    \"\"\"\n    Tests for black-box defense evaluation\n    \"\"\"\n    # prepare data\n    raw_preds = np.array([[0.1, 0.1, 0.2, 0.6], [0.1, 0.7, 0.0, 0.2],\n                          [0.8, 0.1, 0.0, 0.1], [0.1, 0.1, 0.2, 0.6],\n                          [0.1, 0.7, 0.0, 0.2], [0.8, 0.1, 0.0, 0.1],\n                          [0.1, 0.1, 0.2, 0.6], [0.1, 0.7, 0.0, 0.2],\n                          [0.8, 0.1, 0.0, 0.1], [0.1, 0.1, 0.2, 0.6]])\n\n    def_preds = np.array([[0.1, 0.1, 0.2, 0.6], [0.1, 0.7, 0.0, 0.2],\n                          [0.8, 0.1, 0.0, 0.1], [0.1, 0.1, 0.2, 0.6],\n                          [0.1, 0.7, 0.0, 0.2], [0.8, 0.1, 0.0, 0.1],\n                          [0.1, 0.1, 0.2, 0.6], [0.1, 0.7, 0.0, 0.2],\n                          [0.8, 0.1, 0.0, 0.1], [0.1, 0.1, 0.2, 0.6]])\n    raw_query_counts = np.array([0, 0, 0, 0, 0, 10, 10, 20, 20, 30])\n    def_query_counts = np.array([0, 0, 0, 0, 0, 30, 30, 40, 40, 50])\n\n    raw_query_time = np.array([0.1, 0.1, 0.1, 0.1, 0.1, 2, 2, 4, 4, 6])\n    def_query_time = np.array([0.3, 0.3, 0.3, 0.3, 0.3, 4, 4, 8, 8, 12])\n\n    def_detection_counts = np.array([1, 0, 0, 0, 1, 5, 5, 5, 10, 20])\n\n    true_labels = np.array([3, 1, 0, 3, 1, 0, 3, 1, 0, 3])\n\n    # create obj\n    def_eval = BlackDefenseEvaluate(raw_preds,\n                                    def_preds,\n                                    raw_query_counts,\n                                    def_query_counts,\n                                    raw_query_time,\n                                    def_query_time,\n                                    def_detection_counts,\n                                    true_labels,\n                                    max_queries=100)\n    # run eval\n    qcv = def_eval.qcv()\n    asv = def_eval.asv()\n    fpr = def_eval.fpr()\n    qrv = def_eval.qrv()\n    res = [qcv, asv, fpr, qrv]\n\n    # compare\n    expected_value = [0.2, 0.0, 0.4, 2.0]\n    assert np.allclose(res, expected_value, 0.0001, 0.0001)\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/evaluations/test_attack_eval.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n\"\"\"\r\nAttack evaluation test.\r\n\"\"\"\r\nimport numpy as np\r\nimport pytest\r\n\r\nfrom mindarmour.adv_robustness.evaluations import AttackEvaluate\r\n\r\n\r\n@pytest.mark.level0\r\n@pytest.mark.platform_arm_ascend_training\r\n@pytest.mark.platform_x86_ascend_training\r\n@pytest.mark.env_card\r\n@pytest.mark.component_mindarmour\r\ndef test_attack_eval():\r\n    # prepare test data\r\n    np.random.seed(1024)\r\n    inputs = np.random.normal(size=(3, 512, 512, 3))\r\n    labels = np.array([[0.1, 0.1, 0.2, 0.6],\r\n                       [0.1, 0.7, 0.0, 0.2],\r\n                       [0.8, 0.1, 0.0, 0.1]])\r\n    adv_x = inputs + np.ones((3, 512, 512, 3))*0.001\r\n    adv_y = np.array([[0.1, 0.1, 0.2, 0.6],\r\n                      [0.1, 0.0, 0.8, 0.1],\r\n                      [0.0, 0.9, 0.1, 0.0]])\r\n\r\n    # create obj\r\n    attack_eval = AttackEvaluate(inputs, labels, adv_x, adv_y)\r\n\r\n    # run eval\r\n    mr = attack_eval.mis_classification_rate()\r\n    acac = attack_eval.avg_conf_adv_class()\r\n    l_0, l_2, l_inf = attack_eval.avg_lp_distance()\r\n    ass = attack_eval.avg_ssim()\r\n    nte = attack_eval.nte()\r\n    res = [mr, acac, l_0, l_2, l_inf, ass, nte]\r\n\r\n    # compare\r\n    expected_value = [0.6666, 0.8500, 1.0, 0.0009, 0.0001, 0.9999, 0.75]\r\n    assert np.allclose(res, expected_value, 0.0001, 0.0001)\r\n\r\n\r\n@pytest.mark.level0\r\n@pytest.mark.platform_arm_ascend_training\r\n@pytest.mark.platform_x86_ascend_training\r\n@pytest.mark.env_card\r\n@pytest.mark.component_mindarmour\r\ndef test_value_error():\r\n    # prepare test data\r\n    np.random.seed(1024)\r\n    inputs = np.random.normal(size=(3, 512, 512, 3))\r\n    labels = np.array([[0.1, 0.1, 0.2, 0.6],\r\n                       [0.1, 0.7, 0.0, 0.2],\r\n                       [0.8, 0.1, 0.0, 0.1]])\r\n    adv_x = inputs + np.ones((3, 512, 512, 3))*0.001\r\n    adv_y = np.array([[0.1, 0.1, 0.2, 0.6],\r\n                      [0.1, 0.0, 0.8, 0.1],\r\n                      [0.0, 0.9, 0.1, 0.0]])\r\n\r\n    # create obj\r\n    with pytest.raises(ValueError) as e:\r\n        assert AttackEvaluate(inputs, labels, adv_x, adv_y, targeted=True)\r\n    assert str(e.value) == 'targeted attack need target_label, but got None.'\r\n\r\n\r\n@pytest.mark.level0\r\n@pytest.mark.platform_arm_ascend_training\r\n@pytest.mark.platform_x86_ascend_training\r\n@pytest.mark.env_card\r\n@pytest.mark.component_mindarmour\r\ndef test_empty_input_error():\r\n    # prepare test data\r\n    np.random.seed(1024)\r\n    inputs = np.array([])\r\n    labels = np.array([])\r\n    adv_x = inputs\r\n    adv_y = np.array([])\r\n\r\n    # create obj\r\n    with pytest.raises(ValueError) as e:\r\n        assert AttackEvaluate(inputs, labels, adv_x, adv_y)\r\n    assert str(e.value) == 'inputs must not be empty'\r\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/evaluations/test_defense_eval.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nDefense evaluation test.\n\"\"\"\nimport numpy as np\nimport pytest\n\nfrom mindarmour.adv_robustness.evaluations import DefenseEvaluate\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_def_eval():\n    # prepare data\n    raw_preds = np.array([[0.1, 0.1, 0.2, 0.6],\n                          [0.1, 0.7, 0.0, 0.2],\n                          [0.8, 0.1, 0.0, 0.1]])\n    def_preds = np.array([[0.1, 0.1, 0.1, 0.7],\n                          [0.1, 0.6, 0.2, 0.1],\n                          [0.1, 0.2, 0.1, 0.6]])\n    true_labels = np.array([3, 1, 0])\n\n    # create obj\n    def_eval = DefenseEvaluate(raw_preds, def_preds, true_labels)\n\n    # run eval\n    cav = def_eval.cav()\n    crr = def_eval.crr()\n    csr = def_eval.csr()\n    ccv = def_eval.ccv()\n    cos = def_eval.cos()\n    res = [cav, crr, csr, ccv, cos]\n\n    # compare\n    expected_value = [-0.3333, 0.0, 0.3333, 0.0999, 0.0450]\n    assert np.allclose(res, expected_value, 0.0001, 0.0001)\n"
  },
  {
    "path": "tests/ut/python/adv_robustness/evaluations/test_radar_metric.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nRadar map test.\n\"\"\"\nimport numpy as np\nimport pytest\nfrom mindarmour.adv_robustness.evaluations import RadarMetric\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_radar_metric():\n    # prepare data\n    metrics_name = ['MR', 'ACAC', 'ASS', 'NTE', 'RGB']\n    def_metrics = [0.9, 0.85, 0.6, 0.7, 0.8]\n    raw_metrics = [0.5, 0.3, 0.55, 0.65, 0.7]\n    metrics_data = np.array([def_metrics, raw_metrics])\n    metrics_labels = ['before', 'after']\n\n    # create obj\n    _ = RadarMetric(metrics_name, metrics_data, metrics_labels, title='',\n                    scale='sparse')\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_value_error():\n    # prepare data\n    metrics_name = ['MR', 'ACAC', 'ASS', 'NTE', 'RGB']\n    def_metrics = [0.9, 0.85, 0.6, 0.7, 0.8]\n    raw_metrics = [0.5, 0.3, 0.55, 0.65, 0.7]\n    metrics_data = np.array([def_metrics, raw_metrics])\n    metrics_labels = ['before', 'after']\n\n    with pytest.raises(ValueError):\n        assert RadarMetric(metrics_name, metrics_data, metrics_labels,\n                           title='', scale='bad_s')\n\n    with pytest.raises(ValueError):\n        assert RadarMetric(['MR', 'ACAC', 'ASS'], metrics_data, metrics_labels,\n                           title='', scale='bad_s')\n"
  },
  {
    "path": "tests/ut/python/fuzzing/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis package includes unit tests for model fuzzing.\n\"\"\"\n"
  },
  {
    "path": "tests/ut/python/fuzzing/test_coverage_metrics.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nModel-fuzz coverage test.\n\"\"\"\nimport numpy as np\nimport pytest\n\nfrom mindspore import nn\nfrom mindspore.nn import Cell, SoftmaxCrossEntropyWithLogits\nfrom mindspore.train import Model\nfrom mindspore import context\nfrom mindspore.ops import TensorSummary\n\nfrom mindarmour.adv_robustness.attacks import FastGradientSignMethod\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.fuzz_testing import NeuronCoverage, TopKNeuronCoverage, SuperNeuronActivateCoverage, \\\n    NeuronBoundsCoverage, KMultisectionNeuronCoverage\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Neuron coverage test'\nLOGGER.set_level('INFO')\n\n\n# for user\nclass Net(Cell):\n    \"\"\"\n    Construct the network of target model.\n\n    Examples:\n        >>> net = Net()\n    \"\"\"\n\n    def __init__(self):\n        \"\"\"\n        Introduce the layers used for network construction.\n        \"\"\"\n        super(Net, self).__init__()\n        self._relu = nn.ReLU()\n        self.summary = TensorSummary()\n\n    def construct(self, inputs):\n        \"\"\"\n        Construct network.\n\n        Args:\n            inputs (Tensor): Input data.\n        \"\"\"\n        self.summary('input', inputs)\n\n        out = self._relu(inputs)\n        self.summary('1', out)\n        return out\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_lenet_mnist_coverage_cpu():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    # load network\n    net = Net()\n    model = Model(net)\n\n    # initialize fuzz test with training dataset\n    training_data = (np.random.random((10000, 10))*20).astype(np.float32)\n\n    # fuzz test with original test data\n    # get test data\n    test_data = (np.random.random((2000, 10))*20).astype(np.float32)\n    test_labels = np.random.randint(0, 10, 2000).astype(np.int32)\n\n    nc = NeuronCoverage(model, threshold=0.1)\n    nc_metric = nc.get_metrics(test_data)\n\n    tknc = TopKNeuronCoverage(model, top_k=3)\n    tknc_metrics = tknc.get_metrics(test_data)\n\n    snac = SuperNeuronActivateCoverage(model, training_data)\n    snac_metrics = snac.get_metrics(test_data)\n\n    nbc = NeuronBoundsCoverage(model, training_data)\n    nbc_metrics = nbc.get_metrics(test_data)\n\n    kmnc = KMultisectionNeuronCoverage(model, training_data, segmented_num=100)\n    kmnc_metrics = kmnc.get_metrics(test_data)\n\n    print('KMNC of this test is: ', kmnc_metrics)\n    print('NBC of this test is: ', nbc_metrics)\n    print('SNAC of this test is: ', snac_metrics)\n    print('NC of this test is: ', nc_metric)\n    print('TKNC of this test is: ', tknc_metrics)\n\n    # generate adv_data\n    loss = SoftmaxCrossEntropyWithLogits(sparse=True)\n    attack = FastGradientSignMethod(net, eps=0.3, loss_fn=loss)\n    adv_data = attack.batch_generate(test_data, test_labels, batch_size=32)\n    nc_metric = nc.get_metrics(adv_data)\n    tknc_metrics = tknc.get_metrics(adv_data)\n    snac_metrics = snac.get_metrics(adv_data)\n    nbc_metrics = nbc.get_metrics(adv_data)\n    kmnc_metrics = kmnc.get_metrics(adv_data)\n    print('KMNC of adv data is: ', kmnc_metrics)\n    print('NBC of adv data is: ', nbc_metrics)\n    print('SNAC of adv data is: ', snac_metrics)\n    print('NC of adv data is: ', nc_metric)\n    print('TKNC of adv data is: ', tknc_metrics)\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_lenet_mnist_coverage_ascend():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    # load network\n    net = Net()\n    model = Model(net)\n\n    # initialize fuzz test with training dataset\n    training_data = (np.random.random((10000, 10))*20).astype(np.float32)\n\n    # fuzz test with original test data\n    # get test data\n    test_data = (np.random.random((2000, 10))*20).astype(np.float32)\n    nc = NeuronCoverage(model, threshold=0.1)\n    nc_metric = nc.get_metrics(test_data)\n\n    tknc = TopKNeuronCoverage(model, top_k=3)\n    tknc_metrics = tknc.get_metrics(test_data)\n\n    snac = SuperNeuronActivateCoverage(model, training_data)\n    snac_metrics = snac.get_metrics(test_data)\n\n    nbc = NeuronBoundsCoverage(model, training_data)\n    nbc_metrics = nbc.get_metrics(test_data)\n\n    kmnc = KMultisectionNeuronCoverage(model, training_data, segmented_num=100)\n    kmnc_metrics = kmnc.get_metrics(test_data)\n\n    print('KMNC of this test is: ', kmnc_metrics)\n    print('NBC of this test is: ', nbc_metrics)\n    print('SNAC of this test is: ', snac_metrics)\n    print('NC of this test is: ', nc_metric)\n    print('TKNC of this test is: ', tknc_metrics)\n"
  },
  {
    "path": "tests/ut/python/fuzzing/test_fuzzer.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nModel-fuzzer test.\n\"\"\"\nimport numpy as np\nimport pytest\nfrom mindspore import context\nfrom mindspore import nn\nfrom mindspore.common.initializer import TruncatedNormal\nfrom mindspore.ops import operations as P\nfrom mindspore.train import Model\nfrom mindspore.ops import TensorSummary\n\nfrom mindarmour.fuzz_testing import Fuzzer\nfrom mindarmour.fuzz_testing import KMultisectionNeuronCoverage\nfrom mindarmour.utils.logger import LogUtil\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Fuzzing test'\nLOGGER.set_level('INFO')\n\n\ndef conv(in_channels, out_channels, kernel_size, stride=1, padding=0):\n    weight = weight_variable()\n    return nn.Conv2d(in_channels, out_channels,\n                     kernel_size=kernel_size, stride=stride, padding=padding,\n                     weight_init=weight, has_bias=False, pad_mode=\"valid\")\n\n\ndef fc_with_initialize(input_channels, out_channels):\n    weight = weight_variable()\n    bias = weight_variable()\n    return nn.Dense(input_channels, out_channels, weight, bias)\n\n\ndef weight_variable():\n    return TruncatedNormal(0.02)\n\n\nclass Net(nn.Cell):\n    \"\"\"\n    Lenet network\n    \"\"\"\n\n    def __init__(self):\n        super(Net, self).__init__()\n        self.conv1 = conv(1, 6, 5)\n        self.conv2 = conv(6, 16, 5)\n        self.fc1 = fc_with_initialize(16 * 5 * 5, 120)\n        self.fc2 = fc_with_initialize(120, 84)\n        self.fc3 = fc_with_initialize(84, 10)\n        self.relu = nn.ReLU()\n        self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.reshape = P.Reshape()\n        self.summary = TensorSummary()\n\n    def construct(self, x):\n        x = self.conv1(x)\n        x = self.relu(x)\n        self.summary('conv1', x)\n        x = self.max_pool2d(x)\n        x = self.conv2(x)\n        x = self.relu(x)\n        self.summary('conv2', x)\n        x = self.max_pool2d(x)\n        x = self.reshape(x, (-1, 16 * 5 * 5))\n        x = self.fc1(x)\n        x = self.relu(x)\n        self.summary('fc1', x)\n        x = self.fc2(x)\n        x = self.relu(x)\n        self.summary('fc2', x)\n        x = self.fc3(x)\n        self.summary('fc3', x)\n        return x\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_fuzzing_ascend():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    # load network\n    net = Net()\n    model = Model(net)\n    batch_size = 8\n    num_classe = 10\n    mutate_config = [{'method': 'GaussianBlur',\n                      'params': {'ksize': [1, 2, 3, 5],\n                                 'auto_param': [True, False]}},\n                     {'method': 'UniformNoise',\n                      'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n                     {'method': 'Contrast',\n                      'params': {'alpha': [0.5, 1, 1.5], 'beta': [-10, 0, 10], 'auto_param': [False, True]}},\n                     {'method': 'Rotate',\n                      'params': {'angle': [20, 90], 'auto_param': [False, True]}},\n                     {'method': 'FGSM',\n                      'params': {'eps': [0.3, 0.2, 0.4], 'alpha': [0.1], 'bounds': [(0, 1)]}}]\n\n    train_images = np.random.rand(32, 1, 32, 32).astype(np.float32)\n    # fuzz test with original test data\n    # get test data\n    test_images = np.random.rand(batch_size, 1, 32, 32).astype(np.float32)\n    test_labels = np.random.randint(num_classe, size=batch_size).astype(np.int32)\n    test_labels = (np.eye(num_classe)[test_labels]).astype(np.float32)\n\n    initial_seeds = []\n    # make initial seeds\n    for img, label in zip(test_images, test_labels):\n        initial_seeds.append([img, label])\n\n    initial_seeds = initial_seeds[:100]\n\n    nc = KMultisectionNeuronCoverage(model, train_images, segmented_num=100)\n    cn_metrics = nc.get_metrics(test_images[:100])\n    print('neuron coverage of initial seeds is: ', cn_metrics)\n    model_fuzz_test = Fuzzer(model)\n    _, _, _, _, metrics = model_fuzz_test.fuzzing(mutate_config, initial_seeds, nc, max_iters=100)\n    print(metrics)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_fuzzing_cpu():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    # load network\n    net = Net()\n    model = Model(net)\n    batch_size = 8\n    num_classe = 10\n    mutate_config = [{'method': 'GaussianBlur',\n                      'params': {'ksize': [1, 2, 3, 5],\n                                 'auto_param': [True, False]}},\n                     {'method': 'UniformNoise',\n                      'params': {'factor': [0.1, 0.2, 0.3], 'auto_param': [False, True]}},\n                     {'method': 'Contrast',\n                      'params': {'alpha': [0.5, 1, 1.5], 'beta': [-10, 0, 10], 'auto_param': [False, True]}},\n                     {'method': 'Rotate',\n                      'params': {'angle': [20, 90], 'auto_param': [False, True]}},\n                     {'method': 'FGSM',\n                      'params': {'eps': [0.3, 0.2, 0.4], 'alpha': [0.1], 'bounds': [(0, 1)]}}]\n    # initialize fuzz test with training dataset\n    train_images = np.random.rand(32, 1, 32, 32).astype(np.float32)\n\n    # fuzz test with original test data\n    # get test data\n    test_images = np.random.rand(batch_size, 1, 32, 32).astype(np.float32)\n    test_labels = np.random.randint(num_classe, size=batch_size).astype(np.int32)\n    test_labels = (np.eye(num_classe)[test_labels]).astype(np.float32)\n\n    initial_seeds = []\n    # make initial seeds\n    for img, label in zip(test_images, test_labels):\n        initial_seeds.append([img, label])\n\n    initial_seeds = initial_seeds[:100]\n    nc = KMultisectionNeuronCoverage(model, train_images, segmented_num=100)\n    tknc_metrics = nc.get_metrics(test_images[:100])\n    print('neuron coverage of initial seeds is: ', tknc_metrics)\n    model_fuzz_test = Fuzzer(model)\n    _, _, _, _, metrics = model_fuzz_test.fuzzing(mutate_config, initial_seeds, nc, max_iters=100)\n    print(metrics)\n"
  },
  {
    "path": "tests/ut/python/natural_robustness/test_natural_robustness.py",
    "content": "# Copyright 2022 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"Example for natural robustness methods.\"\"\"\n\nimport pytest\nimport numpy as np\nfrom mindspore import context\n\nfrom mindarmour.natural_robustness.transform.image import Translate, Curve, Perspective, Scale, Shear, Rotate, \\\n    SaltAndPepperNoise, NaturalNoise, GaussianNoise, UniformNoise, MotionBlur, GaussianBlur, GradientBlur, Contrast,\\\n    GradientLuminance\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_perspective():\n    \"\"\"\n    Feature: Test image perspective.\n    Description: Image will be transform for given perspective projection.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    image = np.random.random((32, 32, 3))\n    ori_pos = [[0, 0], [0, 800], [800, 0], [800, 800]]\n    dst_pos = [[50, 0], [0, 800], [780, 0], [800, 800]]\n    trans = Perspective(ori_pos, dst_pos)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_uniform_noise():\n    \"\"\"\n    Feature: Test image uniform noise.\n    Description: Add uniform image in image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    image = np.random.random((32, 32, 3))\n    trans = UniformNoise(factor=0.1)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_gaussian_noise():\n    \"\"\"\n    Feature: Test image gaussian noise.\n    Description: Add gaussian image in image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    image = np.random.random((32, 32, 3))\n    trans = GaussianNoise(factor=0.1)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_contrast():\n    \"\"\"\n    Feature: Test image contrast.\n    Description: Adjust image contrast.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    image = np.random.random((32, 32, 3))\n    trans = Contrast(alpha=0.3, beta=0)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_gaussian_blur():\n    \"\"\"\n    Feature: Test image gaussian blur.\n    Description: Add gaussian blur to image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    image = np.random.random((32, 32, 3))\n    trans = GaussianBlur(ksize=5)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_salt_and_pepper_noise():\n    \"\"\"\n    Feature: Test image salt and pepper noise.\n    Description: Add salt and pepper to image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    image = np.random.random((32, 32, 3))\n    trans = SaltAndPepperNoise(factor=0.01)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_translate():\n    \"\"\"\n    Feature: Test image translate.\n    Description: Translate an image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    image = np.random.random((32, 32, 3))\n    trans = Translate(x_bias=0.1, y_bias=0.1)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_scale():\n    \"\"\"\n    Feature: Test image scale.\n    Description: Scale an image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    image = np.random.random((32, 32, 3))\n    trans = Scale(factor_x=0.7, factor_y=0.7)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_shear():\n    \"\"\"\n    Feature: Test image shear.\n    Description: Shear an image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    image = np.random.random((32, 32, 3))\n    trans = Shear(factor=0.2)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_rotate():\n    \"\"\"\n    Feature: Test image rotate.\n    Description: Rotate an image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    image = np.random.random((32, 32, 3))\n    trans = Rotate(angle=20)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_curve():\n    \"\"\"\n    Feature: Test image curve.\n    Description: Transform an image with curve.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    image = np.random.random((32, 32, 3))\n    trans = Curve(curves=1.5, depth=1.5, mode='horizontal')\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_natural_noise():\n    \"\"\"\n    Feature: Test natural noise.\n    Description: Add natural noise to an.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    image = np.random.random((32, 32, 3))\n    trans = NaturalNoise(ratio=0.0001, k_x_range=(1, 30), k_y_range=(1, 10), auto_param=True)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_gradient_luminance():\n    \"\"\"\n    Feature: Test gradient luminance.\n    Description: Adjust image luminance.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    image = np.random.random((32, 32, 3))\n    height, width = image.shape[:2]\n    point = (height // 4, width // 2)\n    start = (255, 255, 255)\n    end = (0, 0, 0)\n    scope = 0.3\n    bright_rate = 0.4\n    trans = GradientLuminance(start, end, start_point=point, scope=scope, pattern='dark', bright_rate=bright_rate,\n                              mode='horizontal')\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_motion_blur():\n    \"\"\"\n    Feature: Test motion blur.\n    Description: Add motion blur to an image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    image = np.random.random((32, 32, 3))\n    angle = -10.5\n    i = 3\n    trans = MotionBlur(degree=i, angle=angle)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_gradient_blur():\n    \"\"\"\n    Feature: Test gradient blur.\n    Description: Add gradient blur to an image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    image = np.random.random((32, 32, 3))\n    number = 10\n    h, w = image.shape[:2]\n    point = (int(h / 5), int(w / 5))\n    center = False\n    trans = GradientBlur(point, number, center)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_perspective_ascend():\n    \"\"\"\n    Feature: Test image perspective.\n    Description: Image will be transform for given perspective projection.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    image = np.random.random((32, 32, 3))\n    ori_pos = [[0, 0], [0, 800], [800, 0], [800, 800]]\n    dst_pos = [[50, 0], [0, 800], [780, 0], [800, 800]]\n    trans = Perspective(ori_pos, dst_pos)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_uniform_noise_ascend():\n    \"\"\"\n    Feature: Test image uniform noise.\n    Description: Add uniform image in image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    image = np.random.random((32, 32, 3))\n    trans = UniformNoise(factor=0.1)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_gaussian_noise_ascend():\n    \"\"\"\n    Feature: Test image gaussian noise.\n    Description: Add gaussian image in image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    image = np.random.random((32, 32, 3))\n    trans = GaussianNoise(factor=0.1)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_contrast_ascend():\n    \"\"\"\n    Feature: Test image contrast.\n    Description: Adjust image contrast.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    image = np.random.random((32, 32, 3))\n    trans = Contrast(alpha=0.3, beta=0)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_gaussian_blur_ascend():\n    \"\"\"\n    Feature: Test image gaussian blur.\n    Description: Add gaussian blur to image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    image = np.random.random((32, 32, 3))\n    trans = GaussianBlur(ksize=5)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_salt_and_pepper_noise_ascend():\n    \"\"\"\n    Feature: Test image salt and pepper noise.\n    Description: Add salt and pepper to image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    image = np.random.random((32, 32, 3))\n    trans = SaltAndPepperNoise(factor=0.01)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_translate_ascend():\n    \"\"\"\n    Feature: Test image translate.\n    Description: Translate an image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    image = np.random.random((32, 32, 3))\n    trans = Translate(x_bias=0.1, y_bias=0.1)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_ascend_mindarmour\ndef test_scale_ascend():\n    \"\"\"\n    Feature: Test image scale.\n    Description: Scale an image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    image = np.random.random((32, 32, 3))\n    trans = Scale(factor_x=0.7, factor_y=0.7)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_shear_ascend():\n    \"\"\"\n    Feature: Test image shear.\n    Description: Shear an image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    image = np.random.random((32, 32, 3))\n    trans = Shear(factor=0.2)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_rotate_ascend():\n    \"\"\"\n    Feature: Test image rotate.\n    Description: Rotate an image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    image = np.random.random((32, 32, 3))\n    trans = Rotate(angle=20)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_curve_ascend():\n    \"\"\"\n    Feature: Test image curve.\n    Description: Transform an image with curve.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    image = np.random.random((32, 32, 3))\n    trans = Curve(curves=1.5, depth=1.5, mode='horizontal')\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_natural_noise_ascend():\n    \"\"\"\n    Feature: Test natural noise.\n    Description: Add natural noise to an.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    image = np.random.random((32, 32, 3))\n    trans = NaturalNoise(ratio=0.0001, k_x_range=(1, 30), k_y_range=(1, 10), auto_param=True)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_gradient_luminance_ascend():\n    \"\"\"\n    Feature: Test gradient luminance.\n    Description: Adjust image luminance.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    image = np.random.random((32, 32, 3))\n    height, width = image.shape[:2]\n    point = (height // 4, width // 2)\n    start = (255, 255, 255)\n    end = (0, 0, 0)\n    scope = 0.3\n    bright_rate = 0.4\n    trans = GradientLuminance(start, end, start_point=point, scope=scope, pattern='dark', bright_rate=bright_rate,\n                              mode='horizontal')\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_motion_blur_ascend():\n    \"\"\"\n    Feature: Test motion blur.\n    Description: Add motion blur to an image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    image = np.random.random((32, 32, 3))\n    angle = -10.5\n    i = 3\n    trans = MotionBlur(degree=i, angle=angle)\n    dst = trans(image)\n    print(dst)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_gradient_blur_ascend():\n    \"\"\"\n    Feature: Test gradient blur.\n    Description: Add gradient blur to an image.\n    Expectation: success.\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    image = np.random.random((32, 32, 3))\n    number = 10\n    h, w = image.shape[:2]\n    point = (int(h / 5), int(w / 5))\n    center = False\n    trans = GradientBlur(point, number, center)\n    dst = trans(image)\n    print(dst)\n"
  },
  {
    "path": "tests/ut/python/privacy/__init__.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis package includes unit tests for differential-privacy training,\n suppress-privacy training and privacy breach estimation.\n\"\"\"\n"
  },
  {
    "path": "tests/ut/python/privacy/diff_privacy/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis package includes unit tests for differential-privacy training and\nprivacy-budget estimation.\n\"\"\"\n"
  },
  {
    "path": "tests/ut/python/privacy/diff_privacy/test_mechanisms.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\ndifferent Privacy test.\n\"\"\"\nimport pytest\n\nfrom mindspore import context\nfrom mindspore import Tensor\nfrom mindspore.common import dtype as mstype\nfrom mindarmour.privacy.diff_privacy import NoiseAdaGaussianRandom\nfrom mindarmour.privacy.diff_privacy import AdaClippingWithGaussianRandom\nfrom mindarmour.privacy.diff_privacy import NoiseMechanismsFactory\nfrom mindarmour.privacy.diff_privacy import ClipMechanismsFactory\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_graph_factory():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    grad = Tensor([0.3, 0.2, 0.4], mstype.float32)\n    norm_bound = 1.0\n    initial_noise_multiplier = 0.1\n    alpha = 0.5\n    decay_policy = 'Step'\n    factory = NoiseMechanismsFactory()\n    noise_mech = factory.create('Gaussian',\n                                norm_bound,\n                                initial_noise_multiplier)\n    noise = noise_mech(grad)\n    print('Gaussian noise: ', noise)\n    ada_noise_mech = factory.create('AdaGaussian',\n                                    norm_bound,\n                                    initial_noise_multiplier,\n                                    noise_decay_rate=alpha,\n                                    decay_policy=decay_policy)\n    ada_noise = ada_noise_mech(grad)\n    print('ada noise: ', ada_noise)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_pynative_factory():\n    context.set_context(mode=context.PYNATIVE_MODE, device_target=\"Ascend\")\n    grad = Tensor([0.3, 0.2, 0.4], mstype.float32)\n    norm_bound = 1.0\n    initial_noise_multiplier = 0.1\n    alpha = 0.5\n    decay_policy = 'Step'\n    factory = NoiseMechanismsFactory()\n    noise_mech = factory.create('Gaussian',\n                                norm_bound,\n                                initial_noise_multiplier)\n    noise = noise_mech(grad)\n    print('Gaussian noise: ', noise)\n    ada_noise_mech = factory.create('AdaGaussian',\n                                    norm_bound,\n                                    initial_noise_multiplier,\n                                    noise_decay_rate=alpha,\n                                    decay_policy=decay_policy)\n    ada_noise = ada_noise_mech(grad)\n    print('ada noise: ', ada_noise)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_pynative_gaussian():\n    context.set_context(mode=context.PYNATIVE_MODE, device_target=\"Ascend\")\n    grad = Tensor([0.3, 0.2, 0.4], mstype.float32)\n    norm_bound = 1.0\n    initial_noise_multiplier = 0.1\n    alpha = 0.5\n    decay_policy = 'Step'\n    factory = NoiseMechanismsFactory()\n    noise_mech = factory.create('Gaussian',\n                                norm_bound,\n                                initial_noise_multiplier)\n    noise = noise_mech(grad)\n    print('Gaussian noise: ', noise)\n    ada_noise_mech = factory.create('AdaGaussian',\n                                    norm_bound,\n                                    initial_noise_multiplier,\n                                    noise_decay_rate=alpha,\n                                    decay_policy=decay_policy)\n    ada_noise = ada_noise_mech(grad)\n    print('ada noise: ', ada_noise)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_graph_ada_gaussian():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    grad = Tensor([0.3, 0.2, 0.4], mstype.float32)\n    norm_bound = 1.0\n    initial_noise_multiplier = 0.1\n    noise_decay_rate = 0.5\n    decay_policy = 'Step'\n    ada_noise_mech = NoiseAdaGaussianRandom(norm_bound,\n                                            initial_noise_multiplier,\n                                            seed=0,\n                                            noise_decay_rate=noise_decay_rate,\n                                            decay_policy=decay_policy)\n    res = ada_noise_mech(grad)\n    print(res)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_pynative_ada_gaussian():\n    context.set_context(mode=context.PYNATIVE_MODE, device_target=\"Ascend\")\n    grad = Tensor([0.3, 0.2, 0.4], mstype.float32)\n    norm_bound = 1.0\n    initial_noise_multiplier = 0.1\n    noise_decay_rate = 0.5\n    decay_policy = 'Step'\n    ada_noise_mech = NoiseAdaGaussianRandom(norm_bound,\n                                            initial_noise_multiplier,\n                                            seed=0,\n                                            noise_decay_rate=noise_decay_rate,\n                                            decay_policy=decay_policy)\n    res = ada_noise_mech(grad)\n    print(res)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_graph_exponential():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    grad = Tensor([0.3, 0.2, 0.4], mstype.float32)\n    norm_bound = 1.0\n    initial_noise_multiplier = 0.1\n    alpha = 0.5\n    decay_policy = 'Exp'\n    factory = NoiseMechanismsFactory()\n    ada_noise = factory.create('AdaGaussian',\n                               norm_bound,\n                               initial_noise_multiplier,\n                               noise_decay_rate=alpha,\n                               decay_policy=decay_policy)\n    ada_noise = ada_noise(grad)\n    print('ada noise: ', ada_noise)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_pynative_exponential():\n    context.set_context(mode=context.PYNATIVE_MODE, device_target=\"Ascend\")\n    grad = Tensor([0.3, 0.2, 0.4], mstype.float32)\n    norm_bound = 1.0\n    initial_noise_multiplier = 0.1\n    alpha = 0.5\n    decay_policy = 'Exp'\n    factory = NoiseMechanismsFactory()\n    ada_noise = factory.create('AdaGaussian',\n                               norm_bound,\n                               initial_noise_multiplier,\n                               noise_decay_rate=alpha,\n                               decay_policy=decay_policy)\n    ada_noise = ada_noise(grad)\n    print('ada noise: ', ada_noise)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_ada_clip_gaussian_random_pynative():\n    context.set_context(mode=context.PYNATIVE_MODE, device_target=\"Ascend\")\n    decay_policy = 'Linear'\n    beta = Tensor(0.5, mstype.float32)\n    norm_bound = Tensor(1.0, mstype.float32)\n    beta_stddev = 0.1\n    learning_rate = 0.1\n    target_unclipped_quantile = 0.3\n    ada_clip = AdaClippingWithGaussianRandom(decay_policy=decay_policy,\n                                             learning_rate=learning_rate,\n                                             target_unclipped_quantile=target_unclipped_quantile,\n                                             fraction_stddev=beta_stddev,\n                                             seed=1)\n    next_norm_bound = ada_clip(beta, norm_bound)\n    print('Liner next norm clip:', next_norm_bound)\n\n    decay_policy = 'Geometric'\n    ada_clip = AdaClippingWithGaussianRandom(decay_policy=decay_policy,\n                                             learning_rate=learning_rate,\n                                             target_unclipped_quantile=target_unclipped_quantile,\n                                             fraction_stddev=beta_stddev,\n                                             seed=1)\n    next_norm_bound = ada_clip(beta, norm_bound)\n    print('Geometric next norm clip:', next_norm_bound)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_ada_clip_gaussian_random_graph():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    decay_policy = 'Linear'\n    beta = Tensor(0.5, mstype.float32)\n    norm_bound = Tensor(1.0, mstype.float32)\n    beta_stddev = 0.1\n    learning_rate = 0.1\n    target_unclipped_quantile = 0.3\n    ada_clip = AdaClippingWithGaussianRandom(decay_policy=decay_policy,\n                                             learning_rate=learning_rate,\n                                             target_unclipped_quantile=target_unclipped_quantile,\n                                             fraction_stddev=beta_stddev,\n                                             seed=1)\n    next_norm_bound = ada_clip(beta, norm_bound)\n    print('Liner next norm clip:', next_norm_bound)\n\n    decay_policy = 'Geometric'\n    ada_clip = AdaClippingWithGaussianRandom(decay_policy=decay_policy,\n                                             learning_rate=learning_rate,\n                                             target_unclipped_quantile=target_unclipped_quantile,\n                                             fraction_stddev=beta_stddev,\n                                             seed=1)\n    next_norm_bound = ada_clip(beta, norm_bound)\n    print('Geometric next norm clip:', next_norm_bound)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_pynative_clip_mech_factory():\n    context.set_context(mode=context.PYNATIVE_MODE, device_target=\"Ascend\")\n    decay_policy = 'Linear'\n    beta = Tensor(0.5, mstype.float32)\n    norm_bound = Tensor(1.0, mstype.float32)\n    beta_stddev = 0.1\n    learning_rate = 0.1\n    target_unclipped_quantile = 0.3\n    factory = ClipMechanismsFactory()\n    ada_clip = factory.create('Gaussian',\n                              decay_policy=decay_policy,\n                              learning_rate=learning_rate,\n                              target_unclipped_quantile=target_unclipped_quantile,\n                              fraction_stddev=beta_stddev)\n    next_norm_bound = ada_clip(beta, norm_bound)\n    print('next_norm_bound: ', next_norm_bound)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_graph_clip_mech_factory():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    decay_policy = 'Linear'\n    beta = Tensor(0.5, mstype.float32)\n    norm_bound = Tensor(1.0, mstype.float32)\n    beta_stddev = 0.1\n    learning_rate = 0.1\n    target_unclipped_quantile = 0.3\n    factory = ClipMechanismsFactory()\n    ada_clip = factory.create('Gaussian',\n                              decay_policy=decay_policy,\n                              learning_rate=learning_rate,\n                              target_unclipped_quantile=target_unclipped_quantile,\n                              fraction_stddev=beta_stddev)\n    next_norm_bound = ada_clip(beta, norm_bound)\n    print('next_norm_bound: ', next_norm_bound)\n"
  },
  {
    "path": "tests/ut/python/privacy/diff_privacy/test_model_train.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nDP-Model test.\n\"\"\"\nimport pytest\nimport numpy as np\n\nfrom mindspore import nn\nfrom mindspore import context\nimport mindspore.dataset as ds\n\nfrom mindarmour.privacy.diff_privacy import DPModel\nfrom mindarmour.privacy.diff_privacy import NoiseMechanismsFactory\nfrom mindarmour.privacy.diff_privacy import ClipMechanismsFactory\nfrom mindarmour.privacy.diff_privacy import DPOptimizerClassFactory\n\nfrom tests.ut.python.utils.mock_net import Net\n\n\ndef dataset_generator():\n    \"\"\"mock training data.\"\"\"\n    batch_size = 32\n    batches = 128\n    data = np.random.random((batches*batch_size, 1, 32, 32)).astype(\n        np.float32)\n    label = np.random.randint(0, 10, batches*batch_size).astype(np.int32)\n    for i in range(batches):\n        yield data[i*batch_size:(i + 1)*batch_size],\\\n              label[i*batch_size:(i + 1)*batch_size]\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_dp_model_with_pynative_mode():\n    context.set_context(mode=context.PYNATIVE_MODE, device_target=\"Ascend\")\n    norm_bound = 1.0\n    initial_noise_multiplier = 0.01\n    network = Net()\n    epochs = 1\n    micro_batches = 2\n    loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True)\n    factory_opt = DPOptimizerClassFactory(micro_batches=micro_batches)\n    factory_opt.set_mechanisms('Gaussian',\n                               norm_bound=norm_bound,\n                               initial_noise_multiplier=initial_noise_multiplier)\n    net_opt = factory_opt.create('Momentum')(network.trainable_params(),\n                                             learning_rate=0.1, momentum=0.9)\n    clip_mech = ClipMechanismsFactory().create('Gaussian',\n                                               decay_policy='Linear',\n                                               learning_rate=0.01,\n                                               target_unclipped_quantile=0.9,\n                                               fraction_stddev=0.01)\n    model = DPModel(micro_batches=micro_batches,\n                    norm_bound=norm_bound,\n                    clip_mech=clip_mech,\n                    noise_mech=None,\n                    network=network,\n                    loss_fn=loss,\n                    optimizer=net_opt,\n                    metrics=None)\n    ms_ds = ds.GeneratorDataset(dataset_generator,\n                                ['data', 'label'])\n    model.train(epochs, ms_ds, dataset_sink_mode=False)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_dp_model_with_graph_mode():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    norm_bound = 1.0\n    initial_noise_multiplier = 0.01\n    network = Net()\n    epochs = 1\n    loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True)\n    noise_mech = NoiseMechanismsFactory().create('Gaussian',\n                                                 norm_bound=norm_bound,\n                                                 initial_noise_multiplier=initial_noise_multiplier)\n    clip_mech = ClipMechanismsFactory().create('Gaussian',\n                                               decay_policy='Linear',\n                                               learning_rate=0.01,\n                                               target_unclipped_quantile=0.9,\n                                               fraction_stddev=0.01)\n    net_opt = nn.Momentum(network.trainable_params(), learning_rate=0.1,\n                          momentum=0.9)\n    model = DPModel(micro_batches=2,\n                    clip_mech=clip_mech,\n                    norm_bound=norm_bound,\n                    noise_mech=noise_mech,\n                    network=network,\n                    loss_fn=loss,\n                    optimizer=net_opt,\n                    metrics=None)\n    ms_ds = ds.GeneratorDataset(dataset_generator,\n                                ['data', 'label'])\n    model.train(epochs, ms_ds, dataset_sink_mode=False)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_dp_model_with_graph_mode_ada_gaussian():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    norm_bound = 1.0\n    initial_noise_multiplier = 0.01\n    network = Net()\n    epochs = 1\n    alpha = 0.8\n    loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True)\n    noise_mech = NoiseMechanismsFactory().create('AdaGaussian',\n                                                 norm_bound=norm_bound,\n                                                 initial_noise_multiplier=initial_noise_multiplier,\n                                                 noise_decay_rate=alpha,\n                                                 decay_policy='Exp')\n    clip_mech = None\n    net_opt = nn.Momentum(network.trainable_params(), learning_rate=0.1,\n                          momentum=0.9)\n    model = DPModel(micro_batches=2,\n                    clip_mech=clip_mech,\n                    norm_bound=norm_bound,\n                    noise_mech=noise_mech,\n                    network=network,\n                    loss_fn=loss,\n                    optimizer=net_opt,\n                    metrics=None)\n    ms_ds = ds.GeneratorDataset(dataset_generator,\n                                ['data', 'label'])\n    model.train(epochs, ms_ds, dataset_sink_mode=False)\n"
  },
  {
    "path": "tests/ut/python/privacy/diff_privacy/test_monitor.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nDP-Monitor test.\n\"\"\"\nimport pytest\nimport numpy as np\n\nimport mindspore.nn as nn\nimport mindspore.dataset as ds\nfrom mindspore.train import Model\nimport mindspore.context as context\n\nfrom mindarmour.privacy.diff_privacy import PrivacyMonitorFactory\nfrom mindarmour.utils.logger import LogUtil\n\nfrom tests.ut.python.utils.mock_net import Net\n\nLOGGER = LogUtil.get_instance()\nTAG = 'DP-Monitor Test'\n\n\ndef dataset_generator():\n    batch_size = 16\n    batches = 128\n\n    data = np.random.random((batches * batch_size, 1, 32, 32)).astype(\n        np.float32)\n    label = np.random.randint(0, 10, batches * batch_size).astype(np.int32)\n    for i in range(batches):\n        yield data[i * batch_size: (i + 1) * batch_size], \\\n              label[i * batch_size: (i + 1) * batch_size]\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_dp_monitor():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    batch_size = 16\n    epochs = 1\n    rdp = PrivacyMonitorFactory.create(policy='rdp', num_samples=60000,\n                                       batch_size=batch_size,\n                                       initial_noise_multiplier=0.4,\n                                       noise_decay_rate=6e-3)\n    suggest_epoch = rdp.max_epoch_suggest()\n    LOGGER.info(TAG, 'The recommended maximum training epochs is: %s',\n                suggest_epoch)\n    network = Net()\n    net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction=\"mean\")\n    net_opt = nn.Momentum(network.trainable_params(), 0.01, 0.9)\n\n    model = Model(network, net_loss, net_opt)\n\n    LOGGER.info(TAG, \"============== Starting Training ==============\")\n    ds1 = ds.GeneratorDataset(dataset_generator,\n                              [\"data\", \"label\"])\n    model.train(epochs, ds1, callbacks=[rdp], dataset_sink_mode=False)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_gpu_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_dp_monitor_gpu():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"GPU\")\n    batch_size = 16\n    epochs = 1\n    rdp = PrivacyMonitorFactory.create(policy='rdp', num_samples=60000,\n                                       batch_size=batch_size,\n                                       initial_noise_multiplier=0.4,\n                                       noise_decay_rate=6e-3)\n    suggest_epoch = rdp.max_epoch_suggest()\n    LOGGER.info(TAG, 'The recommended maximum training epochs is: %s',\n                suggest_epoch)\n    network = Net()\n    net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction=\"mean\")\n    net_opt = nn.Momentum(network.trainable_params(), 0.01, 0.9)\n\n    model = Model(network, net_loss, net_opt)\n\n    LOGGER.info(TAG, \"============== Starting Training ==============\")\n    ds1 = ds.GeneratorDataset(dataset_generator,\n                              [\"data\", \"label\"])\n    model.train(epochs, ds1, callbacks=[rdp], dataset_sink_mode=False)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_dp_monitor_cpu():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    batch_size = 16\n    epochs = 1\n    rdp = PrivacyMonitorFactory.create(policy='rdp', num_samples=60000,\n                                       batch_size=batch_size,\n                                       initial_noise_multiplier=0.4,\n                                       noise_decay_rate=6e-3)\n    suggest_epoch = rdp.max_epoch_suggest()\n    LOGGER.info(TAG, 'The recommended maximum training epochs is: %s',\n                suggest_epoch)\n    network = Net()\n    net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction=\"mean\")\n    net_opt = nn.Momentum(network.trainable_params(), 0.01, 0.9)\n\n    model = Model(network, net_loss, net_opt)\n\n    LOGGER.info(TAG, \"============== Starting Training ==============\")\n    ds1 = ds.GeneratorDataset(dataset_generator,\n                              [\"data\", \"label\"])\n    model.train(epochs, ds1, callbacks=[rdp], dataset_sink_mode=False)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_dp_monitor_zcdp():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    batch_size = 16\n    epochs = 1\n    zcdp = PrivacyMonitorFactory.create(policy='zcdp', num_samples=60000,\n                                        batch_size=batch_size,\n                                        initial_noise_multiplier=0.4,\n                                        noise_decay_rate=6e-3)\n    suggest_epoch = zcdp.max_epoch_suggest()\n    LOGGER.info(TAG, 'The recommended maximum training epochs is: %s',\n                suggest_epoch)\n    network = Net()\n    net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction=\"mean\")\n    net_opt = nn.Momentum(network.trainable_params(), 0.01, 0.9)\n\n    model = Model(network, net_loss, net_opt)\n\n    LOGGER.info(TAG, \"============== Starting Training ==============\")\n    ds1 = ds.GeneratorDataset(dataset_generator,\n                              [\"data\", \"label\"])\n    model.train(epochs, ds1, callbacks=[zcdp], dataset_sink_mode=False)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_gpu_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_dp_monitor_zcdp_gpu():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"GPU\")\n    batch_size = 16\n    epochs = 1\n    zcdp = PrivacyMonitorFactory.create(policy='zcdp', num_samples=60000,\n                                        batch_size=batch_size,\n                                        initial_noise_multiplier=0.4,\n                                        noise_decay_rate=6e-3)\n    suggest_epoch = zcdp.max_epoch_suggest()\n    LOGGER.info(TAG, 'The recommended maximum training epochs is: %s',\n                suggest_epoch)\n    network = Net()\n    net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction=\"mean\")\n    net_opt = nn.Momentum(network.trainable_params(), 0.01, 0.9)\n\n    model = Model(network, net_loss, net_opt)\n\n    LOGGER.info(TAG, \"============== Starting Training ==============\")\n    ds1 = ds.GeneratorDataset(dataset_generator,\n                              [\"data\", \"label\"])\n    model.train(epochs, ds1, callbacks=[zcdp], dataset_sink_mode=False)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_dp_monitor_zcdp_cpu():\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")\n    batch_size = 16\n    epochs = 1\n    zcdp = PrivacyMonitorFactory.create(policy='zcdp', num_samples=60000,\n                                        batch_size=batch_size,\n                                        initial_noise_multiplier=0.4,\n                                        noise_decay_rate=6e-3)\n    suggest_epoch = zcdp.max_epoch_suggest()\n    LOGGER.info(TAG, 'The recommended maximum training epochs is: %s',\n                suggest_epoch)\n    network = Net()\n    net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction=\"mean\")\n    net_opt = nn.Momentum(network.trainable_params(), 0.01, 0.9)\n\n    model = Model(network, net_loss, net_opt)\n\n    LOGGER.info(TAG, \"============== Starting Training ==============\")\n    ds1 = ds.GeneratorDataset(dataset_generator,\n                              [\"data\", \"label\"])\n    model.train(epochs, ds1, callbacks=[zcdp], dataset_sink_mode=False)\n"
  },
  {
    "path": "tests/ut/python/privacy/diff_privacy/test_optimizer.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport pytest\n\nfrom mindspore import nn\nfrom mindspore import context\nfrom mindspore.train.model import Model\n\nfrom mindarmour.privacy.diff_privacy import DPOptimizerClassFactory\n\nfrom tests.ut.python.utils.mock_net import Net\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_optimizer():\n    context.set_context(mode=context.PYNATIVE_MODE, device_target=\"Ascend\")\n    network = Net()\n    lr = 0.01\n    momentum = 0.9\n    micro_batches = 2\n    loss = nn.SoftmaxCrossEntropyWithLogits()\n    factory = DPOptimizerClassFactory(micro_batches)\n    factory.set_mechanisms('Gaussian', norm_bound=1.5, initial_noise_multiplier=5.0)\n    net_opt = factory.create('SGD')(params=network.trainable_params(), learning_rate=lr,\n                                    momentum=momentum)\n    _ = Model(network, loss_fn=loss, optimizer=net_opt, metrics=None)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_gpu_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_optimizer_gpu():\n    context.set_context(mode=context.PYNATIVE_MODE, device_target=\"GPU\")\n    network = Net()\n    lr = 0.01\n    momentum = 0.9\n    micro_batches = 2\n    loss = nn.SoftmaxCrossEntropyWithLogits()\n    factory = DPOptimizerClassFactory(micro_batches)\n    factory.set_mechanisms('Gaussian', norm_bound=1.5, initial_noise_multiplier=5.0)\n    net_opt = factory.create('SGD')(params=network.trainable_params(), learning_rate=lr,\n                                    momentum=momentum)\n    _ = Model(network, loss_fn=loss, optimizer=net_opt, metrics=None)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_optimizer_cpu():\n    context.set_context(mode=context.PYNATIVE_MODE, device_target=\"CPU\")\n    network = Net()\n    lr = 0.01\n    momentum = 0.9\n    micro_batches = 2\n    loss = nn.SoftmaxCrossEntropyWithLogits()\n    factory = DPOptimizerClassFactory(micro_batches)\n    factory.set_mechanisms('Gaussian', norm_bound=1.5, initial_noise_multiplier=5.0)\n    net_opt = factory.create('SGD')(params=network.trainable_params(), learning_rate=lr,\n                                    momentum=momentum)\n    _ = Model(network, loss_fn=loss, optimizer=net_opt, metrics=None)\n"
  },
  {
    "path": "tests/ut/python/privacy/evaluation/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis package includes unit tests for privacy breach estimation.\n\"\"\"\n"
  },
  {
    "path": "tests/ut/python/privacy/evaluation/test_attacker.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nattacker test\n\"\"\"\nimport pytest\n\nimport numpy as np\n\nfrom mindarmour.privacy.evaluation.attacker import _get_attack_model\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_get_knn_model():\n    features = np.random.randint(0, 10, [100, 10])\n    labels = np.random.randint(0, 2, [100])\n    config_knn = {\n        \"method\": \"KNN\",\n        \"params\": {\n            \"n_neighbors\": [3, 5, 7],\n        }\n    }\n    knn_attacker = _get_attack_model(features, labels, config_knn, -1)\n    pred = knn_attacker.predict(features)\n    assert pred is not None\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_get_lr_model():\n    features = np.random.randint(0, 10, [100, 10])\n    labels = np.random.randint(0, 2, [100])\n    config_lr = {\n        \"method\": \"LR\",\n        \"params\": {\n            \"C\": np.logspace(-4, 2, 10),\n        }\n    }\n    lr_attacker = _get_attack_model(features, labels, config_lr, -1)\n    pred = lr_attacker.predict(features)\n    assert pred is not None\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_get_mlp_model():\n    features = np.random.randint(0, 10, [100, 10])\n    labels = np.random.randint(0, 2, [100])\n    config_mlpc = {\n        \"method\": \"MLP\",\n        \"params\": {\n            \"hidden_layer_sizes\": [(64,), (32, 32)],\n            \"solver\": [\"adam\"],\n            \"alpha\": [0.0001, 0.001, 0.01],\n        }\n    }\n    mlpc_attacker = _get_attack_model(features, labels, config_mlpc, -1)\n    pred = mlpc_attacker.predict(features)\n    assert pred is not None\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_get_rf_model():\n    features = np.random.randint(0, 10, [100, 10])\n    labels = np.random.randint(0, 2, [100])\n    config_rf = {\n        \"method\": \"RF\",\n        \"params\": {\n            \"n_estimators\": [100],\n            \"max_features\": [\"auto\", \"sqrt\"],\n            \"max_depth\": [None, 5, 10, 20],\n            \"min_samples_split\": [2, 5, 10],\n            \"min_samples_leaf\": [1, 2, 4],\n        }\n    }\n    rf_attacker = _get_attack_model(features, labels, config_rf, -1)\n    pred = rf_attacker.predict(features)\n    assert pred is not None\n"
  },
  {
    "path": "tests/ut/python/privacy/evaluation/test_inversion_attack.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nInversion attack test\n\"\"\"\nimport pytest\n\nimport numpy as np\n\nimport mindspore.context as context\n\nfrom mindarmour.privacy.evaluation.inversion_attack import ImageInversionAttack\n\nfrom tests.ut.python.utils.mock_net import Net\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_inversion_attack_graph():\n    context.set_context(mode=context.GRAPH_MODE)\n    net = Net()\n    original_images = np.random.random((2, 1, 32, 32)).astype(np.float32)\n    target_features = np.random.random((2, 10)).astype(np.float32)\n    inversion_attack = ImageInversionAttack(net, input_shape=(1, 32, 32), input_bound=(0, 1), loss_weights=[1, 0.2, 5])\n    inversion_images = inversion_attack.generate(target_features, iters=10)\n    avg_ssim = inversion_attack.evaluate(original_images, inversion_images)\n    assert 0 < avg_ssim[1] < 1\n    assert target_features.shape[0] == inversion_images.shape[0]\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_inversion_attack_pynative():\n    context.set_context(mode=context.PYNATIVE_MODE)\n    net = Net()\n    original_images = np.random.random((2, 1, 32, 32)).astype(np.float32)\n    target_features = np.random.random((2, 10)).astype(np.float32)\n    inversion_attack = ImageInversionAttack(net, input_shape=(1, 32, 32), input_bound=(0, 1), loss_weights=[1, 0.2, 5])\n    inversion_images = inversion_attack.generate(target_features, iters=10)\n    avg_ssim = inversion_attack.evaluate(original_images, inversion_images)\n    assert 0 < avg_ssim[1] < 1\n    assert target_features.shape[0] == inversion_images.shape[0]\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_inversion_attack_cpu():\n    context.set_context(device_target='CPU')\n    net = Net()\n    original_images = np.random.random((2, 1, 32, 32)).astype(np.float32)\n    target_features = np.random.random((2, 10)).astype(np.float32)\n    inversion_attack = ImageInversionAttack(net, input_shape=(1, 32, 32), input_bound=(0, 1), loss_weights=[1, 0.2, 5])\n    inversion_images = inversion_attack.generate(target_features, iters=10)\n    avg_ssim = inversion_attack.evaluate(original_images, inversion_images)\n    assert 0 < avg_ssim[1] < 1\n    assert target_features.shape[0] == inversion_images.shape[0]\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_inversion_attack2():\n    net = Net()\n    original_images = np.random.random((2, 1, 32, 32)).astype(np.float32)\n    target_features = np.random.random((2, 10)).astype(np.float32)\n    inversion_attack = ImageInversionAttack(net, input_shape=(1, 32, 32), input_bound=(0, 1), loss_weights=[1, 0.2, 5])\n    inversion_images = inversion_attack.generate(target_features, iters=10)\n    true_labels = np.array([1, 2])\n    new_net = Net()\n    indexes = inversion_attack.evaluate(original_images, inversion_images, true_labels, new_net)\n    assert len(indexes) == 3\n"
  },
  {
    "path": "tests/ut/python/privacy/evaluation/test_membership_inference.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nmembership inference test\n\"\"\"\nimport pytest\n\nimport numpy as np\n\nimport mindspore.dataset as ds\nfrom mindspore import nn\nfrom mindspore.train import Model\nimport mindspore.context as context\n\nfrom mindarmour.privacy.evaluation import MembershipInference\n\nfrom tests.ut.python.utils.mock_net import Net\n\n\ncontext.set_context(mode=context.GRAPH_MODE)\n\n\ndef dataset_generator():\n    \"\"\"mock training data.\"\"\"\n    batch_size = 16\n    batches = 1\n    data = np.random.randn(batches*batch_size, 1, 32, 32).astype(\n        np.float32)\n    label = np.random.randint(0, 10, batches*batch_size).astype(np.int32)\n    for i in range(batches):\n        yield data[i*batch_size:(i + 1)*batch_size],\\\n              label[i*batch_size:(i + 1)*batch_size]\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_get_membership_inference_object():\n    net = Net()\n    loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True)\n    opt = nn.Momentum(params=net.trainable_params(), learning_rate=0.1, momentum=0.9)\n    model = Model(network=net, loss_fn=loss, optimizer=opt)\n    inference_model = MembershipInference(model, -1)\n    assert isinstance(inference_model, MembershipInference)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_gpu_training\n@pytest.mark.platform_x86_cpu\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_membership_inference_object_train():\n    net = Net()\n    loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True)\n    opt = nn.Momentum(params=net.trainable_params(), learning_rate=0.1, momentum=0.9)\n    model = Model(network=net, loss_fn=loss, optimizer=opt)\n    inference_model = MembershipInference(model, 2)\n    assert isinstance(inference_model, MembershipInference)\n\n    config = [{\n        \"method\": \"KNN\",\n        \"params\": {\n            \"n_neighbors\": [3, 5, 7],\n        }\n    }]\n    ds_train = ds.GeneratorDataset(dataset_generator,\n                                   [\"image\", \"label\"])\n    ds_test = ds.GeneratorDataset(dataset_generator,\n                                  [\"image\", \"label\"])\n    inference_model.train(ds_train, ds_test, config)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.env_onecard\n@pytest.mark.component_mindarmour\ndef test_membership_inference_eval():\n    net = Net()\n    loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True)\n    opt = nn.Momentum(params=net.trainable_params(), learning_rate=0.1, momentum=0.9)\n    model = Model(network=net, loss_fn=loss, optimizer=opt)\n    inference_model = MembershipInference(model, -1)\n    assert isinstance(inference_model, MembershipInference)\n\n    eval_train = ds.GeneratorDataset(dataset_generator,\n                                     [\"image\", \"label\"])\n    eval_test = ds.GeneratorDataset(dataset_generator,\n                                    [\"image\", \"label\"])\n\n    metrics = [\"precision\", \"accuracy\", \"recall\"]\n    inference_model.eval(eval_train, eval_test, metrics)\n"
  },
  {
    "path": "tests/ut/python/privacy/sup_privacy/__init__.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis package includes unit tests for suppress-privacy training.\n\"\"\"\n"
  },
  {
    "path": "tests/ut/python/privacy/sup_privacy/test_model_train.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nSuppress Privacy model test.\n\"\"\"\nimport pytest\nimport numpy as np\n\nfrom mindspore import nn\nfrom mindspore import context\nfrom mindspore.train.callback import ModelCheckpoint\nfrom mindspore.train.callback import CheckpointConfig\nfrom mindspore.train.callback import LossMonitor\nfrom mindspore.nn.metrics import Accuracy\nimport mindspore.dataset as ds\n\nfrom mindarmour.privacy.sup_privacy import SuppressModel\nfrom mindarmour.privacy.sup_privacy import SuppressMasker\nfrom mindarmour.privacy.sup_privacy import SuppressPrivacyFactory\nfrom mindarmour.privacy.sup_privacy import MaskLayerDes\n\nfrom tests.ut.python.utils.mock_net import Net as LeNet5\n\n\ndef dataset_generator():\n    \"\"\"mock training data.\"\"\"\n    batches = 10\n    batch_size = 32\n    data = np.random.random((batches*batch_size, 1, 32, 32)).astype(\n        np.float32)\n    label = np.random.randint(0, 10, batches*batch_size).astype(np.int32)\n    for i in range(batches):\n        yield data[i*batch_size:(i + 1)*batch_size],\\\n              label[i*batch_size:(i + 1)*batch_size]\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_suppress_model_with_pynative_mode():\n    context.set_context(mode=context.PYNATIVE_MODE, device_target=\"Ascend\")\n    networks_l5 = LeNet5()\n    epochs = 5\n    batch_num = 10\n    mask_times = 10\n    lr = 0.01\n    masklayers_lenet5 = []\n    masklayers_lenet5.append(MaskLayerDes(\"conv1.weight\", 0, False, False, -1))\n    suppress_ctrl_instance = SuppressPrivacyFactory().create(networks_l5,\n                                                             masklayers_lenet5,\n                                                             policy=\"local_train\",\n                                                             end_epoch=epochs,\n                                                             batch_num=batch_num,\n                                                             start_epoch=1,\n                                                             mask_times=mask_times,\n                                                             lr=lr,\n                                                             sparse_end=0.50,\n                                                             sparse_start=0.0)\n    net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction=\"mean\")\n    net_opt = nn.SGD(networks_l5.trainable_params(), lr)\n    model_instance = SuppressModel(\n        network=networks_l5,\n        loss_fn=net_loss,\n        optimizer=net_opt,\n        metrics={\"Accuracy\": Accuracy()})\n    model_instance.link_suppress_ctrl(suppress_ctrl_instance)\n    suppress_masker = SuppressMasker(model=model_instance, suppress_ctrl=suppress_ctrl_instance)\n    config_ck = CheckpointConfig(save_checkpoint_steps=batch_num, keep_checkpoint_max=10)\n    ckpoint_cb = ModelCheckpoint(prefix=\"checkpoint_lenet\",\n                                 directory=\"./trained_ckpt_file/\",\n                                 config=config_ck)\n    ds_train = ds.GeneratorDataset(dataset_generator, ['data', 'label'])\n\n    model_instance.train(epochs, ds_train, callbacks=[ckpoint_cb, LossMonitor(), suppress_masker],\n                         dataset_sink_mode=False)\n"
  },
  {
    "path": "tests/ut/python/reliability/concept_drift/test_concept_drift_images.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"\nConcept drift test for images.\n\"\"\"\n\nimport os\nimport logging\nimport pytest\nimport numpy as np\nfrom mindarmour.utils.logger import LogUtil\nfrom mindarmour.reliability.concept_drift.concept_drift_check_images import OodDetectorFeatureCluster\nfrom mindspore import Model, context\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\nfrom examples.common.networks.lenet5.lenet5_net_for_fuzzing import LeNet5\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Concept_Test'\n\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_concept_drift_image_ascend():\n    \"\"\"\n    Feature: test concept drift with images\n    Description: make sure the odd detector working properly\n    Expectation: assert np.any(result >=0.0)\n    \"\"\"\n    # load model\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    cur_path = os.path.abspath(os.path.dirname(__file__))\n    ckpt_path = '../../dataset/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\n    ckpt_path = os.path.join(cur_path, ckpt_path)\n    net = LeNet5()\n    load_dict = load_checkpoint(ckpt_path)\n    load_param_into_net(net, load_dict)\n    model = Model(net)\n    # load data\n    ds_train = np.load(os.path.join(cur_path, '../../dataset/concept_train_lenet.npy'))\n    ds_eval = np.load(os.path.join(cur_path, '../../dataset/concept_test_lenet1.npy'))\n    ds_test = np.load(os.path.join(cur_path, '../../dataset/concept_test_lenet2.npy'))\n    # ood detector initialization\n    detector = OodDetectorFeatureCluster(model, ds_train, n_cluster=10, layer='output[:Tensor]')\n    # get optimal threshold with ds_eval\n    num = int(len(ds_eval) / 2)\n    label = np.concatenate((np.zeros(num), np.ones(num)), axis=0)  # ID data = 0, OOD data = 1\n    optimal_threshold = detector.get_optimal_threshold(label, ds_eval)\n    # get result of ds_test. We can also set threshold by ourselves.\n    result = detector.ood_predict(optimal_threshold, ds_test)\n    # result log\n    LOGGER.set_level(logging.DEBUG)\n    LOGGER.debug(TAG, '--start ood test--')\n    LOGGER.debug(result, '--ood result--')\n    LOGGER.debug(optimal_threshold, '--the optimal threshold--')\n    LOGGER.debug(TAG, '--end ood test--')\n    assert np.any(result >= 0.0)\n"
  },
  {
    "path": "tests/ut/python/reliability/concept_drift/test_concept_drift_time_series.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"\nConcept drift test.\n\"\"\"\n\n\nimport logging\nimport pytest\nimport numpy as np\nfrom mindspore import context\nfrom mindarmour import ConceptDriftCheckTimeSeries\nfrom mindarmour.utils.logger import LogUtil\n\nLOGGER = LogUtil.get_instance()\nTAG = 'Concept_Test'\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_concept_drift_time_series_ascend():\n    \"\"\"\n    Feature: test concept drift with time series data\n    Description: make sure the odd detector working properly\n    Expectation: assert np.any(result >=0.0)\n    \"\"\"\n    context.set_context(mode=context.GRAPH_MODE, device_target=\"Ascend\")\n    # create data\n    data = 5*np.random.rand(1000)\n    data[200: 800] = 50*np.random.rand(600)\n    # initialization\n    concept = ConceptDriftCheckTimeSeries(window_size=100, rolling_window=10,\n                                          step=10, threshold_index=1.5, need_label=False)\n    # drift check\n    drift_score, threshold, concept_drift_location = concept.concept_check(data)\n    LOGGER.set_level(logging.DEBUG)\n    LOGGER.debug(TAG, '--start concept drift test--')\n    LOGGER.debug(threshold, '--concept drift threshold--')\n    LOGGER.debug(concept_drift_location, '--concept drift location--')\n    LOGGER.debug(TAG, '--end concept drift test--')\n    assert np.any(drift_score >= 0.0)\n"
  },
  {
    "path": "tests/ut/python/reliability/model_fault_injection/test_fault_injection.py",
    "content": "# Copyright 2021 Huawei Technologies Co., Ltd\r\n#\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n#\r\n# http://www.apache.org/licenses/LICENSE-2.0\r\n#\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n\r\n\"\"\"\r\nTest for fault injection.\r\n\"\"\"\r\n\r\nimport os\r\nimport pytest\r\nimport numpy as np\r\n\r\nfrom mindspore import Model\r\nimport mindspore.dataset as ds\r\nfrom mindspore.train.serialization import load_checkpoint, load_param_into_net\r\n\r\nfrom mindarmour.utils.logger import LogUtil\r\nfrom mindarmour.reliability.model_fault_injection.fault_injection import FaultInjector\r\n\r\nfrom tests.ut.python.utils.mock_net import Net\r\n\r\nLOGGER = LogUtil.get_instance()\r\nTAG = 'Fault injection test'\r\nLOGGER.set_level('INFO')\r\n\r\n\r\ndef dataset_generator():\r\n    \"\"\"mock training data.\"\"\"\r\n    batch_size = 32\r\n    batches = 128\r\n    data = np.random.random((batches * batch_size, 1, 32, 32)).astype(\r\n        np.float32)\r\n    label = np.random.randint(0, 10, batches * batch_size).astype(np.int32)\r\n    for i in range(batches):\r\n        yield data[i * batch_size:(i + 1) * batch_size], \\\r\n              label[i * batch_size:(i + 1) * batch_size]\r\n\r\n\r\n@pytest.mark.level0\r\n@pytest.mark.platform_x86_cpu\r\n@pytest.mark.platform_x86_ascend_training\r\n@pytest.mark.platform_arm_ascend_training\r\n@pytest.mark.env_onecard\r\n@pytest.mark.component_mindarmour\r\ndef test_fault_injector():\r\n    \"\"\"\r\n    Feature: Fault injector\r\n    Description: Test fault injector\r\n    Expectation: Run kick_off and metrics successfully\r\n    \"\"\"\r\n    # load model\r\n    cur_path = os.path.abspath(os.path.dirname(__file__))\r\n    ckpt_path = '../../dataset/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\r\n    ckpt_path = os.path.join(cur_path, ckpt_path)\r\n    net = Net()\r\n    param_dict = load_checkpoint(ckpt_path)\r\n    load_param_into_net(net, param_dict)\r\n    model = Model(net)\r\n\r\n    ds_eval = ds.GeneratorDataset(dataset_generator, ['image', 'label'])\r\n    test_images = []\r\n    test_labels = []\r\n    for data in ds_eval.create_tuple_iterator(output_numpy=True):\r\n        images = data[0].astype(np.float32)\r\n        labels = data[1]\r\n        test_images.append(images)\r\n        test_labels.append(labels)\r\n    ds_data = np.concatenate(test_images, axis=0)\r\n    ds_label = np.concatenate(test_labels, axis=0)\r\n    fi_type = ['bitflips_random', 'bitflips_designated', 'random', 'zeros',\r\n               'nan', 'inf', 'anti_activation', 'precision_loss']\r\n    fi_mode = ['single_layer', 'all_layer']\r\n    fi_size = [1]\r\n\r\n    # Fault injection\r\n    fi = FaultInjector(model, fi_type, fi_mode, fi_size)\r\n    _ = fi.kick_off(ds_data, ds_label, iter_times=100)\r\n    _ = fi.metrics()\r\n\r\n\r\n@pytest.mark.level0\r\n@pytest.mark.platform_x86_cpu\r\n@pytest.mark.platform_x86_ascend_training\r\n@pytest.mark.platform_arm_ascend_training\r\n@pytest.mark.env_onecard\r\n@pytest.mark.component_mindarmour\r\ndef test_wrong_model():\r\n    \"\"\"\r\n    Feature: Fault injector\r\n    Description: Test fault injector\r\n    Expectation: Throw TypeError exception\r\n    \"\"\"\r\n    # load model\r\n    cur_path = os.path.abspath(os.path.dirname(__file__))\r\n    ckpt_path = '../../dataset/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\r\n    ckpt_path = os.path.join(cur_path, ckpt_path)\r\n    net = Net()\r\n    param_dict = load_checkpoint(ckpt_path)\r\n    load_param_into_net(net, param_dict)\r\n\r\n    ds_eval = ds.GeneratorDataset(dataset_generator, ['image', 'label'])\r\n    test_images = []\r\n    test_labels = []\r\n    for data in ds_eval.create_tuple_iterator(output_numpy=True):\r\n        images = data[0].astype(np.float32)\r\n        labels = data[1]\r\n        test_images.append(images)\r\n        test_labels.append(labels)\r\n    ds_data = np.concatenate(test_images, axis=0)\r\n    ds_label = np.concatenate(test_labels, axis=0)\r\n    fi_type = ['bitflips_random', 'bitflips_designated', 'random', 'zeros',\r\n               'nan', 'inf', 'anti_activation', 'precision_loss']\r\n    fi_mode = ['single_layer', 'all_layer']\r\n    fi_size = [1]\r\n\r\n    # Fault injection\r\n    with pytest.raises(TypeError) as exc_info:\r\n        fi = FaultInjector(net, fi_type, fi_mode, fi_size)\r\n        _ = fi.kick_off(ds_data, ds_label, iter_times=100)\r\n        _ = fi.metrics()\r\n    assert exc_info.type is TypeError\r\n\r\n\r\n@pytest.mark.level0\r\n@pytest.mark.platform_x86_cpu\r\n@pytest.mark.platform_x86_ascend_training\r\n@pytest.mark.platform_arm_ascend_training\r\n@pytest.mark.env_onecard\r\n@pytest.mark.component_mindarmour\r\ndef test_wrong_data():\r\n    \"\"\"\r\n    Feature: Fault injector\r\n    Description: Test fault injector\r\n    Expectation: Throw TypeError exception\r\n    \"\"\"\r\n    # load model\r\n    cur_path = os.path.abspath(os.path.dirname(__file__))\r\n    ckpt_path = '../../dataset/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\r\n    ckpt_path = os.path.join(cur_path, ckpt_path)\r\n    net = Net()\r\n    param_dict = load_checkpoint(ckpt_path)\r\n    load_param_into_net(net, param_dict)\r\n    model = Model(net)\r\n\r\n    ds_data = ds.GeneratorDataset(dataset_generator, ['image', 'label'])\r\n    ds_label = ds.GeneratorDataset(dataset_generator, ['image', 'label'])\r\n    fi_type = ['bitflips_random', 'bitflips_designated', 'random', 'zeros',\r\n               'nan', 'inf', 'anti_activation', 'precision_loss']\r\n    fi_mode = ['single_layer', 'all_layer']\r\n    fi_size = [1]\r\n\r\n    # Fault injection\r\n    with pytest.raises(TypeError) as exc_info:\r\n        fi = FaultInjector(model, fi_type, fi_mode, fi_size)\r\n        _ = fi.kick_off(ds_data, ds_label, iter_times=100)\r\n        _ = fi.metrics()\r\n    assert exc_info.type is TypeError\r\n\r\n\r\n@pytest.mark.level0\r\n@pytest.mark.platform_x86_cpu\r\n@pytest.mark.platform_x86_ascend_training\r\n@pytest.mark.platform_arm_ascend_training\r\n@pytest.mark.env_onecard\r\n@pytest.mark.component_mindarmour\r\ndef test_wrong_fi_type():\r\n    \"\"\"\r\n    Feature: Fault injector\r\n    Description: Test fault injector\r\n    Expectation: Throw AttributeError exception\r\n    \"\"\"\r\n    # load model\r\n    cur_path = os.path.abspath(os.path.dirname(__file__))\r\n    ckpt_path = '../../dataset/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\r\n    ckpt_path = os.path.join(cur_path, ckpt_path)\r\n    net = Net()\r\n    param_dict = load_checkpoint(ckpt_path)\r\n    load_param_into_net(net, param_dict)\r\n    model = Model(net)\r\n\r\n    ds_eval = ds.GeneratorDataset(dataset_generator, ['image', 'label'])\r\n    test_images = []\r\n    test_labels = []\r\n    for data in ds_eval.create_tuple_iterator(output_numpy=True):\r\n        images = data[0].astype(np.float32)\r\n        labels = data[1]\r\n        test_images.append(images)\r\n        test_labels.append(labels)\r\n    ds_data = np.concatenate(test_images, axis=0)\r\n    ds_label = np.concatenate(test_labels, axis=0)\r\n    fi_type = ['bitflips_random_haha', 'bitflips_designated', 'random', 'zeros',\r\n               'nan', 'inf', 'anti_activation', 'precision_loss']\r\n    fi_mode = ['single_layer', 'all_layer']\r\n    fi_size = [1]\r\n\r\n    # Fault injection\r\n    with pytest.raises(ValueError) as exc_info:\r\n        fi = FaultInjector(model, fi_type, fi_mode, fi_size)\r\n        _ = fi.kick_off(ds_data, ds_label, iter_times=100)\r\n        _ = fi.metrics()\r\n    assert exc_info.type is ValueError\r\n\r\n\r\n@pytest.mark.level0\r\n@pytest.mark.platform_x86_cpu\r\n@pytest.mark.platform_x86_ascend_training\r\n@pytest.mark.platform_arm_ascend_training\r\n@pytest.mark.env_onecard\r\n@pytest.mark.component_mindarmour\r\ndef test_wrong_fi_mode():\r\n    \"\"\"\r\n    Feature: Fault injector\r\n    Description: Test fault injector\r\n    Expectation: Throw ValueError exception\r\n    \"\"\"\r\n    # load model\r\n    cur_path = os.path.abspath(os.path.dirname(__file__))\r\n    ckpt_path = '../../dataset/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\r\n    ckpt_path = os.path.join(cur_path, ckpt_path)\r\n    net = Net()\r\n    param_dict = load_checkpoint(ckpt_path)\r\n    load_param_into_net(net, param_dict)\r\n    model = Model(net)\r\n\r\n    ds_eval = ds.GeneratorDataset(dataset_generator, ['image', 'label'])\r\n    test_images = []\r\n    test_labels = []\r\n    for data in ds_eval.create_tuple_iterator(output_numpy=True):\r\n        images = data[0].astype(np.float32)\r\n        labels = data[1]\r\n        test_images.append(images)\r\n        test_labels.append(labels)\r\n    ds_data = np.concatenate(test_images, axis=0)\r\n    ds_label = np.concatenate(test_labels, axis=0)\r\n    fi_type = ['bitflips_random', 'bitflips_designated', 'random', 'zeros',\r\n               'nan', 'inf', 'anti_activation', 'precision_loss']\r\n    fi_mode = ['single_layer_tail', 'all_layer']\r\n    fi_size = [1]\r\n\r\n    # Fault injection\r\n    with pytest.raises(ValueError) as exc_info:\r\n        fi = FaultInjector(model, fi_type, fi_mode, fi_size)\r\n        _ = fi.kick_off(ds_data, ds_label, iter_times=100)\r\n        _ = fi.metrics()\r\n    assert exc_info.type is ValueError\r\n\r\n\r\n@pytest.mark.level0\r\n@pytest.mark.platform_x86_cpu\r\n@pytest.mark.platform_x86_ascend_training\r\n@pytest.mark.platform_arm_ascend_training\r\n@pytest.mark.env_onecard\r\n@pytest.mark.component_mindarmour\r\ndef test_wrong_fi_size():\r\n    \"\"\"\r\n    Feature: Fault injector\r\n    Description: Test fault injector\r\n    Expectation: Throw ValueError exception\r\n    \"\"\"\r\n    # load model\r\n    cur_path = os.path.abspath(os.path.dirname(__file__))\r\n    ckpt_path = '../../dataset/trained_ckpt_file/checkpoint_lenet-10_1875.ckpt'\r\n    ckpt_path = os.path.join(cur_path, ckpt_path)\r\n    net = Net()\r\n    param_dict = load_checkpoint(ckpt_path)\r\n    load_param_into_net(net, param_dict)\r\n    model = Model(net)\r\n\r\n    ds_eval = ds.GeneratorDataset(dataset_generator, ['image', 'label'])\r\n    test_images = []\r\n    test_labels = []\r\n    for data in ds_eval.create_tuple_iterator(output_numpy=True):\r\n        images = data[0].astype(np.float32)\r\n        labels = data[1]\r\n        test_images.append(images)\r\n        test_labels.append(labels)\r\n    ds_data = np.concatenate(test_images, axis=0)\r\n    ds_label = np.concatenate(test_labels, axis=0)\r\n\r\n    fi_type = ['bitflips_random', 'bitflips_designated', 'random', 'zeros',\r\n               'nan', 'inf', 'anti_activation', 'precision_loss']\r\n    fi_mode = ['single_layer', 'all_layer']\r\n    fi_size = [-1]\r\n\r\n    # Fault injection\r\n    with pytest.raises(ValueError) as exc_info:\r\n        fi = FaultInjector(model, fi_type, fi_mode, fi_size)\r\n        _ = fi.kick_off(ds_data, ds_label, iter_times=100)\r\n        _ = fi.metrics()\r\n    assert exc_info.type is ValueError\r\n"
  },
  {
    "path": "tests/ut/python/utils/__init__.py",
    "content": "# Copyright 2020 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis package includes common methods called by unit tests.\n\"\"\"\n"
  },
  {
    "path": "tests/ut/python/utils/mock_net.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nmocked model for UT of defense algorithms.\n\"\"\"\nfrom mindspore import nn\nfrom mindspore.common.initializer import TruncatedNormal\n\n\ndef conv(in_channels, out_channels, kernel_size, stride=1, padding=0):\n    weight = weight_variable()\n    return nn.Conv2d(in_channels, out_channels,\n                     kernel_size=kernel_size, stride=stride, padding=padding,\n                     weight_init=weight, has_bias=False, pad_mode=\"valid\")\n\n\ndef fc_with_initialize(input_channels, out_channels):\n    weight = weight_variable()\n    bias = weight_variable()\n    return nn.Dense(input_channels, out_channels, weight, bias)\n\n\ndef weight_variable():\n    return TruncatedNormal(0.02)\n\n\nclass Net(nn.Cell):\n    \"\"\"\n    Lenet network\n    \"\"\"\n    def __init__(self):\n        super(Net, self).__init__()\n        self.conv1 = conv(1, 6, 5)\n        self.conv2 = conv(6, 16, 5)\n        self.fc1 = fc_with_initialize(16*5*5, 120)\n        self.fc2 = fc_with_initialize(120, 84)\n        self.fc3 = fc_with_initialize(84, 10)\n        self.relu = nn.ReLU()\n        self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.flatten = nn.Flatten()\n\n    def construct(self, x):\n        x = self.conv1(x)\n        x = self.relu(x)\n        x = self.max_pool2d(x)\n        x = self.conv2(x)\n        x = self.relu(x)\n        x = self.max_pool2d(x)\n        x = self.flatten(x)\n        x = self.fc1(x)\n        x = self.relu(x)\n        x = self.fc2(x)\n        x = self.relu(x)\n        x = self.fc3(x)\n        return x\n"
  },
  {
    "path": "tests/ut/python/utils/test_log_util.py",
    "content": "# Copyright 2019 Huawei Technologies Co., Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nLogUtil test.\n\"\"\"\nimport logging\nimport pytest\n\nfrom mindarmour.utils.logger import LogUtil\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_logger():\n    logger = LogUtil.get_instance()\n    tag = 'Test'\n    msg = 'i am %s, work in %s'\n    args = ('tom', 'china')\n    logger.debug(tag, msg, *args)\n    logger.info(tag, msg, *args)\n    logger.error(tag, msg, *args)\n    logger.warn(tag, msg, *args)\n\n    logger.set_level(logging.DEBUG)\n\n    logger.debug(tag, msg, *args)\n    logger.info(tag, msg, *args)\n    logger.error(tag, msg, *args)\n    logger.warn(tag, msg, *args)\n\n    msg = 'i am tom, work in china'\n    logger.info(tag, msg)\n\n    logger.info(tag, 'accuracy is %f.', 0.995)\n    logger.debug(tag, 'accuracy is %s.', 0.995)\n\n\n@pytest.mark.level0\n@pytest.mark.platform_arm_ascend_training\n@pytest.mark.platform_x86_ascend_training\n@pytest.mark.env_card\n@pytest.mark.component_mindarmour\ndef test_value_error():\n    with pytest.raises(SyntaxError) as e:\n        assert LogUtil()\n    assert str(e.value) == 'can not instance, please use get_instance.'\n    logger = LogUtil.get_instance()\n    handler = 'logging.Handler(level=1)'\n    with pytest.raises(ValueError):\n        logger.add_handler(handler)\n"
  }
]