diff --git a/.gitignore b/.gitignore index eb9945b84cde66156884911642cfbb850b2d5e67..8783101f09c1492fa57bc7373459e850cac06121 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,9 @@ /test/ut/retiarii/_debug_graph_data.json /test/ut/retiarii/out.tmp +# example generated files +/nni_assets/**/data/ + # Logs logs *.log diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 6ce61868689091e8231f0c697bd1fa4a1ab12ee7..0000000000000000000000000000000000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,68 +0,0 @@ -# Contributing to NNI - -Welcome, and thank you for your interest in contributing to NNI! - -There are many ways in which you can contribute, beyond writing code. The goal of this document is to provide a high-level overview of how you can get involved. - -# Provide feedback or ask a question - -* [File an issue](https://github.com/microsoft/nni/issues/new/choose) on GitHub. -* Ask a question with NNI tags on [Stack Overflow](https://stackoverflow.com/questions/tagged/nni?sort=Newest&edited=true). -* Discuss on the NNI [Gitter](https://gitter.im/Microsoft/nni?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) in NNI. - -Join IM discussion groups: -|Gitter||WeChat| -|----|----|----| -|![image](https://user-images.githubusercontent.com/39592018/80665738-e0574a80-8acc-11ea-91bc-0836dc4cbf89.png)| OR |![image](https://github.com/scarlett2018/nniutil/raw/master/wechat.png)| - - -# Look for an existing issue -Before you create a new issue, please do a search in [open issues](https://github.com/microsoft/nni/issues) to see if the issue or feature request has already been filed. - -Be sure to scan through the [most popular](https://github.com/microsoft/nni/issues?q=is%3Aopen+is%3Aissue+label%3AFAQ+sort%3Areactions-%2B1-desc) feature requests. - -If you find your issue already exists, make relevant comments and add your [reaction](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments). Use a reaction in place of a "+1" comment: - -* 👍 - upvote -* 👎 - downvote - -If you cannot find an existing issue that describes your bug or feature, create a new issue using the guidelines below. - -# Writing good bug reports or feature requests -File a single issue per problem and feature request. Do not enumerate multiple bugs or feature requests in the same issue. - -Provide as much information as you think might relevant to the context (thinking the issue is assigning to you, what kinds of info you will need to debug it!!!). To give you a general idea about what kinds of info are useful for developers to dig out the issue, we had provided issue template for you. - -Once you had submitted an issue, be sure to follow it for questions and discussions. - -Once the bug is fixed or feature is addressed, be sure to close the issue. - -# Contributing fixes or examples - -This project welcomes contributions and suggestions. Most contributions require you to agree to a -Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us -the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. - -When you submit a pull request, a CLA bot will automatically determine whether you need to provide -a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions -provided by the bot. You will only need to do this once across all repos using our CLA. - -# Code of Conduct - -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). -For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or -contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. - -# How to Contribute - -After getting familiar with contribution agreements, you are ready to create your first PR =), follow the NNI developer tutorials to get start: - -* We recommend new contributors to start with simple issues: ['good first issue'](https://github.com/Microsoft/nni/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) or ['help-wanted'](https://github.com/microsoft/nni/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22). -* [NNI developer environment installation tutorial](docs/en_US/Tutorial/SetupNniDeveloperEnvironment.rst) -* [How to debug](docs/en_US/Tutorial/HowToDebug.rst) -* If you have any questions on usage, review [FAQ](https://github.com/microsoft/nni/blob/master/docs/en_US/Tutorial/FAQ.rst) first, if there are no relevant issues and answers to your question, try contact NNI dev team and users in [Gitter](https://gitter.im/Microsoft/nni?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) or [File an issue](https://github.com/microsoft/nni/issues/new/choose) on GitHub. -* [Customize your own Tuner](docs/en_US/Tuner/CustomizeTuner.rst) -* [Implement customized TrainingService](docs/en_US/TrainingService/HowToImplementTrainingService.rst) -* [Implement a new NAS trainer on NNI](docs/en_US/NAS/Advanced.rst) -* [Customize your own Advisor](docs/en_US/Tuner/CustomizeAdvisor.rst) - diff --git a/CONTRIBUTING_zh_CN.md b/CONTRIBUTING_zh_CN.md deleted file mode 100644 index 1626a8524e2c98bfa5957c326a22fcce00b1fcdb..0000000000000000000000000000000000000000 --- a/CONTRIBUTING_zh_CN.md +++ /dev/null @@ -1,62 +0,0 @@ -# 贡献代码 - -非常感谢您有兴趣对 NNI 做出贡献! - -除了编写代码外,您还可以通过多种方式参与, 本文档的目的是提供一个如何参与贡献的高层次概述。 - -# 反馈或提问 - -* 在 Github 上创建 [issue](https://github.com/microsoft/nni/issues/new/choose)。 -* 在 [Stack Overflow](https://stackoverflow.com/questions/tagged/nni?sort=Newest&edited=true) 上使用 nni 标签提问。 -* 在 [Gitter](https://gitter.im/Microsoft/nni?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 中参与讨论。 - -加入聊天组: -| Gitter | | 微信 | -| -------------------------------------------------------------------------------------------------------------- | - | ----------------------------------------------------------------------- | -| ![image](https://user-images.githubusercontent.com/39592018/80665738-e0574a80-8acc-11ea-91bc-0836dc4cbf89.png) | 或 | ![image](https://github.com/scarlett2018/nniutil/raw/master/wechat.png) | - - -# 查找现有问题 -在创建新 issue 之前,请在 [open issues](https://github.com/microsoft/nni/issues) 中进行搜索,以查看问题或功能请求是否已经存在。 - -确保已经浏览了 [最热门](https://github.com/microsoft/nni/issues?q=is%3Aopen+is%3Aissue+label%3AFAQ+sort%3Areactions-%2B1-desc) 的功能请求。 - -如果您的问题已经存在,请在下方发表评论或添加[回应](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments)。 通过回应来代替“+1”评论: - -* 👍 - 赞成 -* 👎 - 反对 - -如果未能找到描述您 Bug 或功能的现有问题,请使用以下指南创建一个新问题。 - -# 编写良好的错误报告或功能请求 -针对每个错误和功能请求提交一个问题, 不要在同一问题中列举多个 Bug 或功能请求。 - -尽可能多地提供您认为与上下文相关的信息(思考问题如果分配给您,您需要什么样的信息来调试它)。 为了让您大致了解哪些信息对开发人员解决问题有帮助,我们为您提供了问题模板。 - -提交问题后,请务必跟进问题并参与讨论。 - -修正 Bug 或实现功能后,请务必关闭此问题。 - -# 贡献修复或示例 - -此项目欢迎任何贡献和建议。 大多数贡献需要您同意参与者许可协议(CLA),来声明您有权并授予我们使用您贡献的权利。 有关详细信息,请访问 https://cla.opensource.microsoft.com。 - -当你提交拉取请求时,CLA 机器人会自动检查你是否需要提供 CLA,并修饰这个拉取请求(例如标签、注释等)。 只需要按照机器人提供的说明进行操作即可。 CLA 只需要同意一次,就能应用到所有的代码仓库上。 - -# 行为准则 - -该项目采用了 [ Microsoft 开源行为准则 ](https://opensource.microsoft.com/codeofconduct/)。 有关详细信息,请参阅[行为守则常见问题解答](https://opensource.microsoft.com/codeofconduct/faq/)或联系 opencode@microsoft.com 咨询问题或评论。 - -# 参与贡献 - -熟悉贡献协议后,即可按照 NNI 开发人员教程,创建第一个 PR =): - -* 推荐新贡献者先从简单的问题开始:['good first issue'](https://github.com/Microsoft/nni/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) 或 ['help-wanted'](https://github.com/microsoft/nni/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)。 -* [NNI 开发环境安装教程](docs/zh_CN/Tutorial/SetupNniDeveloperEnvironment.rst) -* [如何调试](docs/zh_CN/Tutorial/HowToDebug.rst) -* 如果有使用上的问题,可先查看[常见问题解答](https://github.com/microsoft/nni/blob/master/docs/zh_CN/Tutorial/FAQ.rst)。如果没能解决问题,可通过 [Gitter](https://gitter.im/Microsoft/nni?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 联系 NNI 开发团队或在 GitHub 上 [报告问题](https://github.com/microsoft/nni/issues/new/choose)。 -* [自定义 Tuner](docs/zh_CN/Tuner/CustomizeTuner.rst) -* [实现定制的训练平台](docs/zh_CN/TrainingService/HowToImplementTrainingService.rst) -* [在 NNI 上实现新的 NAS Trainer](docs/zh_CN/NAS/Advanced.rst) -* [自定义 Advisor](docs/zh_CN/Tuner/CustomizeAdvisor.rst) - diff --git a/README.md b/README.md index b17838c96a3b3484ee531aa3605c1b539d704b3e..3be82e3eb302bc6c668dbf78abe820c5e1458045 100644 --- a/README.md +++ b/README.md @@ -1,332 +1,245 @@ -

- -

+
+ +
+ +
[![MIT licensed](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE) -[![Build Status](https://msrasrg.visualstudio.com/NNIOpenSource/_apis/build/status/full%20test%20-%20linux?branchName=master)](https://msrasrg.visualstudio.com/NNIOpenSource/_build/latest?definitionId=62&branchName=master) [![Issues](https://img.shields.io/github/issues-raw/Microsoft/nni.svg)](https://github.com/Microsoft/nni/issues?q=is%3Aissue+is%3Aopen) [![Bugs](https://img.shields.io/github/issues/Microsoft/nni/bug.svg)](https://github.com/Microsoft/nni/issues?q=is%3Aissue+is%3Aopen+label%3Abug) [![Pull Requests](https://img.shields.io/github/issues-pr-raw/Microsoft/nni.svg)](https://github.com/Microsoft/nni/pulls?q=is%3Apr+is%3Aopen) -[![Version](https://img.shields.io/github/release/Microsoft/nni.svg)](https://github.com/Microsoft/nni/releases) [![Join the chat at https://gitter.im/Microsoft/nni](https://badges.gitter.im/Microsoft/nni.svg)](https://gitter.im/Microsoft/nni?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Version](https://img.shields.io/github/release/Microsoft/nni.svg)](https://github.com/Microsoft/nni/releases) [![Documentation Status](https://readthedocs.org/projects/nni/badge/?version=stable)](https://nni.readthedocs.io/en/stable/?badge=stable) +[![](https://img.shields.io/github/contributors-anon/microsoft/nni)](https://github.com/microsoft/nni/graphs/contributors) -[NNI Doc](https://nni.readthedocs.io/) | [简体中文](README_zh_CN.md) - -**NNI (Neural Network Intelligence)** is a lightweight but powerful toolkit to help users **automate** Feature Engineering, Neural Architecture Search, Hyperparameter Tuning and Model Compression. -The tool manages automated machine learning (AutoML) experiments, **dispatches and runs** experiments' trial jobs generated by tuning algorithms to search the best neural architecture and/or hyper-parameters in **different training environments** like Local Machine, Remote Servers, OpenPAI, Kubeflow, FrameworkController on K8S (AKS etc.), DLWorkspace (aka. DLTS), AML (Azure Machine Learning), AdaptDL (aka. ADL) , other cloud options and even Hybrid mode. -## **Who should consider using NNI** +[](https://nni.readthedocs.io/) -* Those who want to **try different AutoML algorithms** in their training code/model. -* Those who want to run AutoML trial jobs **in different environments** to speed up search. -* Researchers and data scientists who want to easily **implement and experiment new AutoML algorithms**, may it be: hyperparameter tuning algorithm, neural architect search algorithm or model compression algorithm. -* ML Platform owners who want to **support AutoML in their platform**. +NNI automates feature engineering, neural architecture search, hyperparameter tuning, and model compression for deep learning. Find the latest features, API, examples and tutorials in our **[official documentation](https://nni.readthedocs.io/) ([简体中文版点这里](https://nni.readthedocs.io/zh/stable))**. -## **What's NEW!**   +## What's NEW!   -* **New release**: [v2.6 is available](https://github.com/microsoft/nni/releases/tag/v2.6) - _released on Jan-19-2022_ -* **New demo available**: [Youtube entry](https://www.youtube.com/channel/UCKcafm6861B2mnYhPbZHavw) | [Bilibili 入口](https://space.bilibili.com/1649051673) - _last updated on May-26-2021_ +* **New release**: [v2.7 is available](https://github.com/microsoft/nni/releases/tag/v2.7) - _released on Apr-18-2022_ +* **New demo available**: [Youtube entry](https://www.youtube.com/channel/UCKcafm6861B2mnYhPbZHavw) | [Bilibili 入口](https://space.bilibili.com/1649051673) - _last updated on Apr-18-2022_ * **New webinar**: [Introducing Retiarii: A deep learning exploratory-training framework on NNI](https://note.microsoft.com/MSR-Webinar-Retiarii-Registration-Live.html) - _scheduled on June-24-2021_ * **New community channel**: [Discussions](https://github.com/microsoft/nni/discussions) -* **New emoticons release**: [nnSpider](./docs/source/Tutorial/NNSpider.md) -

- -

- -## **NNI capabilities in a glance** - -NNI provides CommandLine Tool as well as an user friendly WebUI to manage training experiments. With the extensible API, you can customize your own AutoML algorithms and training services. To make it easy for new users, NNI also provides a set of build-in state-of-the-art AutoML algorithms and out of box support for popular training platforms. - -Within the following table, we summarized the current NNI capabilities, we are gradually adding new capabilities and we'd love to have your contribution. - -

- -

- - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Frameworks & Libraries - - - Algorithms - - - Training Services - -
- Built-in - -
  • Supported Frameworks
  • -
      -
    • PyTorch
    • -
    • Keras
    • -
    • TensorFlow
    • -
    • MXNet
    • -
    • Caffe2
    • - More...
      -
    -
-
    -
  • Supported Libraries
  • -
      -
    • Scikit-learn
    • -
    • XGBoost
    • -
    • LightGBM
    • - More...
      -
    -
- -
- Hyperparameter Tuning - - Neural Architecture Search (Retiarii) - - Model Compression - - Feature Engineering (Beta) - - Early Stop Algorithms - - - -
- References - - - - - - -
- -## **Installation** +* **New emoticons release**: [nnSpider](https://nni.readthedocs.io/en/latest/sharings/nn_spider.html) +
+ +
-### **Install** +## Installation -NNI supports and is tested on Ubuntu >= 18.04, Windows 10 >= 21H2, and macOS >= 11. -Simply run the following `pip install` in an environment that has `python 64-bit >= 3.7`. +See the [NNI installation guide](https://nni.readthedocs.io/en/stable/installation.html) to install from pip, or build from source. -Linux or macOS +To install the current release: -```bash -python3 -m pip install --upgrade nni ``` - -Windows - -```bash -python -m pip install --upgrade nni +$ pip install nni ``` -If you want to try latest code, please [install NNI](https://nni.readthedocs.io/en/stable/installation.html) from source code. - -For detail system requirements of NNI, please refer to [here](https://nni.readthedocs.io/en/stable/Tutorial/InstallationLinux.html#system-requirements) for Linux & macOS, and [here](https://nni.readthedocs.io/en/stable/Tutorial/InstallationWin.html#system-requirements) for Windows. - -Note: - -* If there is any privilege issue, add `--user` to install NNI in the user directory. -* Currently NNI on Windows supports local, remote and pai mode. Anaconda or Miniconda is highly recommended to install [NNI on Windows](https://nni.readthedocs.io/en/stable/Tutorial/InstallationWin.html). -* If there is any error like `Segmentation fault`, please refer to [FAQ](https://nni.readthedocs.io/en/stable/Tutorial/FAQ.html). For FAQ on Windows, please refer to [NNI on Windows](https://nni.readthedocs.io/en/stable/Tutorial/InstallationWin.html#faq). - -### **Verify installation** +To update NNI to the latest version, add `--upgrade` flag to the above commands. -* Download the examples via clone the source code. +## NNI capabilities in a glance - ```bash - git clone -b v2.6 https://github.com/Microsoft/nni.git - ``` + -* Run the MNIST example. - - Linux or macOS - - ```bash - nnictl create --config nni/examples/trials/mnist-pytorch/config.yml - ``` - - Windows - - ```powershell - nnictl create --config nni\examples\trials\mnist-pytorch\config_windows.yml - ``` - -* Wait for the message `INFO: Successfully started experiment!` in the command line. This message indicates that your experiment has been successfully started. You can explore the experiment using the `Web UI url`. - -```text -INFO: Starting restful server... -INFO: Successfully started Restful server! -INFO: Setting local config... -INFO: Successfully set local config! -INFO: Starting experiment... -INFO: Successfully started experiment! ------------------------------------------------------------------------ -The experiment id is egchD4qy -The Web UI urls are: http://223.255.255.1:8080 http://127.0.0.1:8080 ------------------------------------------------------------------------ - -You can use these commands to get more information about the experiment ------------------------------------------------------------------------ - commands description -1. nnictl experiment show show the information of experiments -2. nnictl trial ls list all of trial jobs -3. nnictl top monitor the status of running experiments -4. nnictl log stderr show stderr log content -5. nnictl log stdout show stdout log content -6. nnictl stop stop an experiment -7. nnictl trial kill kill a trial job by id -8. nnictl --help get help information about nnictl ------------------------------------------------------------------------ -``` - -* Open the `Web UI url` in your browser, you can view detailed information of the experiment and all the submitted trial jobs as shown below. [Here](https://nni.readthedocs.io/en/stable/Tutorial/WebUI.html) are more Web UI pages. + + + + + + + + + + + + + + + + + + + + + + + + + +
+Hyperparameter Tuning + + +Neural Architecture Search + + +Model Compression + +
+Algorithms + + + + + + +
+Supported Frameworks + + +Training Services + + +Tutorials + +
+Supports + +
    +
  • PyTorch
  • +
  • TensorFlow
  • +
  • Scikit-learn
  • +
  • XGBoost
  • +
  • LightGBM
  • +
  • MXNet
  • +
  • Caffe2
  • +
  • More...
  • +
+
+ + + +
webui -## **Releases and Contributing** -NNI has a monthly release cycle (major releases). Please let us know if you encounter a bug by [filling an issue](https://github.com/microsoft/nni/issues/new/choose). - -We appreciate all contributions. If you are planning to contribute any bug-fixes, please do so without further discussions. +## Resources -If you plan to contribute new features, new tuners, new training services, etc. please first open an issue or reuse an exisiting issue, and discuss the feature with us. We will discuss with you on the issue timely or set up conference calls if needed. +* [NNI Documentation Homepage](https://nni.readthedocs.io/) +* [NNI Installation Guide](https://nni.readthedocs.io/en/stable/installation.html) +* [NNI Examples](https://nni.readthedocs.io/en/latest/examples.html) +* [Python API Reference](https://nni.readthedocs.io/en/latest/reference/python_api.html) +* [Releases (Change Log)](https://nni.readthedocs.io/en/latest/release.html) +* [Related Research and Publications](https://nni.readthedocs.io/en/latest/notes/research_publications.html) +* [Youtube Channel of NNI](https://www.youtube.com/channel/UCKcafm6861B2mnYhPbZHavw) +* [Bilibili Space of NNI](https://space.bilibili.com/1649051673) +* [Webinar of Introducing Retiarii: A deep learning exploratory-training framework on NNI](https://note.microsoft.com/MSR-Webinar-Retiarii-Registration-Live.html) +* [Community Discussions](https://github.com/microsoft/nni/discussions) -To learn more about making a contribution to NNI, please refer to our [How-to contribution page](https://nni.readthedocs.io/en/stable/contribution.html). +## Contribution guidelines -We appreciate all contributions and thank all the contributors! +If you want to contribute to NNI, be sure to review the [contribution guidelines](https://nni.readthedocs.io/en/stable/notes/contributing.html), which includes instructions of submitting feedbacks, best coding practices, and code of conduct. - +We use [GitHub issues](https://github.com/microsoft/nni/issues) to track tracking requests and bugs. +Please use [NNI Discussion](https://github.com/microsoft/nni/discussions) for general questions and new ideas. +For questions of specific use cases, please go to [Stack Overflow](https://stackoverflow.com/questions/tagged/nni). +Participating discussions via the following IM groups is also welcomed. -## **Feedback** -* [File an issue](https://github.com/microsoft/nni/issues/new/choose) on GitHub. -* Open or participate in a [discussion](https://github.com/microsoft/nni/discussions). -* Discuss on the NNI [Gitter](https://gitter.im/Microsoft/nni?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) in NNI. - -Join IM discussion groups: |Gitter||WeChat| |----|----|----| |![image](https://user-images.githubusercontent.com/39592018/80665738-e0574a80-8acc-11ea-91bc-0836dc4cbf89.png)| OR |![image](https://github.com/scarlett2018/nniutil/raw/master/wechat.png)| +Over the past few years, NNI has received thousands of feedbacks on GitHub issues, and pull requests from hundreds of contributors. +We appreciate all contributions from community to make NNI thrive. + + + + ## Test status @@ -363,6 +276,6 @@ Targeting at openness and advancing state-of-art technology, [Microsoft Research We encourage researchers and students leverage these projects to accelerate the AI development and research. -## **License** +## License -The entire codebase is under [MIT license](LICENSE) +The entire codebase is under [MIT license](LICENSE). diff --git a/README_zh_CN.md b/README_zh_CN.md deleted file mode 100644 index 9e551c8ef50afe768ec0c07f4b5566224d91e05c..0000000000000000000000000000000000000000 --- a/README_zh_CN.md +++ /dev/null @@ -1,364 +0,0 @@ -

- -

- -* * * - -[![MIT 许可证](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE) [![生成状态](https://msrasrg.visualstudio.com/NNIOpenSource/_apis/build/status/full%20test%20-%20linux?branchName=master)](https://msrasrg.visualstudio.com/NNIOpenSource/_build/latest?definitionId=62&branchName=master) [![问题](https://img.shields.io/github/issues-raw/Microsoft/nni.svg)](https://github.com/Microsoft/nni/issues?q=is%3Aissue+is%3Aopen) [![Bug](https://img.shields.io/github/issues/Microsoft/nni/bug.svg)](https://github.com/Microsoft/nni/issues?q=is%3Aissue+is%3Aopen+label%3Abug) [![拉取请求](https://img.shields.io/github/issues-pr-raw/Microsoft/nni.svg)](https://github.com/Microsoft/nni/pulls?q=is%3Apr+is%3Aopen) [![版本](https://img.shields.io/github/release/Microsoft/nni.svg)](https://github.com/Microsoft/nni/releases) [![进入 https://gitter.im/Microsoft/nni 聊天室提问](https://badges.gitter.im/Microsoft/nni.svg)](https://gitter.im/Microsoft/nni?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![文档状态](https://readthedocs.org/projects/nni/badge/?version=stable)](https://nni.readthedocs.io/zh/stable/?badge=stable) - -[NNI 文档](https://nni.readthedocs.io/zh/stable/) | [English](README.md) - -**NNI (Neural Network Intelligence)** 是一个帮助用户**自动**进行[特征工程](docs/zh_CN/FeatureEngineering/Overview.rst),[神经网络架构搜索](docs/zh_CN/NAS/Overview.rst),[超参调优](docs/zh_CN/Tuner/BuiltinTuner.rst)以及[模型压缩](docs/zh_CN/Compression/Overview.rst)的轻量且强大的工具包。 - -NNI 管理自动机器学习 (AutoML) 的 Experiment,**调度运行**由调优算法生成的 Trial 任务来找到最好的神经网络架构和/或超参,支持**各种训练环境**,如[本机](docs/zh_CN/TrainingService/LocalMode.rst),[远程服务器](docs/zh_CN/TrainingService/RemoteMachineMode.rst),[OpenPAI](docs/zh_CN/TrainingService/PaiMode.rst),[Kubeflow](docs/zh_CN/TrainingService/KubeflowMode.rst),[基于 K8S 的 FrameworkController(如,AKS 等)](docs/zh_CN/TrainingService/FrameworkControllerMode.rst), [DLWorkspace (又称 DLTS)](docs/zh_CN/TrainingService/DLTSMode.rst), [AML (Azure Machine Learning)](docs/zh_CN/TrainingService/AMLMode.rst), [AdaptDL(又称 ADL)](docs/zh_CN/TrainingService/AdaptDLMode.rst) ,和其他的云平台甚至 [混合模式](docs/zh_CN/TrainingService/HybridMode.rst) 。 DLTS),[AML (Azure Machine Learning)](https://nni.readthedocs.io/zh/stable/TrainingService/AMLMode.html)[AdaptDL(又称 ADL)](https://nni.readthedocs.io/zh/stable/TrainingService/AdaptDLMode.html) ,和其他的云平台甚至[混合模式](https://nni.readthedocs.io/zh/stable/TrainingService/HybridMode.html) 。 - -## **使用场景** - -* 想要在自己的代码、模型中试验**不同的自动机器学习算法**。 -* 想要在**不同的环境中**加速运行自动机器学习。 -* 想要更容易**实现或试验新的自动机器学习算法**的研究员或数据科学家,包括:超参调优算法,神经网络搜索算法以及模型压缩算法。 -* 在机器学习平台中**支持自动机器学习**。 - -## **最新消息!**  [](#nni-released-reminder) - -* **最新版本**:[v2.6 已发布](https://github.com/microsoft/nni/releases/tag/v2.6) - *2022年1月19日* -* **最新视频 demo**:[Youtube 入口](https://www.youtube.com/channel/UCKcafm6861B2mnYhPbZHavw) | [Bilibili 入口](https://space.bilibili.com/1649051673) - *上次更新:2021年5月26日* -* **最新网络研讨会**: [介绍Retiarii:NNI 上的深度学习探索性训练框架](https://note.microsoft.com/MSR-Webinar-Retiarii-Registration-Live.html) - *2021年6月24日* -* **最新互动渠道**: [Discussions](https://github.com/microsoft/nni/discussions) -* **最新粉丝福利表情包上线**: [nnSpider](./docs/en_US/Tutorial/NNSpider.md) -

- -

- -## **NNI 功能一览** - -NNI 提供命令行工具以及友好的 WebUI 来管理训练的 Experiment。 通过可扩展的 API,可定制自动机器学习算法和训练平台。 为了方便新用户,NNI 内置了最新的自动机器学习算法,并为流行的训练平台提供了开箱即用的支持。 - -下表中,包含了 NNI 的功能,同时在不断地增添新功能,也非常希望您能贡献其中。 - -

- -

- - - - - - - - - - - - - - - - - - - - - - - - - - -
- - 支持的框架和库 - - - 算法 - - - 训练平台 - -
- 内置 - -
  • 支持的框架
  • -
      -
    • PyTorch
    • -
    • Keras
    • -
    • TensorFlow
    • -
    • MXNet
    • -
    • Caffe2
    • - 更多...
      -
    -
-
    -
  • 支持的库
  • -
      -
    • Scikit-learn
    • -
    • XGBoost
    • -
    • LightGBM
    • - 更多...
      -
    -
- -
- 超参调优 - - 神经网络架构搜索 - - 模型压缩 - - 特征工程(测试版) - - 提前终止算法 - - - -
- 参考 - - - - - - -
- -## **安装** - -### **安装** - -NNI 支持并在 Ubuntu >= 16.04, macOS >= 10.14.1, 和 Windows 10 >= 1809 通过了测试。 在 `python 64-bit >= 3.6` 的环境中,只需要运行 `pip install` 即可完成安装。 - -Linux 或 macOS - -```bash -python3 -m pip install --upgrade nni -``` - -Windows - -```bash -python -m pip install --upgrade nni -``` - -如果想试试最新代码,可参考从源代码[安装 NNI](https://nni.readthedocs.io/zh/latest/installation.html)。 - -Linux 和 macOS 下 NNI 系统需求[参考这里](https://nni.readthedocs.io/zh/latest/Tutorial/InstallationLinux.html#system-requirements) ,Windows [参考这里](https://nni.readthedocs.io/zh/latest/Tutorial/InstallationWin.html#system-requirements)。 - -注意: - -* 如果遇到任何权限问题,可添加 `--user` 在用户目录中安装 NNI。 -* 目前,Windows 上的 NNI 支持本机,远程和 OpenPAI 模式。 强烈推荐使用 Anaconda 或 Miniconda [在 Windows 上安装 NNI](https://nni.readthedocs.io/zh/stable/Tutorial/InstallationWin.html)。 -* 如果遇到如 `Segmentation fault` 等错误参考[常见问题](docs/zh_CN/Tutorial/FAQ.rst)。 Windows 上的 FAQ 参考[在 Windows 上使用 NNI](docs/zh_CN/Tutorial/InstallationWin.rst#faq)。 Windows 上的 FAQ 参考[在 Windows 上使用 NNI](https://nni.readthedocs.io/zh/stable/Tutorial/InstallationWin.html#faq)。 - -### **验证安装** - -* 通过克隆源代码下载示例。 - - ```bash - git clone -b v2.6 https://github.com/Microsoft/nni.git - ``` - -* 运行 MNIST 示例。 - - Linux 或 macOS - - ```bash - nnictl create --config nni/examples/trials/mnist-pytorch/config.yml - ``` - - Windows - - ```powershell - nnictl create --config nni\examples\trials\mnist-pytorch\config_windows.yml - ``` - -* 在命令行中等待输出 `INFO: Successfully started experiment!`。 此消息表明 Experiment 已成功启动。 通过命令行输出的 `Web UI url` 来访问 Experiment 的界面。 此消息表明 Experiment 已成功启动。 通过命令行输出的 `Web UI url` 来访问 Experiment 的界面。 - -```text -INFO: Starting restful server... -INFO: Successfully started Restful server! -INFO: Setting local config... -INFO: Successfully set local config! -INFO: Starting experiment... -INFO: Successfully started experiment! ------------------------------------------------------------------------ -The experiment id is egchD4qy -The Web UI urls are: http://223.255.255.1:8080 http://127.0.0.1:8080 ------------------------------------------------------------------------ - -You can use these commands to get more information about the experiment ------------------------------------------------------------------------ - commands description - -1. nnictl experiment show show the information of experiments -2. nnictl trial ls list all of trial jobs -3. nnictl top monitor the status of running experiments -4. nnictl log stderr show stderr log content -5. nnictl log stdout show stdout log content -6. nnictl stop stop an experiment -7. nnictl trial kill kill a trial job by id -8. nnictl --help get help information about nnictl ------------------------------------------------------------------------ -``` - -* 在浏览器中打开 `Web UI url`,可看到下图的 Experiment 详细信息,以及所有的 Trial 任务。 查看[这里](docs/zh_CN/Tutorial/WebUI.rst)的更多页面。 查看[这里](https://nni.readthedocs.io/zh/stable/Tutorial/WebUI.html)的更多页面。 - -webui - -## **发布和贡献** - -NNI 有一个月度发布周期(主要发布)。 如果您遇到问题可以通过 [创建 issue](https://github.com/microsoft/nni/issues/new/choose) 来报告。 - -我们感谢所有的贡献。 我们感谢所有的贡献。 如果您计划提供任何 Bug 修复,请放手去做,不需要任何顾虑。 - -如果您计划提供新的功能、新的 Tuner 和 新的训练平台等, 请先创建一个新的 issue 或重用现有 issue,并与我们讨论该功能。 我们会及时与您讨论这个问题,如有需要会安排电话会议。 - -再次感谢所有的贡献者! - -再次感谢所有的贡献者! - - - -## **反馈** - -* [在 GitHub 上提交问题](https://github.com/microsoft/nni/issues/new/choose)。 -* 在 [Gitter](https://gitter.im/Microsoft/nni?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 中参与讨论。 -* NNI 有一个月度发布周期(主要发布)。 如果您遇到问题可以通过 [创建 issue](https://github.com/microsoft/nni/issues/new/choose) 来报告。 - -加入聊天组: - -| Gitter | | 微信 | -| -------------------------------------------------------------------------------------------------------------- | - | ----------------------------------------------------------------------- | -| ![image](https://user-images.githubusercontent.com/39592018/80665738-e0574a80-8acc-11ea-91bc-0836dc4cbf89.png) | 或 | ![image](https://github.com/scarlett2018/nniutil/raw/master/wechat.png) | - -## 测试状态 - -### 必需 - -| 类型 | 状态 | -|:------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| -| Fast test | [![Build Status](https://msrasrg.visualstudio.com/NNIOpenSource/_apis/build/status/fast%20test?branchName=master)](https://msrasrg.visualstudio.com/NNIOpenSource/_build/latest?definitionId=54&branchName=master) | -| Full linux | [![Build Status](https://msrasrg.visualstudio.com/NNIOpenSource/_apis/build/status/full%20test%20-%20linux?repoName=microsoft%2Fnni&branchName=master)](https://msrasrg.visualstudio.com/NNIOpenSource/_build/latest?definitionId=62&repoName=microsoft%2Fnni&branchName=master) | -| Full windows | [![Build Status](https://msrasrg.visualstudio.com/NNIOpenSource/_apis/build/status/full%20test%20-%20windows?branchName=master)](https://msrasrg.visualstudio.com/NNIOpenSource/_build/latest?definitionId=63&branchName=master) | - -### 训练平台 - -| 类型 | 状态 | -|:-------------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| -| Remote - linux to linux | [![Build Status](https://msrasrg.visualstudio.com/NNIOpenSource/_apis/build/status/integration%20test%20-%20remote%20-%20linux%20to%20linux?branchName=master)](https://msrasrg.visualstudio.com/NNIOpenSource/_build/latest?definitionId=64&branchName=master) | -| Remote - linux to windows | [![Build Status](https://msrasrg.visualstudio.com/NNIOpenSource/_apis/build/status/integration%20test%20-%20remote%20-%20linux%20to%20windows?branchName=master)](https://msrasrg.visualstudio.com/NNIOpenSource/_build/latest?definitionId=67&branchName=master) | -| Remote - windows to linux | [![Build Status](https://msrasrg.visualstudio.com/NNIOpenSource/_apis/build/status/integration%20test%20-%20remote%20-%20windows%20to%20linux?branchName=master)](https://msrasrg.visualstudio.com/NNIOpenSource/_build/latest?definitionId=68&branchName=master) | -| OpenPAI | [![Build Status](https://msrasrg.visualstudio.com/NNIOpenSource/_apis/build/status/integration%20test%20-%20openpai%20-%20linux?branchName=master)](https://msrasrg.visualstudio.com/NNIOpenSource/_build/latest?definitionId=65&branchName=master) | -| Frameworkcontroller | [![Build Status](https://msrasrg.visualstudio.com/NNIOpenSource/_apis/build/status/integration%20test%20-%20frameworkcontroller?branchName=master)](https://msrasrg.visualstudio.com/NNIOpenSource/_build/latest?definitionId=70&branchName=master) | -| Kubeflow | [![Build Status](https://msrasrg.visualstudio.com/NNIOpenSource/_apis/build/status/integration%20test%20-%20kubeflow?branchName=master)](https://msrasrg.visualstudio.com/NNIOpenSource/_build/latest?definitionId=69&branchName=master) | -| Hybrid | [![Build Status](https://msrasrg.visualstudio.com/NNIOpenSource/_apis/build/status/integration%20test%20-%20hybrid?branchName=master)](https://msrasrg.visualstudio.com/NNIOpenSource/_build/latest?definitionId=79&branchName=master) | -| AzureML | [![Build Status](https://msrasrg.visualstudio.com/NNIOpenSource/_apis/build/status/integration%20test%20-%20aml?branchName=master)](https://msrasrg.visualstudio.com/NNIOpenSource/_build/latest?definitionId=78&branchName=master) | - -## 相关项目 - -针对开放性和推进最先进的技术,[微软研究院(MSR)](https://www.microsoft.com/en-us/research/group/systems-and-networking-research-group-asia/) 还发布了其他几个开源项目。 - -* [OpenPAI](https://github.com/Microsoft/pai):作为开源平台,提供了完整的 AI 模型训练和资源管理能力,能轻松扩展,并支持各种规模的私有部署、云和混合环境。 -* [FrameworkController](https://github.com/Microsoft/frameworkcontroller):开源的通用 Kubernetes Pod 控制器,通过单个控制器来编排 Kubernetes 上所有类型的应用。 -* [MMdnn](https://github.com/Microsoft/MMdnn):一个完整、跨框架的解决方案,能够转换、可视化、诊断深度神经网络模型。 MMdnn 中的 "MM" 表示 model management(模型管理),而 "dnn" 是 deep neural network(深度神经网络)的缩写。 MMdnn 中的 "MM" 表示 model management(模型管理),而 "dnn" 是 deep neural network(深度神经网络)的缩写。 -* [SPTAG](https://github.com/Microsoft/SPTAG) : Space Partition Tree And Graph (SPTAG) 是用于大规模向量的最近邻搜索场景的开源库。 - -我们鼓励研究人员和学生利用这些项目来加速 AI 开发和研究。 - -## **许可协议** - -代码库遵循 [MIT 许可协议](LICENSE) diff --git a/SECURITY_zh_CN.md b/SECURITY_zh_CN.md deleted file mode 100644 index bfd7da66aa9b56a490e5590ba3d6503c1a01bf94..0000000000000000000000000000000000000000 --- a/SECURITY_zh_CN.md +++ /dev/null @@ -1,41 +0,0 @@ - - -## 安全 - -微软非常重视软件产品和服务的安全性,包括通过我们的 GitHub 组织管理的所有源代码库,其中涵盖 [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin),和 [我们 GitHub 的组织](https://opensource.microsoft.com/)。 - -如果你在任何微软拥有的资源库中发现了安全漏洞,并且符合 [微软对安全漏洞的定义](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)),请按照下文所述向我们报告。 - -## 报告安全问题 - -**请不要通过公开的 GitHub 问题报告安全漏洞。** - -相反,请向微软安全响应中心(MSRC)报告,链接是 [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report)。 - -如果您希望在不登录的情况下提交,请发送电子邮件至 [secure@microsoft.com](mailto:secure@microsoft.com)。 如果可能的话,请用我们的 PGP 密钥对您的信息进行加密;请从以下网站下载该密钥 [微软安全响应中心 PGP 密钥页面](https://www.microsoft.com/en-us/msrc/pgp-key-msrc)。 - -你应该在24小时内收到回复。 如果由于某些原因你没有收到,请通过电子邮件跟进,以确保我们收到你的原始信息。 其他信息可以在以下网站找到 [microsoft.com/msrc](https://www.microsoft.com/msrc)。 - -请包括以下所要求的信息(尽可能多地提供),以帮助我们更好地了解可能的问题的性质和范围。 - - * 问题类型(如缓冲区溢出、SQL 注入、跨站脚本等) - * 与问题表现有关的源文件的完整路径 - * 受影响的源代码位置(标签/分支/提交或 URL) - * 重现该问题所需的任何特殊配置 - * 重现该问题的分步骤说明 - * 概念证明或漏洞代码(如果可能的话) - * 该问题的影响,包括攻击者如何利用该问题 - -这些信息将帮助我们更快地对你的报告进行分流。 - -如果您需要报告错误赏金,更完整的报告可有助于获得更高的赏金奖励。 请访问我们的[微软漏洞赏金计划](https://microsoft.com/msrc/bounty)页面,以了解有关我们活动计划的更多详细信息。 - -## 首选语言 - -我们希望所有的交流都是用英语进行的。 - -## 政策 - -微软遵循[协调漏洞披露](https://www.microsoft.com/en-us/msrc/cvd)的原则。 - - diff --git a/dependencies/develop.txt b/dependencies/develop.txt index 56a4dcadc743eef8ae974a134363cee450d471b9..0e87993cbb72501b803dc9884eca10cc7ed8a615 100644 --- a/dependencies/develop.txt +++ b/dependencies/develop.txt @@ -2,15 +2,20 @@ coverage cython flake8 ipython -jupyterlab +jupyter +jupyterlab == 3.0.9 nbsphinx pylint +pyright pytest pytest-azurepipelines pytest-cov rstcheck -sphinx +sphinx >= 4.5 sphinx-argparse-nni >= 0.4.0 +sphinx-copybutton sphinx-gallery +sphinx-intl +sphinx-tabs sphinxcontrib-bibtex -git+https://github.com/bashtage/sphinx-material.git +git+https://github.com/bashtage/sphinx-material@6e0ef82#egg=sphinx_material diff --git a/dependencies/recommended.txt b/dependencies/recommended.txt index 572dac3489c01db7aec6c4c4b16e6ff5c85a9211..2459808c5a086b362dfcf9190def67909eb73639 100644 --- a/dependencies/recommended.txt +++ b/dependencies/recommended.txt @@ -7,8 +7,9 @@ torch == 1.10.0+cpu ; sys_platform != "darwin" torch == 1.10.0 ; sys_platform == "darwin" torchvision == 0.11.1+cpu ; sys_platform != "darwin" torchvision == 0.11.1 ; sys_platform == "darwin" -pytorch-lightning >= 1.5.0 +pytorch-lightning >= 1.5.0, < 1.6.0 torchmetrics +lightgbm onnx peewee graphviz diff --git a/dependencies/recommended_gpu.txt b/dependencies/recommended_gpu.txt index 54f75b0661546d241686f1b2a0c4a27076bbbec8..f9a5b6d8f56262cd76019b59fd2fca90774f5999 100644 --- a/dependencies/recommended_gpu.txt +++ b/dependencies/recommended_gpu.txt @@ -4,7 +4,8 @@ tensorflow torch == 1.10.0+cu111 torchvision == 0.11.1+cu111 -pytorch-lightning >= 1.5.0 +pytorch-lightning >= 1.5.0, < 1.6.0 +lightgbm onnx peewee graphviz diff --git a/dependencies/recommended_legacy.txt b/dependencies/recommended_legacy.txt index 5c5b39ee61f298fac39ef0c805410bf8dd95105f..da4cacb06f440e9e5aa99bc45ff065fdd2691434 100644 --- a/dependencies/recommended_legacy.txt +++ b/dependencies/recommended_legacy.txt @@ -7,6 +7,7 @@ torchvision == 0.8.2+cpu pytorch-lightning torchmetrics +lightgbm onnx peewee graphviz diff --git a/dependencies/required.txt b/dependencies/required.txt index 2ce30c9cd9e0aded06f8acab7e3c81df59466bdb..bb8d0cc8b9e2b9fd9b93dcb1652b3864d3dec8d3 100644 --- a/dependencies/required.txt +++ b/dependencies/required.txt @@ -6,6 +6,7 @@ hyperopt == 0.1.2 json_tricks >= 3.15.5 numpy < 1.22 ; python_version < "3.8" numpy ; python_version >= "3.8" +packaging pandas prettytable psutil @@ -18,5 +19,5 @@ scikit-learn >= 0.24.1 scipy < 1.8 ; python_version < "3.8" scipy ; python_version >= "3.8" typeguard -typing_extensions ; python_version < "3.8" +typing_extensions >= 4.0.0 ; python_version < "3.8" websockets >= 10.1 diff --git a/docs/.gitignore b/docs/.gitignore index 20b5bd428820e468305c3bb80a62d8e23fe4843c..522de2ff58d13b94c70e6d3cecd9064ea0a3fd56 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -2,3 +2,12 @@ build/ # legacy build _build/ + +# ignored copied rst in tutorials +/source/tutorials/**/cp_*.rst + +# auto-generated reference table +_modules/ + +# Machine-style translation files +*.mo diff --git a/docs/Makefile b/docs/Makefile index ba501f6f5b1bfd30093a73f5fc04b85122e604a4..1d14ccfe792908ba28451f100e5d0b16a59c9b3d 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -11,6 +11,11 @@ BUILDDIR = build help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) +# Build message catelogs for translation +i18n: + @$(SPHINXBUILD) -M getpartialtext "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + sphinx-intl update -p "$(BUILDDIR)/getpartialtext" -d "$(SOURCEDIR)/locales" -l zh + .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new diff --git a/docs/source/Assessor/CurvefittingAssessor.rst b/docs/_removed/CurvefittingAssessor.rst similarity index 100% rename from docs/source/Assessor/CurvefittingAssessor.rst rename to docs/_removed/CurvefittingAssessor.rst diff --git a/docs/source/Tutorial/HowToDebug.rst b/docs/_removed/HowToDebug.rst similarity index 100% rename from docs/source/Tutorial/HowToDebug.rst rename to docs/_removed/HowToDebug.rst diff --git a/docs/source/Tutorial/HowToLaunchFromPython.rst b/docs/_removed/HowToLaunchFromPython.rst similarity index 100% rename from docs/source/Tutorial/HowToLaunchFromPython.rst rename to docs/_removed/HowToLaunchFromPython.rst diff --git a/docs/source/Tutorial/HowToUseDocker.rst b/docs/_removed/HowToUseDocker.rst similarity index 100% rename from docs/source/Tutorial/HowToUseDocker.rst rename to docs/_removed/HowToUseDocker.rst diff --git a/docs/source/Tutorial/InstallationLinux.rst b/docs/_removed/InstallationLinux.rst similarity index 100% rename from docs/source/Tutorial/InstallationLinux.rst rename to docs/_removed/InstallationLinux.rst diff --git a/docs/source/Tutorial/InstallationLinux_zh.rst b/docs/_removed/InstallationLinux_zh.rst similarity index 100% rename from docs/source/Tutorial/InstallationLinux_zh.rst rename to docs/_removed/InstallationLinux_zh.rst diff --git a/docs/source/Tutorial/InstallationWin.rst b/docs/_removed/InstallationWin.rst similarity index 100% rename from docs/source/Tutorial/InstallationWin.rst rename to docs/_removed/InstallationWin.rst diff --git a/docs/source/Tutorial/InstallationWin_zh.rst b/docs/_removed/InstallationWin_zh.rst similarity index 100% rename from docs/source/Tutorial/InstallationWin_zh.rst rename to docs/_removed/InstallationWin_zh.rst diff --git a/docs/source/Release_v1.0.md b/docs/_removed/Release_v1.0.md similarity index 100% rename from docs/source/Release_v1.0.md rename to docs/_removed/Release_v1.0.md diff --git a/docs/source/SupportedFramework_Library.rst b/docs/_removed/SupportedFramework_Library.rst similarity index 100% rename from docs/source/SupportedFramework_Library.rst rename to docs/_removed/SupportedFramework_Library.rst diff --git a/docs/source/TrainingService/AMLMode.rst b/docs/_removed/TrainingService/AMLMode.rst similarity index 100% rename from docs/source/TrainingService/AMLMode.rst rename to docs/_removed/TrainingService/AMLMode.rst diff --git a/docs/source/TrainingService/FrameworkControllerMode.rst b/docs/_removed/TrainingService/FrameworkControllerMode.rst similarity index 100% rename from docs/source/TrainingService/FrameworkControllerMode.rst rename to docs/_removed/TrainingService/FrameworkControllerMode.rst diff --git a/docs/source/TrainingService/HybridMode.rst b/docs/_removed/TrainingService/HybridMode.rst similarity index 100% rename from docs/source/TrainingService/HybridMode.rst rename to docs/_removed/TrainingService/HybridMode.rst diff --git a/docs/source/TrainingService/KubeflowMode.rst b/docs/_removed/TrainingService/KubeflowMode.rst similarity index 100% rename from docs/source/TrainingService/KubeflowMode.rst rename to docs/_removed/TrainingService/KubeflowMode.rst diff --git a/docs/source/TrainingService/Overview.rst b/docs/_removed/TrainingService/Overview.rst similarity index 100% rename from docs/source/TrainingService/Overview.rst rename to docs/_removed/TrainingService/Overview.rst diff --git a/docs/source/TrainingService/PaiMode.rst b/docs/_removed/TrainingService/PaiMode.rst similarity index 100% rename from docs/source/TrainingService/PaiMode.rst rename to docs/_removed/TrainingService/PaiMode.rst diff --git a/docs/source/TrainingService/RemoteMachineMode.rst b/docs/_removed/TrainingService/RemoteMachineMode.rst similarity index 100% rename from docs/source/TrainingService/RemoteMachineMode.rst rename to docs/_removed/TrainingService/RemoteMachineMode.rst diff --git a/docs/source/TrialExample/Cifar10Examples.rst b/docs/_removed/TrialExample/Cifar10Examples.rst similarity index 100% rename from docs/source/TrialExample/Cifar10Examples.rst rename to docs/_removed/TrialExample/Cifar10Examples.rst diff --git a/docs/source/TrialExample/GbdtExample.rst b/docs/_removed/TrialExample/GbdtExample.rst similarity index 100% rename from docs/source/TrialExample/GbdtExample.rst rename to docs/_removed/TrialExample/GbdtExample.rst diff --git a/docs/source/TrialExample/MnistExamples.rst b/docs/_removed/TrialExample/MnistExamples.rst similarity index 100% rename from docs/source/TrialExample/MnistExamples.rst rename to docs/_removed/TrialExample/MnistExamples.rst diff --git a/docs/source/TrialExample/Pix2pixExample.rst b/docs/_removed/TrialExample/Pix2pixExample.rst similarity index 100% rename from docs/source/TrialExample/Pix2pixExample.rst rename to docs/_removed/TrialExample/Pix2pixExample.rst diff --git a/docs/source/TrialExample/SklearnExamples.rst b/docs/_removed/TrialExample/SklearnExamples.rst similarity index 100% rename from docs/source/TrialExample/SklearnExamples.rst rename to docs/_removed/TrialExample/SklearnExamples.rst diff --git a/docs/source/TrialExample/Trials.rst b/docs/_removed/Trials.rst similarity index 100% rename from docs/source/TrialExample/Trials.rst rename to docs/_removed/Trials.rst diff --git a/docs/source/Tuner/BohbAdvisor.rst b/docs/_removed/Tuner/BohbAdvisor.rst similarity index 100% rename from docs/source/Tuner/BohbAdvisor.rst rename to docs/_removed/Tuner/BohbAdvisor.rst diff --git a/docs/source/Tuner/CustomizeAdvisor.rst b/docs/_removed/Tuner/CustomizeAdvisor.rst similarity index 100% rename from docs/source/Tuner/CustomizeAdvisor.rst rename to docs/_removed/Tuner/CustomizeAdvisor.rst diff --git a/docs/source/Tuner/DngoTuner.rst b/docs/_removed/Tuner/DngoTuner.rst similarity index 100% rename from docs/source/Tuner/DngoTuner.rst rename to docs/_removed/Tuner/DngoTuner.rst diff --git a/docs/source/Tuner/EvolutionTuner.rst b/docs/_removed/Tuner/EvolutionTuner.rst similarity index 100% rename from docs/source/Tuner/EvolutionTuner.rst rename to docs/_removed/Tuner/EvolutionTuner.rst diff --git a/docs/source/Tuner/GPTuner.rst b/docs/_removed/Tuner/GPTuner.rst similarity index 100% rename from docs/source/Tuner/GPTuner.rst rename to docs/_removed/Tuner/GPTuner.rst diff --git a/docs/source/Tuner/HyperbandAdvisor.rst b/docs/_removed/Tuner/HyperbandAdvisor.rst similarity index 100% rename from docs/source/Tuner/HyperbandAdvisor.rst rename to docs/_removed/Tuner/HyperbandAdvisor.rst diff --git a/docs/source/Tuner/MetisTuner.rst b/docs/_removed/Tuner/MetisTuner.rst similarity index 100% rename from docs/source/Tuner/MetisTuner.rst rename to docs/_removed/Tuner/MetisTuner.rst diff --git a/docs/source/Tuner/PBTTuner.rst b/docs/_removed/Tuner/PBTTuner.rst similarity index 100% rename from docs/source/Tuner/PBTTuner.rst rename to docs/_removed/Tuner/PBTTuner.rst diff --git a/docs/source/Tuner/SmacTuner.rst b/docs/_removed/Tuner/SmacTuner.rst similarity index 100% rename from docs/source/Tuner/SmacTuner.rst rename to docs/_removed/Tuner/SmacTuner.rst diff --git a/docs/source/Tutorial/NNSpider.md b/docs/_removed/Tutorial/NNSpider.md similarity index 100% rename from docs/source/Tutorial/NNSpider.md rename to docs/_removed/Tutorial/NNSpider.md diff --git a/docs/source/Tutorial/python_api_connect.ipynb b/docs/_removed/Tutorial/python_api_connect.ipynb similarity index 100% rename from docs/source/Tutorial/python_api_connect.ipynb rename to docs/_removed/Tutorial/python_api_connect.ipynb diff --git a/docs/source/Tutorial/python_api_start.ipynb b/docs/_removed/Tutorial/python_api_start.ipynb similarity index 100% rename from docs/source/Tutorial/python_api_start.ipynb rename to docs/_removed/Tutorial/python_api_start.ipynb diff --git a/docs/source/Tutorial/WebUI.rst b/docs/_removed/WebUI.rst similarity index 100% rename from docs/source/Tutorial/WebUI.rst rename to docs/_removed/WebUI.rst diff --git a/docs/source/Tutorial/FAQ.rst b/docs/_removed/faq.rst similarity index 100% rename from docs/source/Tutorial/FAQ.rst rename to docs/_removed/faq.rst diff --git a/docs/_removed/installation.rst b/docs/_removed/installation.rst new file mode 100644 index 0000000000000000000000000000000000000000..5688b3b4c832cb889d91e32b11fe1af9e7e9f2d0 --- /dev/null +++ b/docs/_removed/installation.rst @@ -0,0 +1,12 @@ +############ +Installation +############ + +Currently we support installation on Linux, Mac and Windows. We also allow you to use docker. + +.. toctree:: + :maxdepth: 2 + + Linux & Mac + Windows + Use Docker \ No newline at end of file diff --git a/docs/_removed/reference/python_api.rst b/docs/_removed/reference/python_api.rst new file mode 100644 index 0000000000000000000000000000000000000000..2926461ba6291c0c6eb756d29c79b8ee8d422afc --- /dev/null +++ b/docs/_removed/reference/python_api.rst @@ -0,0 +1,10 @@ +:orphan: + +Python API Reference +==================== + +.. autosummary:: + :toctree: _modules + :recursive: + + nni diff --git a/docs/source/training_services.rst b/docs/_removed/training_services.rst similarity index 72% rename from docs/source/training_services.rst rename to docs/_removed/training_services.rst index ab8f79fbd7d79ed7582eab9463ae5ec4ae90438a..854b09f0b75ee2d3669e7f06bb5d0d073c8862b8 100644 --- a/docs/source/training_services.rst +++ b/docs/_removed/training_services.rst @@ -3,13 +3,9 @@ Introduction to NNI Training Services .. toctree:: Overview <./TrainingService/Overview> - Local<./TrainingService/LocalMode> Remote<./TrainingService/RemoteMachineMode> OpenPAI<./TrainingService/PaiMode> Kubeflow<./TrainingService/KubeflowMode> - AdaptDL<./TrainingService/AdaptDLMode> FrameworkController<./TrainingService/FrameworkControllerMode> - DLTS<./TrainingService/DLTSMode> AML<./TrainingService/AMLMode> - PAI-DLC<./TrainingService/DLCMode> Hybrid<./TrainingService/HybridMode> diff --git a/docs/extension/cardlinkitem.py b/docs/extension/cardlinkitem.py index d3c000f7248eee001657704fb9b1a3a5c6d872f3..80a8902be2146e979d1ae623c97cb2b1a764f1d4 100644 --- a/docs/extension/cardlinkitem.py +++ b/docs/extension/cardlinkitem.py @@ -7,6 +7,7 @@ import os from docutils.parsers.rst import Directive, directives from docutils.statemachine import StringList from docutils import nodes +from sphinx.addnodes import pending_xref TAG_TEMPLATE = """{tag}""" @@ -14,12 +15,12 @@ TAGS_TEMPLATE = """ """ -CARD_TEMPLATE = """ +CARD_HEADER = """ .. raw:: html """ @@ -95,15 +100,30 @@ class CustomCardItemDirective(Directive): else: tags_rst = '' - card_rst = CARD_TEMPLATE.format(header=header, - image=image, - image_background=image_background, - link=link, - description=description, - tags=tags_rst) - card_list = StringList(card_rst.split('\n')) + card_rst = CARD_HEADER.format( + header=header, + image=image, + image_background=image_background, + link=link, + description=description, + tags=tags_rst) card = nodes.paragraph() - self.state.nested_parse(card_list, self.content_offset, card) + self.state.nested_parse(StringList(card_rst.split('\n')), self.content_offset, card) + + # This needs to corporate with javascript: propagate_card_link. + # because sphinx can't correctly handle image in a `pending_xref` after `keepformat`. + link_node = pending_xref('', + reftype='doc', + refdomain='std', + reftarget=link, + refexplicit=False, + refwarn=True) + link_node += nodes.paragraph(header) + link_node['classes'] = ['card-link-anchor'] + card += link_node + + self.state.nested_parse(StringList(CARD_FOOTER.split('\n')), self.content_offset, card) + return [card] diff --git a/docs/extension/codesnippetcard.py b/docs/extension/codesnippetcard.py new file mode 100644 index 0000000000000000000000000000000000000000..d1c067c384166497383d004798fd219aabf9b855 --- /dev/null +++ b/docs/extension/codesnippetcard.py @@ -0,0 +1,114 @@ +""" +Code snippet card, used in index page. +""" + +from docutils.parsers.rst import Directive, directives +from docutils.statemachine import StringList +from docutils import nodes + +from sphinx.addnodes import pending_xref + + +CARD_TEMPLATE_HEADER = """ +.. raw:: html + +
+ +
+ +
+ +
+ +.. image:: {icon} + +.. raw:: html + +
+ +

{title}

+
+ +""" + +CARD_TEMPLATE_FOOTER = """ +.. raw:: html + +
+""" + +CARD_TEMPLATE_LINK_CONTAINER_HEADER = """ +.. raw:: html + +
+ +NNI eases the effort to scale and manage AutoML experiments +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. codesnippetcard:: + :icon: ../img/thumbnails/training-service-small.svg + :title: Training Service + :link: experiment/training_service/overview + :seemore: See more here. + + An AutoML experiment requires many trials to explore feasible and potentially good-performing models. + **Training service** aims to make the tuning process easily scalable in a distributed platforms. + It provides a unified user experience for diverse computation resources (e.g., local machine, remote servers, AKS). + Currently, NNI supports **more than 9** kinds of training services. + +.. codesnippetcard:: + :icon: ../img/thumbnails/web-portal-small.svg + :title: Web Portal + :link: experiment/web_portal/web_portal + :seemore: See more here. + + Web portal visualizes the tuning process, exposing the ability to inspect, monitor and control the experiment. + + .. image:: ../static/img/webui.gif + :width: 100% + +.. codesnippetcard:: + :icon: ../img/thumbnails/experiment-management-small.svg + :title: Experiment Management + :link: experiment/experiment_management + :seemore: See more here. + + The DNN model tuning often requires more than one experiment. + Users might try different tuning algorithms, fine-tune their search space, or switch to another training service. + **Experiment management** provides the power to aggregate and compare tuning results from multiple experiments, + so that the tuning workflow becomes clean and organized. + +Get Support and Contribute Back +------------------------------- + +NNI is maintained on the `NNI GitHub repository `_. We collect feedbacks and new proposals/ideas on GitHub. You can: + +* Open a `GitHub issue `_ for bugs and feature requests. +* Open a `pull request `_ to contribute code (make sure to read the :doc:`contribution guide ` before doing this). +* Participate in `NNI Discussion `_ for general questions and new ideas. +* Join the following IM groups. + +.. list-table:: + :header-rows: 1 + :widths: auto + + * - Gitter + - WeChat + * - + .. image:: https://user-images.githubusercontent.com/39592018/80665738-e0574a80-8acc-11ea-91bc-0836dc4cbf89.png + - + .. image:: https://github.com/scarlett2018/nniutil/raw/master/wechat.png + +Citing NNI +---------- + +If you use NNI in a scientific publication, please consider citing NNI in your references. + + Microsoft. Neural Network Intelligence (version |release|). https://github.com/microsoft/nni + +Bibtex entry (please replace the version with the particular version you are using): :: + + @software{nni2021, + author = {{Microsoft}}, + month = {1}, + title = {{Neural Network Intelligence}}, + url = {https://github.com/microsoft/nni}, + version = {2.0}, + year = {2021} + } diff --git a/docs/source/index_zh.rst b/docs/source/index_zh.rst index e57bd56a1be57ca3a5be9510b6029645d10a7c10..f87d2dee110e60f7ddef02c64d288008add79c1c 100644 --- a/docs/source/index_zh.rst +++ b/docs/source/index_zh.rst @@ -1,483 +1,298 @@ -.. 1c1500ed177d6b4badecd72037a24a30 - -########################### -Neural Network Intelligence -########################### - - -.. toctree:: - :maxdepth: 2 - :titlesonly: - :hidden: - - 概述 - 安装 - 入门 - 教程 - 自动(超参数)调优 - 神经网络架构搜索 - 模型压缩 - 特征工程 - 参考 - 示例与解决方案 - 研究和出版物 - 常见问题 - 如何贡献 - 更改日志 +.. dbd41cab307bcd76cc747b3d478709b8 +NNI 文档 +================= + +.. toctree:: + :maxdepth: 2 + :caption: 开始使用 + :hidden: + + 安装 + 快速入门 + +.. toctree:: + :maxdepth: 2 + :caption: 用户指南 + :hidden: + + 超参调优 + 架构搜索 + 模型压缩 + 特征工程 + 实验管理 + +.. toctree:: + :maxdepth: 2 + :caption: 参考 + :hidden: + + Python API + 实验配置 + nnictl 命令 + +.. toctree:: + :maxdepth: 2 + :caption: 杂项 + :hidden: + + 示例 + 社区分享 + 研究发布 + 源码安装 + 贡献指南 + 版本说明 + +**NNI (Neural Network Intelligence)** 是一个轻量而强大的工具,可以帮助用户 **自动化**: + +* :doc:`超参调优 ` +* :doc:`架构搜索 ` +* :doc:`模型压缩 ` +* :doc:`特征工程 ` + +开始使用 +----------- + +安装最新的版本,可执行以下命令: + +.. code-block:: bash + + $ pip install nni + +如果在安装上遇到问题,可参考 :doc:`安装指南 `。 + +开始你的第一个 NNI 实验 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: shell + + $ nnictl hello + +.. note:: 你需要预先安装 `PyTorch `_ (以及 `torchvision `_ )才能运行这个实验。 + +请阅读 :doc:`NNI 快速入门 ` 以开启你的 NNI 旅程! + +为什么选择 NNI? +-------------------- + +NNI 使得自动机器学习技术即插即用 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + .. raw:: html -
- - NNI (Neural Network Intelligence) 是一个轻量但强大的工具包,帮助用户自动的进行 - 特征工程神经网络架构搜索超参调优以及模型压缩。 -
-

- NNI 管理自动机器学习 (AutoML) 的 Experiment, - 调度运行 - 由调优算法生成的 Trial 任务来找到最好的神经网络架构和/或超参,支持 - 各种训练环境,如 - 本机, - 远程服务器, - OpenPAI, - Kubeflow, - 基于 K8S 的 FrameworkController(如,AKS 等), - DLWorkspace (又称 DLTS), - AML (Azure Machine Learning) - 以及其它云服务。 -

- -
-

使用场景

-
    -
  • 想要在自己的代码、模型中试验不同的自动机器学习算法
  • -
  • 想要在不同的环境中加速运行自动机器学习。
  • -
  • 想要更容易实现或试验新的自动机器学习算法的研究员或数据科学家,包括:超参调优算法,神经网络搜索算法以及模型压缩算法。 -
  • -
  • 在机器学习平台中支持自动机器学习
  • -
-
- - - -
-

NNI 功能一览

-

- NNI 提供命令行工具以及友好的 WebUI 来管理训练的 Experiment。 - 通过可扩展的 API,可定制自动机器学习算法和训练平台。 - 为了方便新用户,NNI 内置了最新的自动机器学习算法,并为流行的训练平台提供了开箱即用的支持。 -

-

- 下表中,包含了 NNI 的功能,同时在不断地增添新功能,也非常希望您能贡献其中。 -

-
- -

- -

- - - - - - - - - - - - - - - - - - - - - - - -
- 框架和库 - - 算法 - - 训练平台 -
内置 -
    -
  • 支持的框架
  • -
      -
    • PyTorch
    • -
    • Keras
    • -
    • TensorFlow
    • -
    • MXNet
    • -
    • Caffe2
    • - 更多...
      -
    -
-
    -
  • 支持的库
  • -
      -
    • Scikit-learn
    • -
    • XGBoost
    • -
    • LightGBM
    • - 更多...
      -
    -
- -
- 超参调优 - - 神经网络架构搜索 - - 模型压缩 - - 特征工程(测试版) - - 提前终止算法 - - - -
参考 - - - - - -
- - -
-

安装

-
-

安装

-

- NNI 支持并在 Ubuntu >= 16.04, macOS >= 10.14.1, 和 Windows 10 >= 1809 通过了测试。 在 python 64-bit >= 3.6 的环境中,只需要运行 pip install 即可完成安装。 -

-
Linux 或 macOS
-
python3 -m pip install --upgrade nni
-
Windows
-
python -m pip install --upgrade nni
-

如果想要尝试最新代码,可通过源代码安装 - NNI。 -

-

Linux 和 macOS 下 NNI 系统需求参考这里,Windows 参考这里

-
-
-

注意:

-
    -
  • 如果遇到任何权限问题,可添加 --user 在用户目录中安装 NNI。
  • -
  • 目前,Windows 上的 NNI 支持本机,远程和 OpenPAI 模式。 强烈推荐使用 Anaconda 或 Miniconda 在 Windows 上安装 NNI
  • -
  • 如果遇到如 Segmentation fault 这样的任何错误请参考 常见问题。 Windows 上的常见问题,参考在 Windows 上使用 NNI。 Windows 上的常见问题,参考在 Windows 上使用 NNI
  • -
-
-
-

验证安装

-

- 以下示例基于 TensorFlow 1.x 构建。 确保运行环境中使用的是 TensorFlow 1.x。 -

-
    -
  • -

    通过克隆源代码下载示例。

    -
    git clone -b v2.6 https://github.com/Microsoft/nni.git
    -
  • -
  • -

    运行 MNIST 示例。

    -
    Linux 或 macOS
    -
    nnictl create --config nni/examples/trials/mnist-tfv1/config.yml
    -
    Windows
    -
    nnictl create --config nni\examples\trials\mnist-tfv1\config_windows.yml
    -
  • -
  • -

    - 在命令行中等待输出 INFO: Successfully started experiment! - 此消息表明 Experiment 已成功启动。 - 通过命令行输出的 Web UI url 来访问 Experiment 的界面。 -

    - -
    -  INFO: Starting restful server...
    -  INFO: Successfully started Restful server!
    -  INFO: Setting local config...
    -  INFO: Successfully set local config!
    -  INFO: Starting experiment...
    -  INFO: Successfully started experiment!
    -  -----------------------------------------------------------------------
    -  The experiment id is egchD4qy
    -  The Web UI urls are: http://223.255.255.1:8080   http://127.0.0.1:8080
    -  -----------------------------------------------------------------------
    -
    -  You can use these commands to get more information about the experiment
    -  -----------------------------------------------------------------------
    -    commands                       description
    -  1. nnictl experiment show        show the information of experiments
    -  2. nnictl trial ls               list all of trial jobs
    -  3. nnictl top                    monitor the status of running experiments
    -  4. nnictl log stderr             show stderr log content
    -  5. nnictl log stdout             show stdout log content
    -  6. nnictl stop                   stop an experiment
    -  7. nnictl trial kill             kill a trial job by id
    -  8. nnictl --help                 get help information about nnictl
    -  -----------------------------------------------------------------------
    -  
    -
  • -
  • - 在浏览器中打开 Web UI 地址,可看到下图的 Experiment 详细信息,以及所有的 Trial 任务。 查看这里的更多页面示例。 - -
- - -
- - -
-

文档

-
    -
  • 要了解 NNI,请阅读 NNI 概述
  • -
  • 要熟悉如何使用 NNI,请阅读文档
  • -
  • 要安装 NNI,请参阅安装 NNI
  • -
-
- - -
-

贡献

-

- 本项目欢迎任何贡献和建议。 大多数贡献都需要你同意参与者许可协议(CLA),来声明你有权,并实际上授予我们有权使用你的贡献。 - 有关详细信息,请访问 https://cla.microsoft.com。 -

-

- 当你提交拉取请求时,CLA 机器人会自动检查你是否需要提供 CLA,并修饰这个拉取请求(例如,标签、注释)。 只需要按照机器人提供的说明进行操作即可。 CLA 只需要同意一次,就能应用到所有的代码仓库上。 -

-

- 该项目采用了 Microsoft 开源行为准则 。 有关详细信息,请参阅行为守则常见问题解答或联系 opencode@microsoft.com 咨询问题或评论。 -

-

- 熟悉贡献协议后,即可按照 NNI 开发人员教程,创建第一个 PR =) 了: -

- -
- - -
-

其它代码库和参考

-

经作者许可的一些 NNI 用法示例和相关文档。

-
    -

    外部代码库

    -
  • 在 NNI 中运行 ENAS
  • -
  • - https://github.com/microsoft/nni/blob/master/examples/feature_engineering/auto-feature-engineering/README_zh_CN.md -
  • -
  • 使用 NNI 的 矩阵分解超参调优
  • -
  • scikit-nni 使用 NNI 为 scikit-learn 开发的超参搜索。
  • -
- - - -
- - -
-

反馈

- -
-
加入聊天组:
- - - - - - - - - - - - - -
Gitter微信
- Gitter - - NNI 微信 -
-
-
- - -
-

相关项目

-

- 以探索先进技术和开放为目标,Microsoft Research (MSR) 还发布了一些相关的开源项目。

-
    -
  • - OpenPAI:作为开源平台,提供了完整的 AI 模型训练和资源管理能力,能轻松扩展,并支持各种规模的私有部署、云和混合环境。 -
  • -
  • - FrameworkController:开源的通用 Kubernetes Pod 控制器,通过单个控制器来编排 Kubernetes 上所有类型的应用。 -
  • -
  • - MMdnn:一个完整、跨框架的解决方案,能够转换、可视化、诊断深度神经网络模型。 MMdnn 中的 "MM" 表示 model management(模型管理),而 "dnn" 是 deep neural network(深度神经网络)的缩写。 -
  • -
  • - SPTAG : Space Partition Tree And Graph (SPTAG) 是用于大规模向量的最近邻搜索场景的开源库。 -
  • -
-

我们鼓励研究人员和学生利用这些项目来加速 AI 开发和研究。

-
- - -
-

许可协议

-

代码库遵循 MIT 许可协议

-
-
\ No newline at end of file +
+ +.. codesnippetcard:: + :icon: ../img/thumbnails/hpo-small.svg + :title: 超参调优 + :link: tutorials/hpo_quickstart_pytorch/main + :seemore: 点这里阅读完整教程 + + .. code-block:: + + params = nni.get_next_parameter() + + class Net(nn.Module): + ... + + model = Net() + optimizer = optim.SGD(model.parameters(), + params['lr'], + params['momentum']) + + for epoch in range(10): + train(...) + + accuracy = test(model) + nni.report_final_result(accuracy) + +.. codesnippetcard:: + :icon: ../img/thumbnails/pruning-small.svg + :title: 模型剪枝 + :link: tutorials/pruning_quick_start_mnist + :seemore: 点这里阅读完整教程 + + .. code-block:: + + # define a config_list + config = [{ + 'sparsity': 0.8, + 'op_types': ['Conv2d'] + }] + + # generate masks for simulated pruning + wrapped_model, masks = \ + L1NormPruner(model, config). \ + compress() + + # apply the masks for real speedup + ModelSpeedup(unwrapped_model, input, masks). \ + speedup_model() + +.. codesnippetcard:: + :icon: ../img/thumbnails/quantization-small.svg + :title: 模型量化 + :link: tutorials/quantization_speedup + :seemore: 点这里阅读完整教程 + + .. code-block:: + + # define a config_list + config = [{ + 'quant_types': ['input', 'weight'], + 'quant_bits': {'input': 8, 'weight': 8}, + 'op_types': ['Conv2d'] + }] + + # in case quantizer needs a extra training + quantizer = QAT_Quantizer(model, config) + quantizer.compress() + # Training... + + # export calibration config and + # generate TensorRT engine for real speedup + calibration_config = quantizer.export_model( + model_path, calibration_path) + engine = ModelSpeedupTensorRT( + model, input_shape, config=calib_config) + engine.compress() + +.. codesnippetcard:: + :icon: ../img/thumbnails/multi-trial-nas-small.svg + :title: 神经网络架构搜索 + :link: tutorials/hello_nas + :seemore: 点这里阅读完整教程 + + .. code-block:: + + # define model space + - self.conv2 = nn.Conv2d(32, 64, 3, 1) + + self.conv2 = nn.LayerChoice([ + + nn.Conv2d(32, 64, 3, 1), + + DepthwiseSeparableConv(32, 64) + + ]) + # search strategy + evaluator + strategy = RegularizedEvolution() + evaluator = FunctionalEvaluator( + train_eval_fn) + + # run experiment + RetiariiExperiment(model_space, + evaluator, strategy).run() + +.. codesnippetcard:: + :icon: ../img/thumbnails/one-shot-nas-small.svg + :title: 单尝试 (One-shot) NAS + :link: nas/exploration_strategy + :seemore: 点这里阅读完整教程 + + .. code-block:: + + # define model space + space = AnySearchSpace() + + # get a darts trainer + trainer = DartsTrainer(space, loss, metrics) + trainer.fit() + + # get final searched architecture + arch = trainer.export() + +.. codesnippetcard:: + :icon: ../img/thumbnails/feature-engineering-small.svg + :title: 特征工程 + :link: feature_engineering/overview + :seemore: 点这里阅读完整教程 + + .. code-block:: + + selector = GBDTSelector() + selector.fit( + X_train, y_train, + lgb_params=lgb_params, + eval_ratio=eval_ratio, + early_stopping_rounds=10, + importance_type='gain', + num_boost_round=1000) + + # get selected features + features = selector.get_selected_features() + +.. End of code snippet card + +.. raw:: html + +
+ +NNI 可降低自动机器学习实验管理的成本 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. codesnippetcard:: + :icon: ../img/thumbnails/training-service-small.svg + :title: 训练平台 + :link: experiment/training_service/overview + :seemore: 点这里了解更多 + + 一个自动机器学习实验通常需要很多次尝试,来找到合适且具有潜力的模型。 + **训练平台** 的目标便是让整个调优过程可以轻松的扩展到分布式平台上,为不同的计算资源(例如本地机器、远端服务器、集群等)提供的统一的用户体验。 + 目前,NNI 已经支持 **超过九种** 训练平台。 + +.. codesnippetcard:: + :icon: ../img/thumbnails/web-portal-small.svg + :title: 网页控制台 + :link: experiment/web_portal/web_portal + :seemore: 点这里了解更多 + + 网页控制台提供了可视化调优过程的能力,让你可以轻松检查、跟踪、控制实验流程。 + + .. image:: ../static/img/webui.gif + :width: 100% + +.. codesnippetcard:: + :icon: ../img/thumbnails/experiment-management-small.svg + :title: 多实验管理 + :link: experiment/experiment_management + :seemore: 点这里了解更多 + + 深度学习模型往往需要多个实验不断迭代,例如用户可能想尝试不同的调优算法,优化他们的搜索空间,或者切换到其他的计算资源。 + **多实验管理** 提供了对多个实验的结果进行聚合和比较的强大能力,极大程度上简化了开发者的开发流程。 + +获取帮助或参与贡献 +------------------------------- + +NNI 使用 `NNI GitHub 仓库 `_ 进行维护。我们在 GitHub 上收集反馈,以及新需求和想法。你可以: + +* 新建一个 `GitHub issue `_ 反馈一个 bug 或者需求。 +* 新建一个 `pull request `_ 以贡献代码(在此之前,请务必确保你已经阅读过 :doc:`贡献指南 `)。 +* 如果你有任何问题,都可以加入 `NNI 讨论 `_。 +* 加入即时聊天群组: + +.. list-table:: + :header-rows: 1 + :widths: auto + + * - Gitter + - 微信 + * - + .. image:: https://user-images.githubusercontent.com/39592018/80665738-e0574a80-8acc-11ea-91bc-0836dc4cbf89.png + - + .. image:: https://github.com/scarlett2018/nniutil/raw/master/wechat.png + +引用 NNI +---------- + +如果你在你的文献中用到了 NNI,请考虑引用我们: + + Microsoft. Neural Network Intelligence (version |release|). https://github.com/microsoft/nni + +Bibtex 格式如下(请将版本号替换成你在使用的特定版本): :: + + @software{nni2021, + author = {{Microsoft}}, + month = {1}, + title = {{Neural Network Intelligence}}, + url = {https://github.com/microsoft/nni}, + version = {2.0}, + year = {2021} + } diff --git a/docs/source/installation.rst b/docs/source/installation.rst index 5688b3b4c832cb889d91e32b11fe1af9e7e9f2d0..8e90c73716a04ab599a1d840fa219507d166b085 100644 --- a/docs/source/installation.rst +++ b/docs/source/installation.rst @@ -1,12 +1,94 @@ -############ -Installation -############ +Install NNI +=========== -Currently we support installation on Linux, Mac and Windows. We also allow you to use docker. +NNI requires Python >= 3.7. +It is tested and supported on Ubuntu >= 18.04, +Windows 10 >= 21H2, and macOS >= 11. -.. toctree:: - :maxdepth: 2 +There are 3 ways to install NNI: - Linux & Mac - Windows - Use Docker \ No newline at end of file +* :ref:`Using pip ` +* :ref:`Build source code ` +* :ref:`Using Docker ` + +.. _installation-pip: + +Using pip +--------- + +NNI provides official packages for x86-64 CPUs. They can be installed with pip: + +.. code-block:: text + + pip install nni + +Or to upgrade to latest version: + +.. code-block:: text + + pip install --latest nni + +You can check installation with: + +.. code-block:: text + + nnictl --version + +On Linux systems without Conda, you may encounter ``bash: nnictl: command not found`` error. +In this case you need to add pip script directory to ``PATH``: + +.. code-block:: bash + + echo 'export PATH=${PATH}:${HOME}/.local/bin' >> ~/.bashrc + source ~/.bashrc + +.. _installation-source: + +Installing from Source Code +--------------------------- + +NNI hosts source code on `GitHub `__. + +NNI has experimental support for ARM64 CPUs, including Apple M1. +It requires to install from source code. + +See :doc:`/notes/build_from_source`. + +.. _installation-docker: + +Using Docker +------------ + +NNI provides official Docker image on `Docker Hub `__. + +.. code-block:: text + + docker pull msranni/nni + +Installing Extra Dependencies +----------------------------- + +Some built-in algorithms of NNI requires extra packages. +Use ``nni[]`` to install their dependencies. + +For example, to install dependencies of :class:`DNGO tuner` : + +.. code-block:: text + + pip install nni[DNGO] + +This command will not reinstall NNI itself, even if it was installed in development mode. + +Alternatively, you may install all extra dependencies at once: + +.. code-block:: text + + pip install nni[all] + +**NOTE**: SMAC tuner depends on swig3, which requires a manual downgrade on Ubuntu: + +.. code-block:: bash + + sudo apt install swig3.0 + sudo rm /usr/bin/swig + sudo ln -s swig3.0 /usr/bin/swig diff --git a/docs/source/installation_zh.rst b/docs/source/installation_zh.rst index cf0e8ccc449fa02d43c94a5cd881bf7f40fea3e3..89ef9d6f77c16c822d67ed250958956c33fa1b2e 100644 --- a/docs/source/installation_zh.rst +++ b/docs/source/installation_zh.rst @@ -1,14 +1,90 @@ -.. c62173d7147a43a13bf2cdf945b82d07 +.. b4703fc8c8e8dc1babdb38ba9ebcd4a6 -############ -安装 -############ +安装 NNI +======== -当前支持在 Linux,macOS 和 Windows 下安装。 还可使用 Docker。 +NNI 依赖于 Python 3.7 或以上版本。 -.. toctree:: - :maxdepth: 2 +您可以通过以下三种方式之一安装 NNI: - Linux 和 macOS - Windows - 使用 Docker \ No newline at end of file +* :ref:`通过 pip 安装` +* :ref:`从源代码编译安装` +* :ref:`使用 Docker 容器` + +.. _zh-installation-pip: + +pip 安装 +-------- + +NNI 为 x86-64 平台提供预编译的安装包,您可以使用 pip 进行安装: + +.. code-block:: text + + pip install nni + +您也可以升级已安装的旧版本 NNI: + +.. code-block:: text + + pip install --latest nni + +安装完成后,请运行以下命令进行检查: + +.. code-block:: text + + nnictl --version + +如果您使用的是 Linux 系统并且没有使用 Conda,您可能会遇到 ``bash: nnictl: command not found`` 错误, +此时您需要将 pip 安装的可执行文件添加到 ``PATH`` 环境变量: + +.. code-block:: bash + + echo 'export PATH=${PATH}:${HOME}/.local/bin' >> ~/.bashrc + source ~/.bashrc + +.. _zh-installation-source: + +编译安装 +-------- + +NNI 项目使用 `GitHub `__ 托管源代码。 + +NNI 对 ARM64 平台(包括苹果 M1)提供实验性支持,如果您希望在此类平台上使用 NNI,请从源代码编译安装。 + +编译步骤请参见英文文档: :doc:`/notes/build_from_source` + +.. _zh-installation-docker: + +Docker 镜像 +----------- + +NNI 在 `Docker Hub `__ 上提供了官方镜像。 + +.. code-block:: text + + docker pull msranni/nni + +安装额外依赖 +------------ + +有一些算法依赖于额外的 pip 包,在使用前需要先指定 ``nni[算法名]`` 安装依赖。以 DNGO 算法为例,使用前请运行以下命令: + +.. code-block:: text + + pip install nni[DNGO] + +如果您已经通过任一种方式安装了 NNI,以上命令不会重新安装或改变 NNI 版本,只会安装 DNGO 算法的额外依赖。 + +您也可以一次性安装所有可选依赖: + +.. code-block:: text + + pip install nni[all] + +**注意**:SMAC 算法依赖于 swig3,在 Ubuntu 系统中需要手动进行降级: + +.. code-block:: bash + + sudo apt install swig3.0 + sudo rm /usr/bin/swig + sudo ln -s swig3.0 /usr/bin/swig diff --git a/docs/source/locales/zh/LC_MESSAGES/compression.po b/docs/source/locales/zh/LC_MESSAGES/compression.po new file mode 100644 index 0000000000000000000000000000000000000000..0ac8fc2776f98a3bb1fce058690356266a30ea38 --- /dev/null +++ b/docs/source/locales/zh/LC_MESSAGES/compression.po @@ -0,0 +1,144 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2022, Microsoft +# This file is distributed under the same license as the NNI package. +# FIRST AUTHOR , 2022. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: NNI \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-04-13 03:14+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.9.1\n" + +#: ../../source/compression/overview.rst:2 +msgid "Overview of NNI Model Compression" +msgstr "" + +#: ../../source/compression/overview.rst:4 +msgid "" +"Deep neural networks (DNNs) have achieved great success in many tasks " +"like computer vision, nature launguage processing, speech processing. " +"However, typical neural networks are both computationally expensive and " +"energy-intensive, which can be difficult to be deployed on devices with " +"low computation resources or with strict latency requirements. Therefore," +" a natural thought is to perform model compression to reduce model size " +"and accelerate model training/inference without losing performance " +"significantly. Model compression techniques can be divided into two " +"categories: pruning and quantization. The pruning methods explore the " +"redundancy in the model weights and try to remove/prune the redundant and" +" uncritical weights. Quantization refers to compress models by reducing " +"the number of bits required to represent weights or activations. We " +"further elaborate on the two methods, pruning and quantization, in the " +"following chapters. Besides, the figure below visualizes the difference " +"between these two methods." +msgstr "" + +#: ../../source/compression/overview.rst:19 +msgid "" +"NNI provides an easy-to-use toolkit to help users design and use model " +"pruning and quantization algorithms. For users to compress their models, " +"they only need to add several lines in their code. There are some popular" +" model compression algorithms built-in in NNI. On the other hand, users " +"could easily customize their new compression algorithms using NNI’s " +"interface." +msgstr "" + +#: ../../source/compression/overview.rst:24 +msgid "There are several core features supported by NNI model compression:" +msgstr "" + +#: ../../source/compression/overview.rst:26 +msgid "Support many popular pruning and quantization algorithms." +msgstr "" + +#: ../../source/compression/overview.rst:27 +msgid "" +"Automate model pruning and quantization process with state-of-the-art " +"strategies and NNI's auto tuning power." +msgstr "" + +#: ../../source/compression/overview.rst:28 +msgid "" +"Speedup a compressed model to make it have lower inference latency and " +"also make it smaller." +msgstr "" + +#: ../../source/compression/overview.rst:29 +msgid "" +"Provide friendly and easy-to-use compression utilities for users to dive " +"into the compression process and results." +msgstr "" + +#: ../../source/compression/overview.rst:30 +msgid "Concise interface for users to customize their own compression algorithms." +msgstr "" + +#: ../../source/compression/overview.rst:34 +msgid "Compression Pipeline" +msgstr "" + +#: ../../source/compression/overview.rst:42 +msgid "" +"The overall compression pipeline in NNI is shown above. For compressing a" +" pretrained model, pruning and quantization can be used alone or in " +"combination. If users want to apply both, a sequential mode is " +"recommended as common practise." +msgstr "" + +#: ../../source/compression/overview.rst:46 +msgid "" +"Note that NNI pruners or quantizers are not meant to physically compact " +"the model but for simulating the compression effect. Whereas NNI speedup " +"tool can truly compress model by changing the network architecture and " +"therefore reduce latency. To obtain a truly compact model, users should " +"conduct :doc:`pruning speedup <../tutorials/pruning_speedup>` or " +":doc:`quantizaiton speedup <../tutorials/quantization_speedup>`. The " +"interface and APIs are unified for both PyTorch and TensorFlow. Currently" +" only PyTorch version has been supported, and TensorFlow version will be " +"supported in future." +msgstr "" + +#: ../../source/compression/overview.rst:52 +msgid "Model Speedup" +msgstr "" + +#: ../../source/compression/overview.rst:54 +msgid "" +"The final goal of model compression is to reduce inference latency and " +"model size. However, existing model compression algorithms mainly use " +"simulation to check the performance (e.g., accuracy) of compressed model." +" For example, using masks for pruning algorithms, and storing quantized " +"values still in float32 for quantization algorithms. Given the output " +"masks and quantization bits produced by those algorithms, NNI can really " +"speedup the model." +msgstr "" + +#: ../../source/compression/overview.rst:59 +msgid "The following figure shows how NNI prunes and speeds up your models." +msgstr "" + +#: ../../source/compression/overview.rst:67 +msgid "" +"The detailed tutorial of Speedup Model with Mask can be found :doc:`here " +"<../tutorials/pruning_speedup>`. The detailed tutorial of Speedup Model " +"with Calibration Config can be found :doc:`here " +"<../tutorials/quantization_speedup>`." +msgstr "" + +#: ../../source/compression/overview.rst:72 +msgid "" +"NNI's model pruning framework has been upgraded to a more powerful " +"version (named pruning v2 before nni v2.6). The old version (`named " +"pruning before nni v2.6 " +"`_) will be " +"out of maintenance. If for some reason you have to use the old pruning, " +"v2.6 is the last nni version to support old pruning version." +msgstr "" + diff --git a/docs/source/locales/zh/LC_MESSAGES/hpo.po b/docs/source/locales/zh/LC_MESSAGES/hpo.po new file mode 100644 index 0000000000000000000000000000000000000000..c3b4da48819b63af78f1fe7001ad003891a2ad23 --- /dev/null +++ b/docs/source/locales/zh/LC_MESSAGES/hpo.po @@ -0,0 +1,211 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2022, Microsoft +# This file is distributed under the same license as the NNI package. +# FIRST AUTHOR , 2022. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: NNI \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-04-20 05:50+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.9.1\n" + +#: ../../source/hpo/overview.rst:2 +msgid "Hyperparameter Optimization Overview" +msgstr "" + +#: ../../source/hpo/overview.rst:4 +msgid "" +"Auto hyperparameter optimization (HPO), or auto tuning, is one of the key" +" features of NNI." +msgstr "" + +#: ../../source/hpo/overview.rst:7 +msgid "Introduction to HPO" +msgstr "" + +#: ../../source/hpo/overview.rst:9 +msgid "" +"In machine learning, a hyperparameter is a parameter whose value is used " +"to control learning process, and HPO is the problem of choosing a set of " +"optimal hyperparameters for a learning algorithm. (`From " +"`__ " +"`Wikipedia " +"`__)" +msgstr "" + +#: ../../source/hpo/overview.rst:14 +msgid "Following code snippet demonstrates a naive HPO process:" +msgstr "" + +#: ../../source/hpo/overview.rst:34 +msgid "" +"You may have noticed, the example will train 4×10×3=120 models in total. " +"Since it consumes so much computing resources, you may want to:" +msgstr "" + +#: ../../source/hpo/overview.rst:37 +msgid "" +":ref:`Find the best hyperparameter set with less iterations. `" +msgstr "" + +#: ../../source/hpo/overview.rst:38 +msgid ":ref:`Train the models on distributed platforms. `" +msgstr "" + +#: ../../source/hpo/overview.rst:39 +msgid "" +":ref:`Have a portal to monitor and control the process. `" +msgstr "" + +#: ../../source/hpo/overview.rst:41 +msgid "NNI will do them for you." +msgstr "" + +#: ../../source/hpo/overview.rst:44 +msgid "Key Features of NNI HPO" +msgstr "" + +#: ../../source/hpo/overview.rst:49 +msgid "Tuning Algorithms" +msgstr "" + +#: ../../source/hpo/overview.rst:51 +msgid "" +"NNI provides *tuners* to speed up the process of finding best " +"hyperparameter set." +msgstr "" + +#: ../../source/hpo/overview.rst:53 +msgid "" +"A tuner, or a tuning algorithm, decides the order in which hyperparameter" +" sets are evaluated. Based on the results of historical hyperparameter " +"sets, an efficient tuner can predict where the best hyperparameters " +"locates around, and finds them in much fewer attempts." +msgstr "" + +#: ../../source/hpo/overview.rst:57 +msgid "" +"The naive example above evaluates all possible hyperparameter sets in " +"constant order, ignoring the historical results. This is the brute-force " +"tuning algorithm called *grid search*." +msgstr "" + +#: ../../source/hpo/overview.rst:60 +msgid "" +"NNI has out-of-the-box support for a variety of popular tuners. It " +"includes naive algorithms like random search and grid search, Bayesian-" +"based algorithms like TPE and SMAC, RL based algorithms like PPO, and " +"much more." +msgstr "" + +#: ../../source/hpo/overview.rst:64 +msgid "Main article: :doc:`tuners`" +msgstr "" + +#: ../../source/hpo/overview.rst:69 +msgid "Training Platforms" +msgstr "" + +#: ../../source/hpo/overview.rst:71 +msgid "" +"If you are not interested in distributed platforms, you can simply run " +"NNI HPO with current computer, just like any ordinary Python library." +msgstr "" + +#: ../../source/hpo/overview.rst:74 +msgid "" +"And when you want to leverage more computing resources, NNI provides " +"built-in integration for training platforms from simple on-premise " +"servers to scalable commercial clouds." +msgstr "" + +#: ../../source/hpo/overview.rst:77 +msgid "" +"With NNI you can write one piece of model code, and concurrently evaluate" +" hyperparameter sets on local machine, SSH servers, Kubernetes-based " +"clusters, AzureML service, and much more." +msgstr "" + +#: ../../source/hpo/overview.rst:80 +msgid "Main article: :doc:`/experiment/training_service/overview`" +msgstr "" + +#: ../../source/hpo/overview.rst:85 +msgid "Web Portal" +msgstr "" + +#: ../../source/hpo/overview.rst:87 +msgid "" +"NNI provides a web portal to monitor training progress, to visualize " +"hyperparameter performance, to manually customize hyperparameters, and to" +" manage multiple HPO experiments." +msgstr "" + +#: ../../source/hpo/overview.rst:90 +msgid "Main article: :doc:`/experiment/web_portal/web_portal`" +msgstr "" + +#: ../../source/hpo/overview.rst:96 +msgid "Tutorials" +msgstr "" + +#: ../../source/hpo/overview.rst:98 +msgid "" +"To start using NNI HPO, choose the quickstart tutorial of your favorite " +"framework:" +msgstr "" + +#: ../../source/hpo/overview.rst:100 +msgid ":doc:`PyTorch tutorial `" +msgstr "" + +#: ../../source/hpo/overview.rst:101 +msgid ":doc:`TensorFlow tutorial `" +msgstr "" + +#: ../../source/hpo/overview.rst:104 +msgid "Extra Features" +msgstr "" + +#: ../../source/hpo/overview.rst:106 +msgid "" +"After you are familiar with basic usage, you can explore more HPO " +"features:" +msgstr "" + +#: ../../source/hpo/overview.rst:108 +msgid "" +":doc:`Use command line tool to create and manage experiments (nnictl) " +"`" +msgstr "" + +#: ../../source/hpo/overview.rst:110 +msgid ":doc:`nnictl example `" +msgstr "" + +#: ../../source/hpo/overview.rst:112 +msgid ":doc:`Early stop non-optimal models (assessor) `" +msgstr "" + +#: ../../source/hpo/overview.rst:113 +msgid ":doc:`TensorBoard integration `" +msgstr "" + +#: ../../source/hpo/overview.rst:114 +msgid ":doc:`Implement your own algorithm `" +msgstr "" + +#: ../../source/hpo/overview.rst:115 +msgid ":doc:`Benchmark tuners `" +msgstr "" + diff --git a/docs/source/locales/zh/LC_MESSAGES/index.po b/docs/source/locales/zh/LC_MESSAGES/index.po new file mode 100644 index 0000000000000000000000000000000000000000..b7024287ada3d783a77f32b815e2dd0124eb6f42 --- /dev/null +++ b/docs/source/locales/zh/LC_MESSAGES/index.po @@ -0,0 +1,219 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2022, Microsoft +# This file is distributed under the same license as the NNI package. +# FIRST AUTHOR , 2022. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: NNI \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-04-20 05:50+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.9.1\n" + +#: ../../source/index.rst:4 ../../source/index.rst:52 +msgid "Get Started" +msgstr "" + +#: ../../source/index.rst:12 +msgid "Model Compression" +msgstr "" + +#: ../../source/index.rst:12 +msgid "User Guide" +msgstr "" + +#: ../../source/index.rst:23 +msgid "Python API" +msgstr "" + +#: ../../source/index.rst:23 +msgid "References" +msgstr "" + +#: ../../source/index.rst:32 +msgid "Misc" +msgstr "" + +#: ../../source/index.rst:2 +msgid "NNI Documentation" +msgstr "" + +#: ../../source/index.rst:44 +msgid "" +"**NNI (Neural Network Intelligence)** is a lightweight but powerful " +"toolkit to help users **automate**:" +msgstr "" + +#: ../../source/index.rst:46 +msgid ":doc:`Hyperparameter Optimization `" +msgstr "" + +#: ../../source/index.rst:47 +msgid ":doc:`Neural Architecture Search `" +msgstr "" + +#: ../../source/index.rst:48 +msgid ":doc:`Model Compression `" +msgstr "" + +#: ../../source/index.rst:49 +msgid ":doc:`Feature Engineering `" +msgstr "" + +#: ../../source/index.rst:54 +msgid "To install the current release:" +msgstr "" + +#: ../../source/index.rst:60 +msgid "" +"See the :doc:`installation guide ` if you need additional " +"help on installation." +msgstr "" + +#: ../../source/index.rst:63 +msgid "Try your first NNI experiment" +msgstr "" + +#: ../../source/index.rst:69 +msgid "" +"You need to have `PyTorch `_ (as well as " +"`torchvision `_) installed " +"to run this experiment." +msgstr "" + +#: ../../source/index.rst:71 +msgid "" +"To start your journey now, please follow the :doc:`absolute quickstart of" +" NNI `!" +msgstr "" + +#: ../../source/index.rst:74 +msgid "Why choose NNI?" +msgstr "" + +#: ../../source/index.rst:77 +msgid "NNI makes AutoML techniques plug-and-play" +msgstr "" + +#: ../../source/index.rst:221 +msgid "NNI eases the effort to scale and manage AutoML experiments" +msgstr "" + +#: ../../source/index.rst:229 +msgid "" +"An AutoML experiment requires many trials to explore feasible and " +"potentially good-performing models. **Training service** aims to make the" +" tuning process easily scalable in a distributed platforms. It provides a" +" unified user experience for diverse computation resources (e.g., local " +"machine, remote servers, AKS). Currently, NNI supports **more than 9** " +"kinds of training services." +msgstr "" + +#: ../../source/index.rst:240 +msgid "" +"Web portal visualizes the tuning process, exposing the ability to " +"inspect, monitor and control the experiment." +msgstr "" + +#: ../../source/index.rst:251 +msgid "" +"The DNN model tuning often requires more than one experiment. Users might" +" try different tuning algorithms, fine-tune their search space, or switch" +" to another training service. **Experiment management** provides the " +"power to aggregate and compare tuning results from multiple experiments, " +"so that the tuning workflow becomes clean and organized." +msgstr "" + +#: ../../source/index.rst:257 +msgid "Get Support and Contribute Back" +msgstr "" + +#: ../../source/index.rst:259 +msgid "" +"NNI is maintained on the `NNI GitHub repository " +"`_. We collect feedbacks and new " +"proposals/ideas on GitHub. You can:" +msgstr "" + +#: ../../source/index.rst:261 +msgid "" +"Open a `GitHub issue `_ for bugs" +" and feature requests." +msgstr "" + +#: ../../source/index.rst:262 +msgid "" +"Open a `pull request `_ to " +"contribute code (make sure to read the :doc:`contribution guide " +"` before doing this)." +msgstr "" + +#: ../../source/index.rst:263 +msgid "" +"Participate in `NNI Discussion " +"`_ for general questions " +"and new ideas." +msgstr "" + +#: ../../source/index.rst:264 +msgid "Join the following IM groups." +msgstr "" + +#: ../../source/index.rst:270 +msgid "Gitter" +msgstr "" + +#: ../../source/index.rst:271 +msgid "WeChat" +msgstr "" + +#: ../../source/index.rst:278 +msgid "Citing NNI" +msgstr "" + +#: ../../source/index.rst:280 +msgid "" +"If you use NNI in a scientific publication, please consider citing NNI in" +" your references." +msgstr "" + +#: ../../source/index.rst:282 +msgid "" +"Microsoft. Neural Network Intelligence (version |release|). " +"https://github.com/microsoft/nni" +msgstr "" + +#: ../../source/index.rst:284 +msgid "" +"Bibtex entry (please replace the version with the particular version you " +"are using): ::" +msgstr "" + +#~ msgid "Hyperparameter Optimization" +#~ msgstr "" + +#~ msgid "To run your first NNI experiment:" +#~ msgstr "" + +#~ msgid "" +#~ "you need to have `PyTorch " +#~ "`_ (as well as " +#~ "`torchvision `_)" +#~ " installed to run this experiment." +#~ msgstr "" + +#~ msgid "" +#~ "Open a `pull request " +#~ "`_ to contribute" +#~ " code (make sure to read the " +#~ "`contribution guide ` before " +#~ "doing this)." +#~ msgstr "" + diff --git a/docs/source/locales/zh/LC_MESSAGES/installation.po b/docs/source/locales/zh/LC_MESSAGES/installation.po new file mode 100644 index 0000000000000000000000000000000000000000..8960bf0f944dd7b0e3f5f29420895a59daf56c87 --- /dev/null +++ b/docs/source/locales/zh/LC_MESSAGES/installation.po @@ -0,0 +1,130 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2022, Microsoft +# This file is distributed under the same license as the NNI package. +# FIRST AUTHOR , 2022. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: NNI \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-04-13 03:14+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.9.1\n" + +#: ../../source/installation.rst:2 +msgid "Install NNI" +msgstr "" + +#: ../../source/installation.rst:4 +msgid "" +"NNI requires Python >= 3.7. It is tested and supported on Ubuntu >= " +"18.04, Windows 10 >= 21H2, and macOS >= 11." +msgstr "" + +#: ../../source/installation.rst:8 +msgid "There are 3 ways to install NNI:" +msgstr "" + +#: ../../source/installation.rst:10 +msgid ":ref:`Using pip `" +msgstr "" + +#: ../../source/installation.rst:11 +msgid ":ref:`Build source code `" +msgstr "" + +#: ../../source/installation.rst:12 +msgid ":ref:`Using Docker `" +msgstr "" + +#: ../../source/installation.rst:17 +msgid "Using pip" +msgstr "" + +#: ../../source/installation.rst:19 +msgid "" +"NNI provides official packages for x86-64 CPUs. They can be installed " +"with pip:" +msgstr "" + +#: ../../source/installation.rst:25 +msgid "Or to upgrade to latest version:" +msgstr "" + +#: ../../source/installation.rst:31 +msgid "You can check installation with:" +msgstr "" + +#: ../../source/installation.rst:37 +msgid "" +"On Linux systems without Conda, you may encounter ``bash: nnictl: command" +" not found`` error. In this case you need to add pip script directory to " +"``PATH``:" +msgstr "" + +#: ../../source/installation.rst:48 +msgid "Installing from Source Code" +msgstr "" + +#: ../../source/installation.rst:50 +msgid "NNI hosts source code on `GitHub `__." +msgstr "" + +#: ../../source/installation.rst:52 +msgid "" +"NNI has experimental support for ARM64 CPUs, including Apple M1. It " +"requires to install from source code." +msgstr "" + +#: ../../source/installation.rst:55 +msgid "See :doc:`/notes/build_from_source`." +msgstr "" + +#: ../../source/installation.rst:60 +msgid "Using Docker" +msgstr "" + +#: ../../source/installation.rst:62 +msgid "" +"NNI provides official Docker image on `Docker Hub " +"`__." +msgstr "" + +#: ../../source/installation.rst:69 +msgid "Installing Extra Dependencies" +msgstr "" + +#: ../../source/installation.rst:71 +msgid "" +"Some built-in algorithms of NNI requires extra packages. Use ``nni" +"[]`` to install their dependencies." +msgstr "" + +#: ../../source/installation.rst:74 +msgid "" +"For example, to install dependencies of :class:`DNGO " +"tuner` :" +msgstr "" + +#: ../../source/installation.rst:80 +msgid "" +"This command will not reinstall NNI itself, even if it was installed in " +"development mode." +msgstr "" + +#: ../../source/installation.rst:82 +msgid "Alternatively, you may install all extra dependencies at once:" +msgstr "" + +#: ../../source/installation.rst:88 +msgid "" +"**NOTE**: SMAC tuner depends on swig3, which requires a manual downgrade " +"on Ubuntu:" +msgstr "" + diff --git a/docs/source/locales/zh/LC_MESSAGES/nas.po b/docs/source/locales/zh/LC_MESSAGES/nas.po new file mode 100644 index 0000000000000000000000000000000000000000..094225265eb477213a620441e09ea0c3c8eafdd3 --- /dev/null +++ b/docs/source/locales/zh/LC_MESSAGES/nas.po @@ -0,0 +1,318 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2022, Microsoft +# This file is distributed under the same license as the NNI package. +# FIRST AUTHOR , 2022. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: NNI \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-04-20 05:50+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.9.1\n" + +#: ../../source/nas/overview.rst:2 +msgid "Overview" +msgstr "" + +#: ../../source/nas/overview.rst:4 +msgid "" +"NNI's latest NAS supports are all based on Retiarii Framework, users who " +"are still on `early version using NNI NAS v1.0 " +"`__ shall migrate your work " +"to Retiarii as soon as possible. We plan to remove the legacy NAS " +"framework in the next few releases." +msgstr "" + +#: ../../source/nas/overview.rst:6 +msgid "" +"PyTorch is the **only supported framework on Retiarii**. Inquiries of NAS" +" support on Tensorflow is in `this discussion " +"`__. If you intend to " +"run NAS with DL frameworks other than PyTorch and Tensorflow, please " +"`open new issues `__ to let us " +"know." +msgstr "" + +#: ../../source/nas/overview.rst:9 +msgid "Basics" +msgstr "" + +#: ../../source/nas/overview.rst:11 +msgid "" +"Automatic neural architecture search is playing an increasingly important" +" role in finding better models. Recent research has proven the " +"feasibility of automatic NAS and has led to models that beat many " +"manually designed and tuned models. Representative works include `NASNet " +"`__, `ENAS " +"`__, `DARTS " +"`__, `Network Morphism " +"`__, and `Evolution " +"`__. In addition, new innovations " +"continue to emerge." +msgstr "" + +#: ../../source/nas/overview.rst:13 +msgid "" +"High-level speaking, aiming to solve any particular task with neural " +"architecture search typically requires: search space design, search " +"strategy selection, and performance evaluation. The three components work" +" together with the following loop (from the famous `NAS survey " +"`__):" +msgstr "" + +#: ../../source/nas/overview.rst:19 +msgid "In this figure:" +msgstr "" + +#: ../../source/nas/overview.rst:21 +msgid "" +"*Model search space* means a set of models from which the best model is " +"explored/searched. Sometimes we use *search space* or *model space* in " +"short." +msgstr "" + +#: ../../source/nas/overview.rst:22 +msgid "" +"*Exploration strategy* is the algorithm that is used to explore a model " +"search space. Sometimes we also call it *search strategy*." +msgstr "" + +#: ../../source/nas/overview.rst:23 +msgid "" +"*Model evaluator* is responsible for training a model and evaluating its " +"performance." +msgstr "" + +#: ../../source/nas/overview.rst:25 +msgid "" +"The process is similar to :doc:`Hyperparameter Optimization " +"`, except that the target is the best architecture rather " +"than hyperparameter. Concretely, an exploration strategy selects an " +"architecture from a predefined search space. The architecture is passed " +"to a performance evaluation to get a score, which represents how well " +"this architecture performs on a particular task. This process is repeated" +" until the search process is able to find the best architecture." +msgstr "" + +#: ../../source/nas/overview.rst:28 +msgid "Key Features" +msgstr "" + +#: ../../source/nas/overview.rst:30 +msgid "" +"The current NAS framework in NNI is powered by the research of `Retiarii:" +" A Deep Learning Exploratory-Training Framework " +"`__, where " +"we highlight the following features:" +msgstr "" + +#: ../../source/nas/overview.rst:32 +msgid ":doc:`Simple APIs to construct search space easily `" +msgstr "" + +#: ../../source/nas/overview.rst:33 +msgid ":doc:`SOTA NAS algorithms to explore search space `" +msgstr "" + +#: ../../source/nas/overview.rst:34 +msgid "" +":doc:`Experiment backend support to scale up experiments on large-scale " +"AI platforms `" +msgstr "" + +#: ../../source/nas/overview.rst:37 +msgid "Why NAS with NNI" +msgstr "" + +#: ../../source/nas/overview.rst:39 +msgid "" +"We list out the three perspectives where NAS can be particularly " +"challegning without NNI. NNI provides solutions to relieve users' " +"engineering effort when they want to try NAS techniques in their own " +"scenario." +msgstr "" + +#: ../../source/nas/overview.rst:42 +msgid "Search Space Design" +msgstr "" + +#: ../../source/nas/overview.rst:44 +msgid "" +"The search space defines which architectures can be represented in " +"principle. Incorporating prior knowledge about typical properties of " +"architectures well-suited for a task can reduce the size of the search " +"space and simplify the search. However, this also introduces a human " +"bias, which may prevent finding novel architectural building blocks that " +"go beyond the current human knowledge. Search space design can be very " +"challenging for beginners, who might not possess the experience to " +"balance the richness and simplicity." +msgstr "" + +#: ../../source/nas/overview.rst:46 +msgid "" +"In NNI, we provide a wide range of APIs to build the search space. There " +"are :doc:`high-level APIs `, that enables the " +"possibility to incorporate human knowledge about what makes a good " +"architecture or search space. There are also :doc:`low-level APIs " +"`, that is a list of primitives to construct a network from " +"operation to operation." +msgstr "" + +#: ../../source/nas/overview.rst:49 +msgid "Exploration strategy" +msgstr "" + +#: ../../source/nas/overview.rst:51 +msgid "" +"The exploration strategy details how to explore the search space (which " +"is often exponentially large). It encompasses the classical exploration-" +"exploitation trade-off since, on the one hand, it is desirable to find " +"well-performing architectures quickly, while on the other hand, premature" +" convergence to a region of suboptimal architectures should be avoided. " +"The \"best\" exploration strategy for a particular scenario is usually " +"found via trial-and-error. As many state-of-the-art strategies are " +"implemented with their own code-base, it becomes very troublesome to " +"switch from one to another." +msgstr "" + +#: ../../source/nas/overview.rst:53 +msgid "" +"In NNI, we have also provided :doc:`a list of strategies " +"`. Some of them are powerful yet time consuming, " +"while others might be suboptimal but really efficient. Given that all " +"strategies are implemented with a unified interface, users can always " +"find one that matches their need." +msgstr "" + +#: ../../source/nas/overview.rst:56 +msgid "Performance estimation" +msgstr "" + +#: ../../source/nas/overview.rst:58 +msgid "" +"The objective of NAS is typically to find architectures that achieve high" +" predictive performance on unseen data. Performance estimation refers to " +"the process of estimating this performance. The problem with performance " +"estimation is mostly its scalability, i.e., how can I run and manage " +"multiple trials simultaneously." +msgstr "" + +#: ../../source/nas/overview.rst:60 +msgid "" +"In NNI, we standardize this process is implemented with :doc:`evaluator " +"`, which is responsible of estimating a model's performance. " +"NNI has quite a few built-in supports of evaluators, ranging from the " +"simplest option, e.g., to perform a standard training and validation of " +"the architecture on data, to complex configurations and implementations. " +"Evaluators are run in *trials*, where trials can be spawn onto " +"distributed platforms with our powerful :doc:`training service " +"`." +msgstr "" + +#: ../../source/nas/overview.rst:63 +msgid "Tutorials" +msgstr "" + +#: ../../source/nas/overview.rst:65 +msgid "" +"To start using NNI NAS framework, we recommend at least going through the" +" following tutorials:" +msgstr "" + +#: ../../source/nas/overview.rst:67 +msgid ":doc:`Quickstart `" +msgstr "" + +#: ../../source/nas/overview.rst:68 +msgid ":doc:`construct_space`" +msgstr "" + +#: ../../source/nas/overview.rst:69 +msgid ":doc:`exploration_strategy`" +msgstr "" + +#: ../../source/nas/overview.rst:70 +msgid ":doc:`evaluator`" +msgstr "" + +#: ../../source/nas/overview.rst:73 +msgid "Resources" +msgstr "" + +#: ../../source/nas/overview.rst:75 +msgid "" +"The following articles will help with a better understanding of the " +"current arts of NAS:" +msgstr "" + +#: ../../source/nas/overview.rst:77 +msgid "" +"`Neural Architecture Search: A Survey " +"`__" +msgstr "" + +#: ../../source/nas/overview.rst:78 +msgid "" +"`A Comprehensive Survey of Neural Architecture Search: Challenges and " +"Solutions `__" +msgstr "" + +#~ msgid "Basics" +#~ msgstr "" + +#~ msgid "Basic Concepts" +#~ msgstr "" + +#~ msgid "" +#~ "The process is similar to " +#~ ":doc:`Hyperparameter Optimization `, " +#~ "except that the target is the best" +#~ " architecture rather than hyperparameter. " +#~ "Concretely, an exploration strategy selects" +#~ " an architecture from a predefined " +#~ "search space. The architecture is passed" +#~ " to a performance evaluation to get" +#~ " a score, which represents how well" +#~ " this architecture performs on a " +#~ "particular task. This process is " +#~ "repeated until the search process is " +#~ "able to find the best architecture." +#~ msgstr "" + +#~ msgid "" +#~ "In NNI, we provide a wide range" +#~ " of APIs to build the search " +#~ "space. There are :doc:`high-level APIs" +#~ " `, that enables incorporating" +#~ " human knowledge about what makes a" +#~ " good architecture or search space. " +#~ "There are also :doc:`low-level APIs " +#~ "`, that is a list of " +#~ "primitives to construct a network from" +#~ " operator to operator." +#~ msgstr "" + +#~ msgid "" +#~ "In NNI, we standardize this process " +#~ "is implemented with :doc:`evaluator " +#~ "`, which is responsible of " +#~ "estimating a model's performance. The " +#~ "choices of evaluators also range from" +#~ " the simplest option, e.g., to " +#~ "perform a standard training and " +#~ "validation of the architecture on data," +#~ " to complex configurations and " +#~ "implementations. Evaluators are run in " +#~ "*trials*, where trials can be spawn " +#~ "onto distributed platforms with our " +#~ "powerful :doc:`training service " +#~ "`." +#~ msgstr "" + diff --git a/docs/source/locales/zh/LC_MESSAGES/quickstart.po b/docs/source/locales/zh/LC_MESSAGES/quickstart.po new file mode 100644 index 0000000000000000000000000000000000000000..38bf534989d43727bc9997f6357381f37bd52b23 --- /dev/null +++ b/docs/source/locales/zh/LC_MESSAGES/quickstart.po @@ -0,0 +1,23 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2022, Microsoft +# This file is distributed under the same license as the NNI package. +# FIRST AUTHOR , 2022. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: NNI \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-04-13 03:14+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.9.1\n" + +#: ../../source/quickstart.rst:2 +msgid "Quickstart" +msgstr "" + diff --git a/docs/source/locales/zh/LC_MESSAGES/sphinx.po b/docs/source/locales/zh/LC_MESSAGES/sphinx.po new file mode 100644 index 0000000000000000000000000000000000000000..b059911f13e0d7cbe4f7f41f959e3c8466dedcf2 --- /dev/null +++ b/docs/source/locales/zh/LC_MESSAGES/sphinx.po @@ -0,0 +1,23 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2022, Microsoft +# This file is distributed under the same license as the NNI package. +# FIRST AUTHOR , 2022. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: NNI \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-04-12 17:35+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.9.1\n" + +#: ../../templates/globaltoc.html:6 +msgid "Overview" +msgstr "" + diff --git a/docs/source/locales/zh/LC_MESSAGES/tutorials.po b/docs/source/locales/zh/LC_MESSAGES/tutorials.po new file mode 100644 index 0000000000000000000000000000000000000000..ad12c7bccff76cdf816f40cf72afeb140b6500df --- /dev/null +++ b/docs/source/locales/zh/LC_MESSAGES/tutorials.po @@ -0,0 +1,773 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2022, Microsoft +# This file is distributed under the same license as the NNI package. +# FIRST AUTHOR , 2022. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: NNI \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-04-20 05:50+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.9.1\n" + +#: ../../source/tutorials/hello_nas.rst:13 +msgid "" +"Click :ref:`here ` to download " +"the full example code" +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:22 +msgid "Hello, NAS!" +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:24 +msgid "" +"This is the 101 tutorial of Neural Architecture Search (NAS) on NNI. In " +"this tutorial, we will search for a neural architecture on MNIST dataset " +"with the help of NAS framework of NNI, i.e., *Retiarii*. We use multi-" +"trial NAS as an example to show how to construct and explore a model " +"space." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:28 +msgid "" +"There are mainly three crucial components for a neural architecture " +"search task, namely," +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:30 +msgid "Model search space that defines a set of models to explore." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:31 +msgid "A proper strategy as the method to explore this model space." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:32 +msgid "" +"A model evaluator that reports the performance of every model in the " +"space." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:34 +msgid "" +"Currently, PyTorch is the only supported framework by Retiarii, and we " +"have only tested **PyTorch 1.7 to 1.10**. This tutorial assumes PyTorch " +"context but it should also apply to other frameworks, which is in our " +"future plan." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:38 +msgid "Define your Model Space" +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:40 +msgid "" +"Model space is defined by users to express a set of models that users " +"want to explore, which contains potentially good-performing models. In " +"this framework, a model space is defined with two parts: a base model and" +" possible mutations on the base model." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:46 +msgid "Define Base Model" +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:48 +msgid "" +"Defining a base model is almost the same as defining a PyTorch (or " +"TensorFlow) model. Usually, you only need to replace the code ``import " +"torch.nn as nn`` with ``import nni.retiarii.nn.pytorch as nn`` to use our" +" wrapped PyTorch modules." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:52 +msgid "Below is a very simple example of defining a base model." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:93 +msgid "" +"Always keep in mind that you should use ``import nni.retiarii.nn.pytorch " +"as nn`` and :meth:`nni.retiarii.model_wrapper`. Many mistakes are a " +"result of forgetting one of those. Also, please use ``torch.nn`` for " +"submodules of ``nn.init``, e.g., ``torch.nn.init`` instead of " +"``nn.init``." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:98 +msgid "Define Model Mutations" +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:100 +msgid "" +"A base model is only one concrete model not a model space. We provide " +":doc:`API and Primitives ` for users to express how" +" the base model can be mutated. That is, to build a model space which " +"includes many models." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:103 +msgid "Based on the above base model, we can define a model space as below." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:134 +msgid "This results in the following code:" +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:189 +#: ../../source/tutorials/hello_nas.rst:259 +#: ../../source/tutorials/hello_nas.rst:471 +#: ../../source/tutorials/hello_nas.rst:564 +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:244 +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:281 +#: ../../source/tutorials/pruning_quick_start_mnist.rst:65 +#: ../../source/tutorials/pruning_quick_start_mnist.rst:107 +#: ../../source/tutorials/pruning_quick_start_mnist.rst:172 +#: ../../source/tutorials/pruning_quick_start_mnist.rst:218 +#: ../../source/tutorials/pruning_quick_start_mnist.rst:255 +#: ../../source/tutorials/pruning_quick_start_mnist.rst:283 +msgid "Out:" +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:210 +msgid "" +"This example uses two mutation APIs, :class:`nn.LayerChoice " +"` and :class:`nn.InputChoice " +"`. :class:`nn.LayerChoice " +"` takes a list of candidate modules " +"(two in this example), one will be chosen for each sampled model. It can " +"be used like normal PyTorch module. :class:`nn.InputChoice " +"` takes a list of candidate values, " +"one will be chosen to take effect for each sampled model." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:219 +msgid "" +"More detailed API description and usage can be found :doc:`here " +"`." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:223 +msgid "" +"We are actively enriching the mutation APIs, to facilitate easy " +"construction of model space. If the currently supported mutation APIs " +"cannot express your model space, please refer to :doc:`this doc " +"` for customizing mutators." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:228 +msgid "Explore the Defined Model Space" +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:230 +msgid "" +"There are basically two exploration approaches: (1) search by evaluating " +"each sampled model independently, which is the search approach in :ref" +":`multi-trial NAS ` and (2) one-shot weight-sharing " +"based search, which is used in one-shot NAS. We demonstrate the first " +"approach in this tutorial. Users can refer to :ref:`here ` " +"for the second approach." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:235 +msgid "" +"First, users need to pick a proper exploration strategy to explore the " +"defined model space. Second, users need to pick or customize a model " +"evaluator to evaluate the performance of each explored model." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:239 +msgid "Pick an exploration strategy" +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:241 +msgid "" +"Retiarii supports many :doc:`exploration strategies " +"`." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:243 +msgid "Simply choosing (i.e., instantiate) an exploration strategy as below." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:273 +msgid "Pick or customize a model evaluator" +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:275 +msgid "" +"In the exploration process, the exploration strategy repeatedly generates" +" new models. A model evaluator is for training and validating each " +"generated model to obtain the model's performance. The performance is " +"sent to the exploration strategy for the strategy to generate better " +"models." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:279 +msgid "" +"Retiarii has provided :doc:`built-in model evaluators `, " +"but to start with, it is recommended to use :class:`FunctionalEvaluator " +"`, that is, to wrap your own " +"training and evaluation code with one single function. This function " +"should receive one single model class and uses " +":func:`nni.report_final_result` to report the final score of this model." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:284 +msgid "" +"An example here creates a simple evaluator that runs on MNIST dataset, " +"trains for 2 epochs, and reports its validation accuracy." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:367 +msgid "Create the evaluator" +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:386 +msgid "" +"The ``train_epoch`` and ``test_epoch`` here can be any customized " +"function, where users can write their own training recipe." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:389 +msgid "" +"It is recommended that the ``evaluate_model`` here accepts no additional " +"arguments other than ``model_cls``. However, in the :doc:`advanced " +"tutorial `, we will show how to use additional arguments " +"in case you actually need those. In future, we will support mutation on " +"the arguments of evaluators, which is commonly called \"Hyper-parmeter " +"tuning\"." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:394 +msgid "Launch an Experiment" +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:396 +msgid "" +"After all the above are prepared, it is time to start an experiment to do" +" the model search. An example is shown below." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:417 +msgid "" +"The following configurations are useful to control how many trials to run" +" at most / at the same time." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:436 +msgid "" +"Remember to set the following config if you want to GPU. " +"``use_active_gpu`` should be set true if you wish to use an occupied GPU " +"(possibly running a GUI)." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:456 +msgid "" +"Launch the experiment. The experiment should take several minutes to " +"finish on a workstation with 2 GPUs." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:495 +msgid "" +"Users can also run Retiarii Experiment with :doc:`different training " +"services ` besides ``local`` " +"training service." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:499 +msgid "Visualize the Experiment" +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:501 +msgid "" +"Users can visualize their experiment in the same way as visualizing a " +"normal hyper-parameter tuning experiment. For example, open " +"``localhost:8081`` in your browser, 8081 is the port that you set in " +"``exp.run``. Please refer to :doc:`here " +"` for details." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:505 +msgid "" +"We support visualizing models with 3rd-party visualization engines (like " +"`Netron `__). This can be used by clicking " +"``Visualization`` in detail panel for each trial. Note that current " +"visualization is based on `onnx `__ , thus " +"visualization is not feasible if the model cannot be exported into onnx." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:510 +msgid "" +"Built-in evaluators (e.g., Classification) will automatically export the " +"model into a file. For your own evaluator, you need to save your file " +"into ``$NNI_OUTPUT_DIR/model.onnx`` to make this work. For instance," +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:541 +msgid "Relaunch the experiment, and a button is shown on Web portal." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:546 +msgid "Export Top Models" +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:548 +msgid "" +"Users can export top models after the exploration is done using " +"``export_top_models``." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:575 +msgid "" +"The output is ``json`` object which records the mutation actions of the " +"top model. If users want to output source code of the top model, they can" +" use :ref:`graph-based execution engine ` " +"for the experiment, by simply adding the following two lines." +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:597 +msgid "**Total running time of the script:** ( 2 minutes 4.499 seconds)" +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:612 +msgid ":download:`Download Python source code: hello_nas.py `" +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:618 +msgid ":download:`Download Jupyter notebook: hello_nas.ipynb `" +msgstr "" + +#: ../../source/tutorials/hello_nas.rst:625 +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:335 +#: ../../source/tutorials/pruning_quick_start_mnist.rst:357 +msgid "`Gallery generated by Sphinx-Gallery `_" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:13 +msgid "" +"Click :ref:`here " +"` to download" +" the full example code" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:22 +msgid "HPO Quickstart with PyTorch" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:23 +msgid "" +"This tutorial optimizes the model in `official PyTorch quickstart`_ with " +"auto-tuning." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:25 +msgid "The tutorial consists of 4 steps:" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:27 +msgid "Modify the model for auto-tuning." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:28 +msgid "Define hyperparameters' search space." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:29 +msgid "Configure the experiment." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:30 +msgid "Run the experiment." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:37 +msgid "Step 1: Prepare the model" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:38 +msgid "In first step, we need to prepare the model to be tuned." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:40 +msgid "" +"The model should be put in a separate script. It will be evaluated many " +"times concurrently, and possibly will be trained on distributed " +"platforms." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:44 +msgid "In this tutorial, the model is defined in :doc:`model.py `." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:46 +msgid "In short, it is a PyTorch model with 3 additional API calls:" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:48 +msgid "" +"Use :func:`nni.get_next_parameter` to fetch the hyperparameters to be " +"evalutated." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:49 +msgid "" +"Use :func:`nni.report_intermediate_result` to report per-epoch accuracy " +"metrics." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:50 +msgid "Use :func:`nni.report_final_result` to report final accuracy." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:52 +msgid "Please understand the model code before continue to next step." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:57 +msgid "Step 2: Define search space" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:58 +msgid "" +"In model code, we have prepared 3 hyperparameters to be tuned: " +"*features*, *lr*, and *momentum*." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:61 +msgid "" +"Here we need to define their *search space* so the tuning algorithm can " +"sample them in desired range." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:63 +msgid "Assuming we have following prior knowledge for these hyperparameters:" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:65 +msgid "*features* should be one of 128, 256, 512, 1024." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:66 +msgid "" +"*lr* should be a float between 0.0001 and 0.1, and it follows exponential" +" distribution." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:67 +msgid "*momentum* should be a float between 0 and 1." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:69 +msgid "" +"In NNI, the space of *features* is called ``choice``; the space of *lr* " +"is called ``loguniform``; and the space of *momentum* is called " +"``uniform``. You may have noticed, these names are derived from " +"``numpy.random``." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:74 +msgid "" +"For full specification of search space, check :doc:`the reference " +"`." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:76 +msgid "Now we can define the search space as follow:" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:99 +msgid "Step 3: Configure the experiment" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:100 +msgid "" +"NNI uses an *experiment* to manage the HPO process. The *experiment " +"config* defines how to train the models and how to explore the search " +"space." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:103 +msgid "" +"In this tutorial we use a *local* mode experiment, which means models " +"will be trained on local machine, without using any special training " +"platform." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:122 +msgid "Now we start to configure the experiment." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:125 +msgid "Configure trial code" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:126 +msgid "" +"In NNI evaluation of each hyperparameter set is called a *trial*. So the " +"model script is called *trial code*." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:144 +msgid "" +"When ``trial_code_directory`` is a relative path, it relates to current " +"working directory. To run ``main.py`` in a different path, you can set " +"trial code directory to ``Path(__file__).parent``. (`__file__ " +"`__ is " +"only available in standard Python, not in Jupyter Notebook.)" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:151 +msgid "" +"If you are using Linux system without Conda, you may need to change " +"``\"python model.py\"`` to ``\"python3 model.py\"``." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:157 +msgid "Configure search space" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:175 +msgid "Configure tuning algorithm" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:176 +msgid "Here we use :doc:`TPE tuner `." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:195 +msgid "Configure how many trials to run" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:196 +msgid "" +"Here we evaluate 10 sets of hyperparameters in total, and concurrently " +"evaluate 2 sets at a time." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:213 +msgid "You may also set ``max_experiment_duration = '1h'`` to limit running time." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:215 +msgid "" +"If neither ``max_trial_number`` nor ``max_experiment_duration`` are set, " +"the experiment will run forever until you press Ctrl-C." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:220 +msgid "" +"``max_trial_number`` is set to 10 here for a fast example. In real world " +"it should be set to a larger number. With default config TPE tuner " +"requires 20 trials to warm up." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:227 +msgid "Step 4: Run the experiment" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:228 +msgid "" +"Now the experiment is ready. Choose a port and launch it. (Here we use " +"port 8080.)" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:230 +msgid "" +"You can use the web portal to view experiment status: " +"http://localhost:8080." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:260 +msgid "After the experiment is done" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:261 +msgid "Everything is done and it is safe to exit now. The following are optional." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:263 +msgid "" +"If you are using standard Python instead of Jupyter Notebook, you can add" +" ``input()`` or ``signal.pause()`` to prevent Python from exiting, " +"allowing you to view the web portal after the experiment is done." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:293 +msgid "" +":meth:`nni.experiment.Experiment.stop` is automatically invoked when " +"Python exits, so it can be omitted in your code." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:296 +msgid "" +"After the experiment is stopped, you can run " +":meth:`nni.experiment.Experiment.view` to restart web portal." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:300 +msgid "" +"This example uses :doc:`Python API ` to create " +"experiment." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:302 +msgid "" +"You can also create and manage experiments with :doc:`command line tool " +"<../hpo_nnictl/nnictl>`." +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:307 +msgid "**Total running time of the script:** ( 1 minutes 24.367 seconds)" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:322 +msgid ":download:`Download Python source code: main.py `" +msgstr "" + +#: ../../source/tutorials/hpo_quickstart_pytorch/main.rst:328 +msgid ":download:`Download Jupyter notebook: main.ipynb `" +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:13 +msgid "" +"Click :ref:`here " +"` to download " +"the full example code" +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:22 +msgid "Pruning Quickstart" +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:24 +msgid "" +"Model pruning is a technique to reduce the model size and computation by " +"reducing model weight size or intermediate state size. There are three " +"common practices for pruning a DNN model:" +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:27 +msgid "Pre-training a model -> Pruning the model -> Fine-tuning the pruned model" +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:28 +msgid "" +"Pruning a model during training (i.e., pruning aware training) -> Fine-" +"tuning the pruned model" +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:29 +msgid "Pruning a model -> Training the pruned model from scratch" +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:31 +msgid "" +"NNI supports all of the above pruning practices by working on the key " +"pruning stage. Following this tutorial for a quick look at how to use NNI" +" to prune a model in a common practice." +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:37 +msgid "Preparation" +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:39 +msgid "" +"In this tutorial, we use a simple model and pre-trained on MNIST dataset." +" If you are familiar with defining a model and training in pytorch, you " +"can skip directly to `Pruning Model`_." +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:121 +msgid "Pruning Model" +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:123 +msgid "" +"Using L1NormPruner to prune the model and generate the masks. Usually, a " +"pruner requires original model and ``config_list`` as its inputs. " +"Detailed about how to write ``config_list`` please refer " +":doc:`compression config specification " +"<../compression/compression_config_list>`." +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:127 +msgid "" +"The following `config_list` means all layers whose type is `Linear` or " +"`Conv2d` will be pruned, except the layer named `fc3`, because `fc3` is " +"`exclude`. The final sparsity ratio for each layer is 50%. The layer " +"named `fc3` will not be pruned." +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:153 +msgid "Pruners usually require `model` and `config_list` as input arguments." +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:232 +msgid "" +"Speedup the original model with masks, note that `ModelSpeedup` requires " +"an unwrapped model. The model becomes smaller after speedup, and reaches " +"a higher sparsity ratio because `ModelSpeedup` will propagate the masks " +"across layers." +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:269 +msgid "the model will become real smaller after speedup" +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:307 +msgid "Fine-tuning Compacted Model" +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:308 +msgid "" +"Note that if the model has been sped up, you need to re-initialize a new " +"optimizer for fine-tuning. Because speedup will replace the masked big " +"layers with dense small ones." +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:329 +msgid "**Total running time of the script:** ( 0 minutes 58.337 seconds)" +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:344 +msgid "" +":download:`Download Python source code: pruning_quick_start_mnist.py " +"`" +msgstr "" + +#: ../../source/tutorials/pruning_quick_start_mnist.rst:350 +msgid "" +":download:`Download Jupyter notebook: pruning_quick_start_mnist.ipynb " +"`" +msgstr "" + +#~ msgid "**Total running time of the script:** ( 2 minutes 15.810 seconds)" +#~ msgstr "" + +#~ msgid "NNI HPO Quickstart with PyTorch" +#~ msgstr "" + +#~ msgid "" +#~ "There is also a :doc:`TensorFlow " +#~ "version<../hpo_quickstart_tensorflow/main>` if you " +#~ "prefer it." +#~ msgstr "" + +#~ msgid "" +#~ "You can also create and manage " +#~ "experiments with :doc:`command line tool " +#~ "`." +#~ msgstr "" + +#~ msgid "**Total running time of the script:** ( 1 minutes 24.393 seconds)" +#~ msgstr "" + diff --git a/docs/source/model_compression.rst b/docs/source/model_compression.rst deleted file mode 100644 index 04be65b3a4660c618150b468ab3e206197a52090..0000000000000000000000000000000000000000 --- a/docs/source/model_compression.rst +++ /dev/null @@ -1,34 +0,0 @@ -################# -Model Compression -################# - -Deep neural networks (DNNs) have achieved great success in many tasks. However, typical neural networks are both -computationally expensive and energy intensive, can be difficult to be deployed on devices with low computation -resources or with strict latency requirements. Therefore, a natural thought is to perform model compression to -reduce model size and accelerate model training/inference without losing performance significantly. Model compression -techniques can be divided into two categories: pruning and quantization. The pruning methods explore the redundancy -in the model weights and try to remove/prune the redundant and uncritical weights. Quantization refers to compressing -models by reducing the number of bits required to represent weights or activations. - -NNI provides an easy-to-use toolkit to help user design and use model pruning and quantization algorithms. -It supports Tensorflow and PyTorch with unified interface. -For users to compress their models, they only need to add several lines in their code. -There are some popular model compression algorithms built-in in NNI. -Users could further use NNI's auto tuning power to find the best compressed model, -which is detailed in Auto Model Compression. -On the other hand, users could easily customize their new compression algorithms using NNI's interface. - -For details, please refer to the following tutorials: - -.. toctree:: - :maxdepth: 2 - - Overview - Quick Start - Tutorial - Pruning - Pruning V2 - Quantization - Utilities - Advanced Usage - API Reference diff --git a/docs/source/model_compression_zh.rst b/docs/source/model_compression_zh.rst deleted file mode 100644 index 01f4a37e1070fff87019035e3d8302097a03e27f..0000000000000000000000000000000000000000 --- a/docs/source/model_compression_zh.rst +++ /dev/null @@ -1,36 +0,0 @@ -.. da97b4cdd507bd8fad43d640f3d2bfef - -################# -模型压缩 -################# - -深度神经网络(DNNs)在许多领域都取得了巨大的成功。 然而,典型的神经网络是 -计算和能源密集型的,很难将其部署在计算资源匮乏 -或具有严格延迟要求的设备上。 因此,一个自然的想法就是对模型进行压缩 -以减小模型大小并加速模型训练/推断,同时不会显着降低模型性能。 模型压缩 -技术可以分为两类:剪枝和量化。 剪枝方法探索模型权重中的冗余, -并尝试删除/修剪冗余和非关键的权重。 量化是指通过减少 -权重表示或激活所需的比特数来压缩模型。 - -NNI 提供了易于使用的工具包来帮助用户设计并使用剪枝和量化算法。 -其使用了统一的接口来支持 TensorFlow 和 PyTorch。 -对用户来说, 只需要添加几行代码即可压缩模型。 -NNI 中也内置了一些主流的模型压缩算法。 -用户可以进一步利用 NNI 的自动调优功能找到最佳的压缩模型, -该功能在自动模型压缩部分有详细介绍。 -另一方面,用户可以使用 NNI 的接口自定义新的压缩算法。 - -详细信息,参考以下教程: - -.. toctree:: - :maxdepth: 2 - - 概述 - 快速入门 - 教程 - 剪枝 - 剪枝(V2版本) - 量化 - 工具 - 高级用法 - API 参考 diff --git a/docs/source/nas.rst b/docs/source/nas.rst deleted file mode 100644 index 0c9860388a982341d89a6d2474af3ba5926dde6f..0000000000000000000000000000000000000000 --- a/docs/source/nas.rst +++ /dev/null @@ -1,34 +0,0 @@ -############################################# -Retiarii for Neural Architecture Search (NAS) -############################################# - -Automatic neural architecture search is taking an increasingly important role on finding better models. -Recent research works have proved the feasibility of automatic NAS, and also found some models that could beat manually tuned models. -Some of representative works are NASNet, ENAS, DARTS, Network Morphism, and Evolution. Moreover, new innovations keep emerging. - -However, it takes great efforts to implement NAS algorithms, and it is hard to reuse code base of existing algorithms in a new one. -To facilitate NAS innovations (e.g., design and implement new NAS models, compare different NAS models side-by-side), -an easy-to-use and flexible programming interface is crucial. - -Thus, we design `Retiarii `__. It is a deep learning framework that supports the exploratory training on a neural network model space, rather than on a single neural network model. -Exploratory training with Retiarii allows user to express various search spaces for *Neural Architecture Search* and *Hyper-Parameter Tuning* with high flexibility. - -Some frequently used terminologies in this document: - -* *Model search space*: it means a set of models from which the best model is explored/searched. Sometimes we use *search space* or *model space* in short. -* *Exploration strategy*: the algorithm that is used to explore a model search space. -* *Model evaluator*: it is used to train a model and evaluate the model's performance. - -Follow the instructions below to start your journey with Retiarii. - -.. toctree:: - :maxdepth: 2 - - Overview - Quick Start - Construct Model Space - Multi-trial NAS - One-shot NAS - Hardware-aware NAS - NAS Benchmarks - NAS API References diff --git a/docs/source/nas/advanced_usage.rst b/docs/source/nas/advanced_usage.rst new file mode 100644 index 0000000000000000000000000000000000000000..7cce6fcf1e4e3d6546d41bb156073c774e28b424 --- /dev/null +++ b/docs/source/nas/advanced_usage.rst @@ -0,0 +1,12 @@ +Advanced Usage +============== + +.. toctree:: + :maxdepth: 2 + + execution_engine + hardware_aware_nas + mutator + customize_strategy + serialization + benchmarks_toctree diff --git a/docs/source/nas/benchmarks.rst b/docs/source/nas/benchmarks.rst new file mode 100644 index 0000000000000000000000000000000000000000..7c0ceddf9b18306c72530dc71347050a063e81c8 --- /dev/null +++ b/docs/source/nas/benchmarks.rst @@ -0,0 +1,85 @@ +NAS Benchmark +============= + +.. note:: :doc:`Example usage of NAS benchmarks `. + +To improve the reproducibility of NAS algorithms as well as reducing computing resource requirements, researchers proposed a series of NAS benchmarks such as `NAS-Bench-101 `__, `NAS-Bench-201 `__, `NDS `__, etc. NNI provides a query interface for users to acquire these benchmarks. Within just a few lines of code, researcher are able to evaluate their NAS algorithms easily and fairly by utilizing these benchmarks. + +Prerequisites +------------- + +* Please prepare a folder to household all the benchmark databases. By default, it can be found at ``${HOME}/.cache/nni/nasbenchmark``. Or you can place it anywhere you like, and specify it in ``NASBENCHMARK_DIR`` via ``export NASBENCHMARK_DIR=/path/to/your/nasbenchmark`` before importing NNI. +* Please install ``peewee`` via ``pip3 install peewee``, which NNI uses to connect to database. + +Data Preparation +---------------- + +Option 1 (Recommended) +^^^^^^^^^^^^^^^^^^^^^^ + +You can download the preprocessed benchmark files via ``python -m nni.nas.benchmarks.download ``, where ```` can be ``nasbench101``, ``nasbench201``, and etc. Add ``--help`` to the command for supported command line arguments. + +Option 2 +^^^^^^^^ + +.. note:: If you have files that are processed before v2.5, it is recommended that you delete them and try option 1. + +#. Clone NNI to your machine and enter ``examples/nas/benchmarks`` directory. + + .. code-block:: bash + + git clone -b ${NNI_VERSION} https://github.com/microsoft/nni + cd nni/examples/nas/benchmarks + + Replace ``${NNI_VERSION}`` with a released version name or branch name, e.g., ``v2.4``. + +#. Install dependencies via ``pip3 install -r xxx.requirements.txt``. ``xxx`` can be ``nasbench101``, ``nasbench201`` or ``nds``. + +#. Generate the database via ``./xxx.sh``. The directory that stores the benchmark file can be configured with ``NASBENCHMARK_DIR`` environment variable, which defaults to ``~/.nni/nasbenchmark``. Note that the NAS-Bench-201 dataset will be downloaded from a google drive. + +Please make sure there is at least 10GB free disk space and note that the conversion process can take up to hours to complete. + +Example Usages +-------------- + +Please refer to :doc:`examples usages of Benchmarks API `. + +NAS-Bench-101 +------------- + +* `Paper link `__ +* `Open-source `__ + +NAS-Bench-101 contains 423,624 unique neural networks, combined with 4 variations in number of epochs (4, 12, 36, 108), each of which is trained 3 times. It is a cell-wise search space, which constructs and stacks a cell by enumerating DAGs with at most 7 operators, and no more than 9 connections. All operators can be chosen from ``CONV3X3_BN_RELU``, ``CONV1X1_BN_RELU`` and ``MAXPOOL3X3``, except the first operator (always ``INPUT``\ ) and last operator (always ``OUTPUT``\ ). + +Notably, NAS-Bench-101 eliminates invalid cells (e.g., there is no path from input to output, or there is redundant computation). Furthermore, isomorphic cells are de-duplicated, i.e., all the remaining cells are computationally unique. + +See :doc:`example usages ` and :ref:`API references `. + +NAS-Bench-201 +------------- + +* `Paper link `__ +* `Open-source API `__ +* `Implementations `__ + +NAS-Bench-201 is a cell-wise search space that views nodes as tensors and edges as operators. The search space contains all possible densely-connected DAGs with 4 nodes, resulting in 15,625 candidates in total. Each operator (i.e., edge) is selected from a pre-defined operator set (\ ``NONE``, ``SKIP_CONNECT``, ``CONV_1X1``, ``CONV_3X3`` and ``AVG_POOL_3X3``\ ). Training appraoches vary in the dataset used (CIFAR-10, CIFAR-100, ImageNet) and number of epochs scheduled (12 and 200). Each combination of architecture and training approach is repeated 1 - 3 times with different random seeds. + +See :doc:`example usages ` and :ref:`API references `. + +NDS +--- + +* `Paper link `__ +* `Open-source `__ + +*On Network Design Spaces for Visual Recognition* released trial statistics of over 100,000 configurations (models + hyper-parameters) sampled from multiple model families, including vanilla (feedforward network loosely inspired by VGG), ResNet and ResNeXt (residual basic block and residual bottleneck block) and NAS cells (following popular design from NASNet, Ameoba, PNAS, ENAS and DARTS). Most configurations are trained only once with a fixed seed, except a few that are trained twice or three times. + +Instead of storing results obtained with different configurations in separate files, we dump them into one single database to enable comparison in multiple dimensions. Specifically, we use ``model_family`` to distinguish model types, ``model_spec`` for all hyper-parameters needed to build this model, ``cell_spec`` for detailed information on operators and connections if it is a NAS cell, ``generator`` to denote the sampling policy through which this configuration is generated. Refer to API documentation for details. + +Here is a list of available operators used in NDS. + +.. automodule:: nni.nas.benchmarks.nds.constants + :noindex: + +See :doc:`example usages ` and :ref:`API references `. diff --git a/docs/source/nas/benchmarks_toctree.rst b/docs/source/nas/benchmarks_toctree.rst new file mode 100644 index 0000000000000000000000000000000000000000..e586da641dc85c8c0e8f639e3feb79f8ca100515 --- /dev/null +++ b/docs/source/nas/benchmarks_toctree.rst @@ -0,0 +1,8 @@ +NAS Benchmark +============= + +.. toctree:: + :hidden: + + Overview + Examples diff --git a/docs/source/nas/construct_space.rst b/docs/source/nas/construct_space.rst new file mode 100644 index 0000000000000000000000000000000000000000..f8c4f3822f70b6b8df5a6726248998757d3079b3 --- /dev/null +++ b/docs/source/nas/construct_space.rst @@ -0,0 +1,45 @@ +Construct Model Space +===================== + +NNI provides powerful (and multi-level) APIs for users to easily express model space (or search space). + +* *Mutation Primitives*: high-level APIs (e.g., ValueChoice, LayerChoice) that are utilities to build blocks in search space. In most cases, mutation pritimives should be straightforward yet expressive enough. **We strongly recommend users to try them first,** and report issues if those APIs are not satisfying. +* *Hyper-module Library*: plug-and-play modules that are proved useful. They are usually well studied in research, and comes with pre-searched results. (For example, the optimal activation function in `AutoActivation `__ is reported to be `Swish `__). +* *Mutator*: for advanced users only. NNI provides interface to customize new mutators for expressing more complicated model spaces. + +The following table summarizes all the APIs we have provided for constructing search space. + +.. list-table:: + :header-rows: 1 + :widths: auto + + * - Name + - Category + - Brief Description + * - :class:`LayerChoice ` + - :ref:`Mutation Primitives ` + - Select from some PyTorch modules + * - :class:`InputChoice ` + - :ref:`Mutation Primitives ` + - Select from some inputs (tensors) + * - :class:`ValueChoice ` + - :ref:`Mutation Primitives ` + - Select from some candidate values + * - :class:`Repeat ` + - :ref:`Mutation Primitives ` + - Repeat a block by a variable number of times + * - :class:`Cell ` + - :ref:`Mutation Primitives ` + - Cell structure popularly used in literature + * - :class:`NasBench101Cell ` + - :ref:`Mutation Primitives ` + - Cell structure (variant) proposed by NAS-Bench-101 + * - :class:`NasBench201Cell ` + - :ref:`Mutation Primitives ` + - Cell structure (variant) proposed by NAS-Bench-201 + * - :class:`AutoActivation ` + - :ref:`Hyper-modules Library ` + - Searching for activation functions + * - :class:`Mutator ` + - :doc:`Mutator ` + - Flexible mutations on graphs. :doc:`See tutorial here ` diff --git a/docs/source/nas/customize_strategy.rst b/docs/source/nas/customize_strategy.rst new file mode 100644 index 0000000000000000000000000000000000000000..636e439bcde71f1d1a06abaddff5e73b23ec0993 --- /dev/null +++ b/docs/source/nas/customize_strategy.rst @@ -0,0 +1,98 @@ +Customize Exploration Strategy +============================== + +Customize Multi-trial Strategy +------------------------------ + +If users want to innovate a new exploration strategy, they can easily customize a new one following the interface provided by NNI. Specifically, users should inherit the base strategy class :class:`nni.retiarii.strategy.BaseStrategy`, then implement the member function ``run``. This member function takes ``base_model`` and ``applied_mutators`` as its input arguments. It can simply apply the user specified mutators in ``applied_mutators`` onto ``base_model`` to generate a new model. When a mutator is applied, it should be bound with a sampler (e.g., ``RandomSampler``). Every sampler implements the ``choice`` function which chooses value(s) from candidate values. The ``choice`` functions invoked in mutators are executed with the sampler. + +Below is a very simple random strategy, which makes the choices completely random. + +.. code-block:: python + + from nni.retiarii import Sampler + + class RandomSampler(Sampler): + def choice(self, candidates, mutator, model, index): + return random.choice(candidates) + + class RandomStrategy(BaseStrategy): + def __init__(self): + self.random_sampler = RandomSampler() + + def run(self, base_model, applied_mutators): + _logger.info('stargety start...') + while True: + avail_resource = query_available_resources() + if avail_resource > 0: + model = base_model + _logger.info('apply mutators...') + _logger.info('mutators: %s', str(applied_mutators)) + for mutator in applied_mutators: + mutator.bind_sampler(self.random_sampler) + model = mutator.apply(model) + # run models + submit_models(model) + else: + time.sleep(2) + +You can find that this strategy does not know the search space beforehand, it passively makes decisions every time ``choice`` is invoked from mutators. If a strategy wants to know the whole search space before making any decision (e.g., TPE, SMAC), it can use ``dry_run`` function provided by ``Mutator`` to obtain the space. An example strategy can be found :githublink:`here `. + +After generating a new model, the strategy can use our provided APIs (e.g., :func:`nni.retiarii.execution.submit_models`, :func:`nni.retiarii.execution.is_stopped_exec`) to submit the model and get its reported results. + +Customize a New One-shot Trainer (legacy) +----------------------------------------- + +One-shot trainers should inherit :class:`nni.retiarii.oneshot.BaseOneShotTrainer`, and need to implement ``fit()`` (used to conduct the fitting and searching process) and ``export()`` method (used to return the searched best architecture). + +Writing a one-shot trainer is very different to single-arch evaluator. First of all, there are no more restrictions on init method arguments, any Python arguments are acceptable. Secondly, the model fed into one-shot trainers might be a model with Retiarii-specific modules, such as LayerChoice and InputChoice. Such model cannot directly forward-propagate and trainers need to decide how to handle those modules. + +A typical example is DartsTrainer, where learnable-parameters are used to combine multiple choices in LayerChoice. Retiarii provides ease-to-use utility functions for module-replace purposes, namely :meth:`nni.retiarii.oneshot.pytorch.utils.replace_layer_choice`, :meth:`nni.retiarii.oneshot.pytorch.utils.replace_input_choice`. A simplified example is as follows: + +.. code-block:: python + + from nni.retiarii.oneshot import BaseOneShotTrainer + from nni.retiarii.oneshot.pytorch.utils import replace_layer_choice, replace_input_choice + + + class DartsLayerChoice(nn.Module): + def __init__(self, layer_choice): + super(DartsLayerChoice, self).__init__() + self.name = layer_choice.label + self.op_choices = nn.ModuleDict(layer_choice.named_children()) + self.alpha = nn.Parameter(torch.randn(len(self.op_choices)) * 1e-3) + + def forward(self, *args, **kwargs): + op_results = torch.stack([op(*args, **kwargs) for op in self.op_choices.values()]) + alpha_shape = [-1] + [1] * (len(op_results.size()) - 1) + return torch.sum(op_results * F.softmax(self.alpha, -1).view(*alpha_shape), 0) + + + class DartsTrainer(BaseOneShotTrainer): + + def __init__(self, model, loss, metrics, optimizer): + self.model = model + self.loss = loss + self.metrics = metrics + self.num_epochs = 10 + + self.nas_modules = [] + replace_layer_choice(self.model, DartsLayerChoice, self.nas_modules) + + ... # init dataloaders and optimizers + + def fit(self): + for i in range(self.num_epochs): + for (trn_X, trn_y), (val_X, val_y) in zip(self.train_loader, self.valid_loader): + self.train_architecture(val_X, val_y) + self.train_model_weight(trn_X, trn_y) + + @torch.no_grad() + def export(self): + result = dict() + for name, module in self.nas_modules: + if name not in result: + result[name] = select_best_of_module(module) + return result + +The full code of DartsTrainer is available to Retiarii source code. Please have a check at :githublink:`DartsTrainer `. diff --git a/docs/source/NAS/ModelEvaluators.rst b/docs/source/nas/evaluator.rst similarity index 71% rename from docs/source/NAS/ModelEvaluators.rst rename to docs/source/nas/evaluator.rst index 670014d9711af6c18cdc071cfd3122c1d13c8d8d..78a1f2e95d498ccdf890250966e7c20603952097 100644 --- a/docs/source/NAS/ModelEvaluators.rst +++ b/docs/source/nas/evaluator.rst @@ -1,12 +1,14 @@ -Model Evaluators -================ +Model Evaluator +=============== A model evaluator is for training and validating each generated model. They are necessary to evaluate the performance of new explored models. +.. _functional-evaluator: + Customize Evaluator with Any Function ------------------------------------- -The simplest way to customize a new evaluator is with functional APIs, which is very easy when training code is already available. Users only need to write a fit function that wraps everything, which usually includes training, validating and testing of a single model. This function takes one positional arguments (``model_cls``) and possible keyword arguments. The keyword arguments (other than ``model_cls``) are fed to FunctionEvaluator as its initialization parameters (note that they will be `serialized <./Serialization.rst>`__). In this way, users get everything under their control, but expose less information to the framework and as a result, further optimizations like `CGO <./ExecutionEngines.rst#cgo-execution-engine-experimental>`__ might be not feasible. An example is as belows: +The simplest way to customize a new evaluator is with :class:`FunctionalEvaluator `, which is very easy when training code is already available. Users only need to write a fit function that wraps everything, which usually includes training, validating and testing of a single model. This function takes one positional arguments (``model_cls``) and possible keyword arguments. The keyword arguments (other than ``model_cls``) are fed to :class:`FunctionalEvaluator ` as its initialization parameters (note that they will be :doc:`serialized <./serialization>`). In this way, users get everything under their control, but expose less information to the framework and as a result, further optimizations like :ref:`CGO ` might be not feasible. An example is as belows: .. code-block:: python @@ -46,12 +48,15 @@ Evaluators with PyTorch-Lightning Use Built-in Evaluators ^^^^^^^^^^^^^^^^^^^^^^^ -NNI provides some commonly used model evaluators for users' convenience. These evaluators are built upon the awesome library PyTorch-Lightning. +NNI provides some commonly used model evaluators for users' convenience. These evaluators are built upon the awesome library PyTorch-Lightning. Read the :doc:`reference ` for their detailed usages. + +* :class:`nni.retiarii.evaluator.pytorch.Classification`: for classification tasks. +* :class:`nni.retiarii.evaluator.pytorch.Regression`: for regression tasks. -We recommend to read the `serialization tutorial <./Serialization.rst>`__ before using these evaluators. A few notes to summarize the tutorial: +We recommend to read the :doc:`serialization tutorial ` before using these evaluators. A few notes to summarize the tutorial: -1. ``pl.DataLoader`` should be used in place of ``torch.utils.data.DataLoader``. -2. The datasets used in data-loader should be decorated with ``nni.trace`` recursively. +1. :class:`nni.retiarii.evaluator.pytorch.DataLoader` should be used in place of ``torch.utils.data.DataLoader``. +2. The datasets used in data-loader should be decorated with :meth:`nni.trace` recursively. For example, @@ -69,18 +74,12 @@ For example, val_dataloaders=pl.DataLoader(test_dataset, batch_size=100), max_epochs=10) -.. autoclass:: nni.retiarii.evaluator.pytorch.lightning.Classification - :noindex: - -.. autoclass:: nni.retiarii.evaluator.pytorch.lightning.Regression - :noindex: - Customize Evaluator with PyTorch-Lightning ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Another approach is to write training code in PyTorch-Lightning style, that is, to write a LightningModule that defines all elements needed for training (e.g., loss function, optimizer) and to define a trainer that takes (optional) dataloaders to execute the training. Before that, please read the `document of PyTorch-lightning `__ to learn the basic concepts and components provided by PyTorch-lightning. -In practice, writing a new training module in Retiarii should inherit ``nni.retiarii.evaluator.pytorch.lightning.LightningModule``, which has a ``set_model`` that will be called after ``__init__`` to save the candidate model (generated by strategy) as ``self.model``. The rest of the process (like ``training_step``) should be the same as writing any other lightning module. Evaluators should also communicate with strategies via two API calls (``nni.report_intermediate_result`` for periodical metrics and ``nni.report_final_result`` for final metrics), added in ``on_validation_epoch_end`` and ``teardown`` respectively. +In practice, writing a new training module in Retiarii should inherit :class:`nni.retiarii.evaluator.pytorch.LightningModule`, which has a ``set_model`` that will be called after ``__init__`` to save the candidate model (generated by strategy) as ``self.model``. The rest of the process (like ``training_step``) should be the same as writing any other lightning module. Evaluators should also communicate with strategies via two API calls (:meth:`nni.report_intermediate_result` for periodical metrics and :meth:`nni.report_final_result` for final metrics), added in ``on_validation_epoch_end`` and ``teardown`` respectively. An example is as follows: @@ -133,7 +132,7 @@ An example is as follows: if stage == 'fit': nni.report_final_result(self.trainer.callback_metrics['val_loss'].item()) -Then, users need to wrap everything (including LightningModule, trainer and dataloaders) into a ``Lightning`` object, and pass this object into a Retiarii experiment. +Then, users need to wrap everything (including LightningModule, trainer and dataloaders) into a :class:`nni.retiarii.evaluator.pytorch.Lightning` object, and pass this object into a Retiarii experiment. .. code-block:: python diff --git a/docs/source/NAS/ExecutionEngines.rst b/docs/source/nas/execution_engine.rst similarity index 73% rename from docs/source/NAS/ExecutionEngines.rst rename to docs/source/nas/execution_engine.rst index e0e2bb5f5694359dd2f7faac35cc257659050ab6..242d03a95cdceeb754778f7796d6469952cdd7d0 100644 --- a/docs/source/NAS/ExecutionEngines.rst +++ b/docs/source/nas/execution_engine.rst @@ -1,35 +1,37 @@ Execution Engines ================= -Execution engine is for running Retiarii Experiment. NNI supports three execution engines, users can choose a speicific engine according to the type of their model mutation definition and their requirements for cross-model optimizations. +Execution engine is for running Retiarii Experiment. NNI supports three execution engines, users can choose a specific engine according to the type of their model mutation definition and their requirements for cross-model optimizations. -* **Pure-python execution engine** is the default engine, it supports the model space expressed by `inline mutation API <./MutationPrimitives.rst>`__. +* **Pure-python execution engine** is the default engine, it supports the model space expressed by :doc:`mutation primitives `. -* **Graph-based execution engine** supports the use of `inline mutation APIs <./MutationPrimitives.rst>`__ and model spaces represented by `mutators <./Mutators.rst>`__. It requires the user's model to be parsed by `TorchScript `__. +* **Graph-based execution engine** supports the use of :doc:`mutation primitives ` and model spaces represented by :doc:`mutators `. It requires the user's model to be parsed by `TorchScript `__. * **CGO execution engine** has the same requirements and capabilities as the **Graph-based execution engine**. But further enables cross-model optimizations, which makes model space exploration faster. +.. _pure-python-execution-engine: + Pure-python Execution Engine ---------------------------- Pure-python Execution Engine is the default engine, we recommend users to keep using this execution engine, if they are new to NNI NAS. Pure-python execution engine plays magic within the scope of inline mutation APIs, while does not touch the rest of user model. Thus, it has minimal requirement on user model. -One steps are needed to use this engine now. - -1. Add ``@nni.retiarii.model_wrapper`` decorator outside the whole PyTorch model. +Rememeber to add :meth:`nni.retiarii.model_wrapper` decorator outside the whole PyTorch model before using this engine. .. note:: You should always use ``super().__init__()`` instead of ``super(MyNetwork, self).__init__()`` in the PyTorch model, because the latter one has issues with model wrapper. +.. _graph-based-execution-engine: + Graph-based Execution Engine ---------------------------- For graph-based execution engine, it converts user-defined model to a graph representation (called graph IR) using `TorchScript `__, each instantiated module in the model is converted to a subgraph. Then mutations are applied to the graph to generate new graphs. Each new graph is then converted back to PyTorch code and executed on the user specified training service. -Users may find ``@basic_unit`` helpful in some cases. ``@basic_unit`` here means the module will not be converted to a subgraph, instead, it is converted to a single graph node as a basic unit. +Users may find ``@basic_unit`` helpful in some cases. :meth:`nni.retiarii.basic_unit` here means the module will not be converted to a subgraph, instead, it is converted to a single graph node as a basic unit. ``@basic_unit`` is usually used in the following cases: -* When users want to tune initialization parameters of a module using ``ValueChoice``, then decorate the module with ``@basic_unit``. For example, ``self.conv = MyConv(kernel_size=nn.ValueChoice([1, 3, 5]))``, here ``MyConv`` should be decorated. +* When users want to tune initialization parameters of a module using :class:`nni.retiarii.nn.pytorch.ValueChoice`, then decorate the module with ``@basic_unit``. For example, ``self.conv = MyConv(kernel_size=nn.ValueChoice([1, 3, 5]))``, here ``MyConv`` should be decorated. * When a module cannot be successfully parsed to a subgraph, decorate the module with ``@basic_unit``. The parse failure could be due to complex control flow. Currently Retiarii does not support adhoc loop, if there is adhoc loop in a module's forward, this class should be decorated as serializable module. For example, the following ``MyModule`` should be decorated. @@ -43,23 +45,25 @@ Users may find ``@basic_unit`` helpful in some cases. ``@basic_unit`` here means for i in range(10): # <- adhoc loop ... -* Some inline mutation APIs require their handled module to be decorated with ``@basic_unit``. For example, user-defined module that is provided to ``LayerChoice`` as a candidate op should be decorated. +* Some inline mutation APIs require their handled module to be decorated with ``@basic_unit``. For example, user-defined module that is provided to :class:`nni.retiarii.nn.pytorch.LayerChoice` as a candidate op should be decorated. Three steps are need to use graph-based execution engine. 1. Remove ``@nni.retiarii.model_wrapper`` if there is any in your model. -2. Add ``config.execution_engine = 'base'`` to ``RetiariiExeConfig``. The default value of ``execution_engine`` is 'py', which means pure-python execution engine. +2. Add ``config.execution_engine = 'base'`` to :class:`nni.retiarii.experiment.pytorch.RetiariiExeConfig`. The default value of ``execution_engine`` is 'py', which means pure-python execution engine. 3. Add ``@basic_unit`` when necessary following the above guidelines. For exporting top models, graph-based execution engine supports exporting source code for top models by running ``exp.export_top_models(formatter='code')``. +.. _cgo-execution-engine: + CGO Execution Engine (experimental) ----------------------------------- -CGO(Cross-Graph Optimization) execution engine does cross-model optimizations based on the graph-based execution engine. In CGO execution engine, multiple models could be merged and trained together in one trial. +CGO (Cross-Graph Optimization) execution engine does cross-model optimizations based on the graph-based execution engine. In CGO execution engine, multiple models could be merged and trained together in one trial. Currently, it only supports ``DedupInputOptimizer`` that can merge graphs sharing the same dataset to only loading and pre-processing each batch of data once, which can avoid bottleneck on data loading. -.. note :: To use CGO engine, PyTorch-lightning above version 1.4.2 is required. +.. note :: To use CGO engine, PyTorch Lightning of 1.5.x is required. To enable CGO execution engine, you need to follow these steps: @@ -67,7 +71,7 @@ To enable CGO execution engine, you need to follow these steps: 2. Add configurations for remote training service 3. Add configurations for CGO engine - .. code-block:: python +.. code-block:: python exp = RetiariiExperiment(base_model, trainer, mutators, strategy) config = RetiariiExeConfig('remote') @@ -103,4 +107,4 @@ We have already implemented two trainers: :class:`nni.retiarii.evaluator.pytorch Advanced users can also implement their own trainers by inheriting ``MultiModelSupervisedLearningModule``. Sometimes, a mutated model cannot be executed (e.g., due to shape mismatch). When a trial running multiple models contains -a bad model, CGO execution engine will re-run each model independently in seperate trials without cross-model optimizations. +a bad model, CGO execution engine will re-run each model independently in separate trials without cross-model optimizations. diff --git a/docs/source/nas/exploration_strategy.rst b/docs/source/nas/exploration_strategy.rst new file mode 100644 index 0000000000000000000000000000000000000000..0b29976d659ae508244863f195a89a00a649d1ee --- /dev/null +++ b/docs/source/nas/exploration_strategy.rst @@ -0,0 +1,99 @@ +Exploration Strategy +==================== + +There are two types of model space exploration approach: **Multi-trial strategy** and **One-shot strategy**. When the model space has been constructed, users can use either exploration approach to explore the model space. + +* :ref:`Mutli-trial strategy ` trains each sampled model in the model space independently. +* :ref:`One-shot strategy ` samples the model from a super model. + +Here is the list of exploration strategies that NNI has supported. + +.. list-table:: + :header-rows: 1 + :widths: auto + + * - Name + - Category + - Brief Description + * - :class:`Random ` + - :ref:`Multi-trial ` + - Randomly sample an architecture each time + * - :class:`GridSearch ` + - :ref:`Multi-trial ` + - Traverse the search space and try all possibilities + * - :class:`RegularizedEvolution ` + - :ref:`Multi-trial ` + - Evolution algorithm for NAS. `Reference `__ + * - :class:`TPE ` + - :ref:`Multi-trial ` + - Tree-structured Parzen Estimator (TPE). `Reference `__ + * - :class:`PolicyBasedRL ` + - :ref:`Multi-trial ` + - Policy-based reinforcement learning, based on implementation of tianshou. `Reference `__ + * - :ref:`darts-strategy` + - :ref:`One-shot ` + - Continuous relaxation of the architecture representation, allowing efficient search of the architecture using gradient descent. `Reference `__ + * - :ref:`enas-strategy` + - :ref:`One-shot ` + - RL controller learns to generate the best network on a super-net. `Reference `__ + * - :ref:`fbnet-strategy` + - :ref:`One-shot ` + - Choose the best block by using Gumbel Softmax random sampling and differentiable training. `Reference `__ + * - :ref:`spos-strategy` + - :ref:`One-shot ` + - Train a super-net with uniform path sampling. `Reference `__ + * - :ref:`proxylessnas-strategy` + - :ref:`One-shot ` + - A low-memory-consuming optimized version of differentiable architecture search. `Reference `__ + +.. _multi-trial-nas: + +Multi-trial strategy +-------------------- + +Multi-trial NAS means each sampled model from model space is trained independently. A typical multi-trial NAS is `NASNet `__. In multi-trial NAS, users need model evaluator to evaluate the performance of each sampled model, and need an exploration strategy to sample models from a defined model space. Here, users could use NNI provided model evaluators or write their own model evalutor. They can simply choose a exploration strategy. Advanced users can also customize new exploration strategy. + +To use an exploration strategy, users simply instantiate an exploration strategy and pass the instantiated object to :class:`RetiariiExperiment `. Below is a simple example. + +.. code-block:: python + + import nni.retiarii.strategy as strategy + exploration_strategy = strategy.Random(dedup=True) + +Rather than using :class:`strategy.Random `, users can choose one of the strategies from the table above. + +.. _one-shot-nas: + +One-shot strategy +----------------- + +One-shot NAS algorithms leverage weight sharing among models in neural architecture search space to train a supernet, and use this supernet to guide the selection of better models. This type of algorihtms greatly reduces computational resource compared to independently training each model from scratch (which we call "Multi-trial NAS"). + +Currently, the usage of one-shot NAS strategy is a little different from multi-trial strategy. One-shot strategy is implemented with a special type of objects named *Trainer*. Following the common practice of one-shot NAS, *Trainer* trains the super-net and searches for the optimal architecture in a single run. For example, + +.. code-block:: python + + from nni.retiarii.oneshot.pytorch import DartsTrainer + + trainer = DartsTrainer( + model=model, + loss=criterion, + metrics=lambda output, target: accuracy(output, target, topk=(1,)), + optimizer=optim, + dataset=dataset_train, + batch_size=32, + log_frequency=50 + ) + trainer.fit() + +One-shot strategy can be used without :class:`RetiariiExperiment `. Thus, the ``trainer.fit()`` here runs the experiment locally. + +After ``trainer.fit()`` completes, we can use ``trainer.export()`` to export the searched architecture (a dict of choices) to a file. + +.. code-block:: python + + final_architecture = trainer.export() + print('Final architecture:', trainer.export()) + json.dump(trainer.export(), open('checkpoint.json', 'w')) + +.. tip:: The trained super-net (neither the weights or exported JSON) can't be used directly. It's only an intermediate result used for deriving the final architecture. The exported architecture (can be retrieved with :meth:`nni.retiarii.fixed_arch`) needs to be *retrained* with a standard training recipe to get the final model. diff --git a/docs/source/NAS/HardwareAwareNAS.rst b/docs/source/nas/hardware_aware_nas.rst similarity index 65% rename from docs/source/NAS/HardwareAwareNAS.rst rename to docs/source/nas/hardware_aware_nas.rst index afcadb8c6cd0006db31262f0668bb2b4eb0b1068..3b95db9199f8ae443f964292ba77409d01c0f976 100644 --- a/docs/source/NAS/HardwareAwareNAS.rst +++ b/docs/source/nas/hardware_aware_nas.rst @@ -1,7 +1,7 @@ Hardware-aware NAS ================== -.. contents:: +.. This file should be rewritten as a tutorial End-to-end Multi-trial SPOS Demo -------------------------------- @@ -18,17 +18,21 @@ Then run multi-trail SPOS demo: .. code-block:: bash - python ${NNI_ROOT}/examples/nas/oneshot/spos/multi_trial.py + cd ${NNI_ROOT}/examples/nas/oneshot/spos/ + python search.py --latency-filter cortexA76cpu_tflite21 How the demo works ^^^^^^^^^^^^^^^^^^ -To support hardware-aware NAS, you first need a ``Strategy`` that supports filtering the models by latency. We provide such a filter named ``LatencyFilter`` in NNI and initialize a ``Random`` strategy with the filter: +To support hardware-aware NAS, you first need a ``Strategy`` that supports filtering the models by latency. We provide such a filter named ``LatencyFilter`` in NNI and initialize a ``RegularizedEvolution`` strategy with the filter: .. code-block:: python - simple_strategy = strategy.Random(model_filter=LatencyFilter(threshold=100, predictor=base_predictor)) + evolution_strategy = strategy.RegularizedEvolution( + model_filter=latency_filter, + sample_size=args.evolution_sample_size, population_size=args.evolution_population_size, cycles=args.evolution_cycles + ) ``LatencyFilter`` will predict the models\' latency by using nn-Meter and filter out the models whose latency are larger than the threshold (i.e., ``100`` in this example). You can also build your own strategies and filters to support more flexible NAS such as sorting the models according to latency. @@ -37,21 +41,21 @@ Then, pass this strategy to ``RetiariiExperiment``: .. code-block:: python - exp = RetiariiExperiment(base_model, trainer, strategy=simple_strategy) + exp = RetiariiExperiment(base_model, evaluator, strategy=evolution_strategy) exp_config = RetiariiExeConfig('local') ... - exp_config.dummy_input = [1, 3, 32, 32] + exp_config.dummy_input = [1, 3, 224, 224] - exp.run(exp_config, port) + exp.run(exp_config, args.port) -In ``exp_config``, ``dummy_input`` is required for tracing shape info. +In ``exp_config``, ``dummy_input`` is required for tracing shape info in latency predictor. End-to-end ProxylessNAS with Latency Constraints ------------------------------------------------ -`ProxylessNAS `__ is a hardware-aware one-shot NAS algorithm. ProxylessNAS applies the expected latency of the model to build a differentiable metric and design efficient neural network architectures for hardware. The latency loss is added as a regularization term for architecture parameter optimization. In this example, nn-Meter provides a latency estimator to predict expected latency for the mixed operation on other types of mobile and edge hardware. +`ProxylessNAS `__ is a hardware-aware one-shot NAS algorithm. ProxylessNAS applies the expected latency of the model to build a differentiable metric and design efficient neural network architectures for hardware. The latency loss is added as a regularization term for architecture parameter optimization. In this example, nn-Meter provides a latency estimator to predict expected latency for the mixed operation on other types of mobile and edge hardware. To run the one-shot ProxylessNAS demo, first install nn-Meter by running: @@ -61,14 +65,14 @@ To run the one-shot ProxylessNAS demo, first install nn-Meter by running: Then run one-shot ProxylessNAS demo: -```bash -python ${NNI_ROOT}/examples/nas/oneshot/proxylessnas/main.py --applied_hardware --reference_latency -``` +.. code-block:: bash + + python ${NNI_ROOT}/examples/nas/oneshot/proxylessnas/main.py --applied_hardware HARDWARE --reference_latency REFERENCE_LATENCY_MS How the demo works ^^^^^^^^^^^^^^^^^^ -In the implementation of ProxylessNAS ``trainer``, we provide a ``HardwareLatencyEstimator`` which currently builds a lookup table, that stores the measured latency of each candidate building block in the search space. The latency sum of all building blocks in a candidate model will be treated as the model inference latency. The latency prediction is obtained by ``nn-Meter``. ``HardwareLatencyEstimator`` predicts expected latency for the mixed operation based on the path weight of `ProxylessLayerChoice`. With leveraging ``nn-Meter`` in NNI, users can apply ProxylessNAS to search efficient DNN models on more types of edge devices. +In the implementation of ProxylessNAS ``trainer``, we provide a ``HardwareLatencyEstimator`` which currently builds a lookup table, that stores the measured latency of each candidate building block in the search space. The latency sum of all building blocks in a candidate model will be treated as the model inference latency. The latency prediction is obtained by ``nn-Meter``. ``HardwareLatencyEstimator`` predicts expected latency for the mixed operation based on the path weight of ``ProxylessLayerChoice``. With leveraging ``nn-Meter`` in NNI, users can apply ProxylessNAS to search efficient DNN models on more types of edge devices. Despite of ``applied_hardware`` and ``reference_latency``, There are some other parameters related to hardware-aware ProxylessNAS training in this :githublink:`example `: diff --git a/docs/source/NAS/Mutators.rst b/docs/source/nas/mutator.rst similarity index 59% rename from docs/source/NAS/Mutators.rst rename to docs/source/nas/mutator.rst index 3e02f89d467025256491c0471076638205e7ad9b..710dbd17944a8d231648f80ead9fc0549ca03271 100644 --- a/docs/source/NAS/Mutators.rst +++ b/docs/source/nas/mutator.rst @@ -1,9 +1,9 @@ -Express Mutations with Mutators -=============================== +Construct Space with Mutator +============================ -Besides the inline mutation APIs demonstrated `here <./MutationPrimitives.rst>`__, NNI provides a more general approach to express a model space, i.e., *Mutator*, to cover more complex model spaces. Those inline mutation APIs are also implemented with mutator in the underlying system, which can be seen as a special case of model mutation. +Besides the mutation primitives demonstrated in the :doc:`basic tutorial `, NNI provides a more general approach to express a model space, i.e., *Mutator*, to cover more complex model spaces. The high-level APIs are also implemented with mutator in the underlying system, which can be seen as a special case of model mutation. -.. note:: Mutator and inline mutation APIs cannot be used together. +.. warning:: Mutator and inline mutation APIs can NOT be used together. A mutator is a piece of logic to express how to mutate a given model. Users are free to write their own mutators. Then a model space is expressed with a base model and a list of mutators. A model in the model space is sampled by applying the mutators on the base model one after another. An example is shown below. @@ -18,7 +18,7 @@ A mutator is a piece of logic to express how to mutate a given model. Users are Write a mutator --------------- -User-defined mutator should inherit ``Mutator`` class, and implement mutation logic in the member function ``mutate``. +User-defined mutator should inherit :class:`nni.retiarii.Mutator` class, and implement mutation logic in the member function :meth:`nni.retiarii.Mutator.mutate`. .. code-block:: python @@ -35,9 +35,9 @@ User-defined mutator should inherit ``Mutator`` class, and implement mutation lo chosen_op = self.choice(self.candidate_op_list) node.update_operation(chosen_op.type, chosen_op.params) -The input of ``mutate`` is graph IR (Intermediate Representation) of the base model (please refer to `here <./ApiReference.rst>`__ for the format and APIs of the IR), users can mutate the graph using the graph's member functions (e.g., ``get_nodes_by_label``, ``update_operation``). The mutation operations can be combined with the API ``self.choice``, in order to express a set of possible mutations. In the above example, the node's operation can be changed to any operation from ``candidate_op_list``. +The input of :meth:`nni.retiarii.Mutator.mutate` is graph IR (Intermediate Representation) of the base model, users can mutate the graph using the graph's member functions (e.g., :meth:`nni.retiarii.Model.get_nodes_by_label`). The mutation operations can be combined with the API ``self.choice``, in order to express a set of possible mutations. In the above example, the node's operation can be changed to any operation from ``candidate_op_list``. -Use placehoder to make mutation easier: ``nn.Placeholder``. If you want to mutate a subgraph or node of your model, you can define a placeholder in this model to represent the subgraph or node. Then, use mutator to mutate this placeholder to make it real modules. +Use placeholder to make mutation easier: :class:`nni.retiarii.nn.pytorch.Placeholder`. If you want to mutate a subgraph or node of your model, you can define a placeholder in this model to represent the subgraph or node. Then, use mutator to mutate this placeholder to make it real modules. .. code-block:: python @@ -51,7 +51,7 @@ Use placehoder to make mutation easier: ``nn.Placeholder``. If you want to mutat ``label`` is used by mutator to identify this placeholder. The other parameters are the information that is required by mutator. They can be accessed from ``node.operation.parameters`` as a dict, it could include any information that users want to put to pass it to user defined mutator. The complete example code can be found in :githublink:`Mnasnet base model `. -Starting an experiment is almost the same as using inline mutation APIs. The only difference is that the applied mutators should be passed to ``RetiariiExperiment``. Below is a simple example. +Starting an experiment is almost the same as using inline mutation APIs. The only difference is that the applied mutators should be passed to :class:`nni.retiarii.experiment.pytorch.RetiariiExperiment`. Below is a simple example. .. code-block:: python diff --git a/docs/source/nas/overview.rst b/docs/source/nas/overview.rst new file mode 100644 index 0000000000000000000000000000000000000000..14251ac53332f376d305c0588dae7db92972669a --- /dev/null +++ b/docs/source/nas/overview.rst @@ -0,0 +1,78 @@ +Overview +======== + +.. attention:: NNI's latest NAS supports are all based on Retiarii Framework, users who are still on `early version using NNI NAS v1.0 `__ shall migrate your work to Retiarii as soon as possible. We plan to remove the legacy NAS framework in the next few releases. + +.. note:: PyTorch is the **only supported framework on Retiarii**. Inquiries of NAS support on Tensorflow is in `this discussion `__. If you intend to run NAS with DL frameworks other than PyTorch and Tensorflow, please `open new issues `__ to let us know. + +Basics +------ + +Automatic neural architecture search is playing an increasingly important role in finding better models. Recent research has proven the feasibility of automatic NAS and has led to models that beat many manually designed and tuned models. Representative works include `NASNet `__, `ENAS `__, `DARTS `__, `Network Morphism `__, and `Evolution `__. In addition, new innovations continue to emerge. + +High-level speaking, aiming to solve any particular task with neural architecture search typically requires: search space design, search strategy selection, and performance evaluation. The three components work together with the following loop (from the famous `NAS survey `__): + +.. image:: ../../img/nas_abstract_illustration.png + :align: center + :width: 700 + +In this figure: + +* *Model search space* means a set of models from which the best model is explored/searched. Sometimes we use *search space* or *model space* in short. +* *Exploration strategy* is the algorithm that is used to explore a model search space. Sometimes we also call it *search strategy*. +* *Model evaluator* is responsible for training a model and evaluating its performance. + +The process is similar to :doc:`Hyperparameter Optimization `, except that the target is the best architecture rather than hyperparameter. Concretely, an exploration strategy selects an architecture from a predefined search space. The architecture is passed to a performance evaluation to get a score, which represents how well this architecture performs on a particular task. This process is repeated until the search process is able to find the best architecture. + +Key Features +------------ + +The current NAS framework in NNI is powered by the research of `Retiarii: A Deep Learning Exploratory-Training Framework `__, where we highlight the following features: + +* :doc:`Simple APIs to construct search space easily ` +* :doc:`SOTA NAS algorithms to explore search space ` +* :doc:`Experiment backend support to scale up experiments on large-scale AI platforms ` + +Why NAS with NNI +---------------- + +We list out the three perspectives where NAS can be particularly challegning without NNI. NNI provides solutions to relieve users' engineering effort when they want to try NAS techniques in their own scenario. + +Search Space Design +^^^^^^^^^^^^^^^^^^^ + +The search space defines which architectures can be represented in principle. Incorporating prior knowledge about typical properties of architectures well-suited for a task can reduce the size of the search space and simplify the search. However, this also introduces a human bias, which may prevent finding novel architectural building blocks that go beyond the current human knowledge. Search space design can be very challenging for beginners, who might not possess the experience to balance the richness and simplicity. + +In NNI, we provide a wide range of APIs to build the search space. There are :doc:`high-level APIs `, that enables the possibility to incorporate human knowledge about what makes a good architecture or search space. There are also :doc:`low-level APIs `, that is a list of primitives to construct a network from operation to operation. + +Exploration strategy +^^^^^^^^^^^^^^^^^^^^ + +The exploration strategy details how to explore the search space (which is often exponentially large). It encompasses the classical exploration-exploitation trade-off since, on the one hand, it is desirable to find well-performing architectures quickly, while on the other hand, premature convergence to a region of suboptimal architectures should be avoided. The "best" exploration strategy for a particular scenario is usually found via trial-and-error. As many state-of-the-art strategies are implemented with their own code-base, it becomes very troublesome to switch from one to another. + +In NNI, we have also provided :doc:`a list of strategies `. Some of them are powerful yet time consuming, while others might be suboptimal but really efficient. Given that all strategies are implemented with a unified interface, users can always find one that matches their need. + +Performance estimation +^^^^^^^^^^^^^^^^^^^^^^ + +The objective of NAS is typically to find architectures that achieve high predictive performance on unseen data. Performance estimation refers to the process of estimating this performance. The problem with performance estimation is mostly its scalability, i.e., how can I run and manage multiple trials simultaneously. + +In NNI, we standardize this process is implemented with :doc:`evaluator `, which is responsible of estimating a model's performance. NNI has quite a few built-in supports of evaluators, ranging from the simplest option, e.g., to perform a standard training and validation of the architecture on data, to complex configurations and implementations. Evaluators are run in *trials*, where trials can be spawn onto distributed platforms with our powerful :doc:`training service `. + +Tutorials +--------- + +To start using NNI NAS framework, we recommend at least going through the following tutorials: + +* :doc:`Quickstart ` +* :doc:`construct_space` +* :doc:`exploration_strategy` +* :doc:`evaluator` + +Resources +--------- + +The following articles will help with a better understanding of the current arts of NAS: + +* `Neural Architecture Search: A Survey `__ +* `A Comprehensive Survey of Neural Architecture Search: Challenges and Solutions `__ diff --git a/docs/source/nas/overview_zh.rst b/docs/source/nas/overview_zh.rst new file mode 100644 index 0000000000000000000000000000000000000000..b71913cbd4f897fcd042fcf5f2c23e24805a4d3f --- /dev/null +++ b/docs/source/nas/overview_zh.rst @@ -0,0 +1,89 @@ +.. 48c39585a539a877461aadef63078c48 + +神经架构搜索 +=========================== + +.. toctree:: + :hidden: + + 快速入门 + 构建搜索空间 + 探索策略 + 评估器 + 高级用法 + +.. attention:: NNI 最新的架构搜索支持都是基于 Retiarii 框架,还在使用 `NNI 架构搜索的早期版本 `__ 的用户应尽快将您的工作迁移到 Retiarii。我们计划在接下来的几个版本中删除旧的架构搜索框架。 + +.. attention:: PyTorch 是 **Retiarii 唯一支持的框架**。有关 Tensorflow 上架构搜索支持的需求在 `此讨论 `__ 中。另外,如果您打算使用 PyTorch 和 Tensorflow 以外的 DL 框架运行 NAS,请 `创建新 issue `__ 让我们知道。 + +概述 +------ + +自动神经架构搜索 (Neural Architecture Search, NAS)在寻找更好的模型方面发挥着越来越重要的作用。最近的研究证明了自动架构搜索的可行性,并导致模型击败了许多手动设计和调整的模型。其中具有代表性的有 `NASNet `__、 `ENAS `__、 `DARTS `__、 `Network Morphism `__ 和 `进化算法 `__。此外,新的创新正不断涌现。 + +总的来说,使用神经架构搜索解决任何特定任务通常需要:搜索空间设计、搜索策略选择和性能评估。这三个组件形成如下的循环(图来自于 `架构搜索综述 `__): + +.. image:: ../../img/nas_abstract_illustration.png + :align: center + :width: 700 + +在这个图中: + +* *模型搜索空间* 是指一组模型,从中探索/搜索最佳模型,简称为 *搜索空间* 或 *模型空间*。 +* *探索策略* 是用于探索模型搜索空间的算法。有时我们也称它为 *搜索策略*。 +* *模型评估者* 负责训练模型并评估其性能。 + +该过程类似于 :doc:`超参数优化 `,只不过目标是最佳网络结构而不是最优超参数。具体来说,探索策略从预定义的搜索空间中选择架构。该架构被传递给性能评估以获得评分,该评分表示这个网络结构在特定任务上的表现。重复此过程,直到搜索过程能够找到最优的网络结构。 + +主要特点 +------------ + +NNI 中当前的架构搜索框架由 `Retiarii: A Deep Learning Exploratory-Training Framework `__ 的研究支撑,具有以下特点: + +* :doc:`简单的 API,让您轻松构建搜索空间 ` +* :doc:`SOTA 架构搜索算法,以高效探索搜索空间 ` +* :doc:`后端支持,在大规模 AI 平台上运行实验 ` + +为什么使用 NNI 的架构搜索 +------------------------------- + +若没有 NNI,实现架构搜索将极具挑战性,主要包含以下三个方面。当用户想在自己的场景中尝试架构搜索技术时,NNI 提供的解决方案可以极大程度上减轻用户的工作量。 + +搜索空间设计 +^^^^^^^^^^^^^^^^^^^ + +搜索空间定义了架构的可行域集合。为了简化搜索,我们通常需要结合任务相关的先验知识,减小搜索空间的规模。然而,这也引入了人类的偏见,在某种程度上可能会丧失突破人类认知的可能性。无论如何,对于初学者来说,搜索空间设计是一个极具挑战性的任务,因为他们可能无法在简单的空间和丰富的想象力之间取得平衡。 + +在 NNI 中,我们提供了不同层级的 API 来构建搜索空间。有 :doc:`高层 API `,引入大量先验,帮助用户迅速了解什么是好的架构或搜索空间;也有 :doc:`底层 API `,提供了最底层的算子和图变换原语。 + +探索策略 +^^^^^^^^^^^^^^^^^^^^ + +探索策略定义了如何探索搜索空间(通常是指数级规模的)。它包含经典的探索-利用权衡。一方面,我们希望快速找到性能良好的架构;而另一方面,我们也应避免过早收敛到次优架构的区域。我们往往需要通常通过反复试验找到特定场景的“最佳”探索策略。由于许多近期发表的探索策略都是使用自己的代码库实现的,因此从一个切换到另一个变得非常麻烦。 + +在 NNI 中,我们还提供了 :doc:`一系列的探索策略 `。其中一些功能强大但耗时,而另一些可能不能找到最优架构但非常高效。鉴于所有策略都使用统一的用户接口实现,用户可以轻松找到符合他们需求的策略。 + +性能评估 +^^^^^^^^^^^^^^^^^^^^^^ + +架构搜索的目标通常是找到能够在测试数据集表现理想的网络结构。性能评估的作用便是量化每个网络的好坏。其主要难点在于可扩展性,即如何在大规模训练平台上同时运行和管理多个试验。 + +在 NNI 中,我们使用 :doc:`evaluator ` 来标准化性能评估流程。它负责估计模型的性能。NNI 内建了不少性能评估器,从最简单的交叉验证,到复杂的自定义配置。评估器在 *试验 (trials)* 中运行,可以通过我们强大的 :doc:`训练平台 ` 将试验分发到大规模训练平台上。 + +教程 +--------- + +要开始使用 NNI 架构搜索框架,我们建议至少阅读以下教程: + +* :doc:`快速入门 ` +* :doc:`构建搜索空间 ` +* :doc:`探索策略 ` +* :doc:`评估器 ` + +资源 +--------- + +以下文章将有助于更好地了解 NAS 的最新发展: + +* `神经架构搜索:综述 `__ +* `神经架构搜索的综述:挑战和解决方案 `__ diff --git a/docs/source/NAS/Serialization.rst b/docs/source/nas/serialization.rst similarity index 53% rename from docs/source/NAS/Serialization.rst rename to docs/source/nas/serialization.rst index fbe69059ee7045cf5bf100e90eedf958a467fbdc..7f7ae083800c1957e99f7e66ab161743a9c84629 100644 --- a/docs/source/NAS/Serialization.rst +++ b/docs/source/nas/serialization.rst @@ -1,22 +1,22 @@ Serialization ============= -In multi-trial NAS, a sampled model should be able to be executed on a remote machine or a training platform (e.g., AzureML, OpenPAI). "Serialization" enables re-instantiation of model evaluator in another process or machine, such that, both the model and its model evaluator should be correctly serialized. To make NNI correctly serialize model evaluator, users should apply ``nni.trace`` on some of their functions and objects. API references can be found in :func:`nni.trace`. +In multi-trial NAS, a sampled model should be able to be executed on a remote machine or a training platform (e.g., AzureML, OpenPAI). "Serialization" enables re-instantiation of model evaluator in another process or machine, such that, both the model and its model evaluator should be correctly serialized. To make NNI correctly serialize model evaluator, users should apply :func:`nni.trace ` on some of their functions and objects. API references can be found in :func:`nni.trace `. Serialization is implemented as a combination of `json-tricks `_ and `cloudpickle `_. Essentially, it is json-tricks, that is a enhanced version of Python JSON, enabling handling of serialization of numpy arrays, date/times, decimal, fraction and etc. The difference lies in the handling of class instances. Json-tricks deals with class instances with ``__dict__`` and ``__class__``, which in most of our cases are not reliable (e.g., datasets, dataloaders). Rather, our serialization deals with class instances with two methods: -1. If the class / factory that creates the object is decorated with ``nni.trace``, we can serialize the class / factory function, along with the parameters, such that the instance can be re-instantiated. +1. If the class / factory that creates the object is decorated with :func:`nni.trace `, we can serialize the class / factory function, along with the parameters, such that the instance can be re-instantiated. 2. Otherwise, cloudpickle is used to serialize the object into a binary. -The recommendation is, unless you are absolutely certain that there is no problem and extra burden to serialize the object into binary, always add ``nni.trace``. In most cases, it will be more clean and neat, and enables possibilities such as mutation of parameters (will be supported in future). +The recommendation is, unless you are absolutely certain that there is no problem and extra burden to serialize the object into binary, always add :func:`nni.trace `. In most cases, it will be more clean and neat, and enables possibilities such as mutation of parameters (will be supported in future). .. warning:: **What will happen if I forget to "trace" my objects?** - It is likely that the program can still run. NNI will try to serialize the untraced object into a binary. It might fail in complex cases. For example, when the object is too large. Even if it succeeds, the result might be a substantially large object. For example, if you forgot to add ``nni.trace`` on ``MNIST``, the MNIST dataset object wil be serialized into binary, which will be dozens of megabytes because the object has the whole 60k images stored inside. You might see warnings and even errors when running experiments. To avoid such issues, the easiest way is to always remember to add ``nni.trace`` to non-primitive objects. + It is likely that the program can still run. NNI will try to serialize the untraced object into a binary. It might fail in complex cases. For example, when the object is too large. Even if it succeeds, the result might be a substantially large object. For example, if you forgot to add :func:`nni.trace ` on ``MNIST``, the MNIST dataset object wil be serialized into binary, which will be dozens of megabytes because the object has the whole 60k images stored inside. You might see warnings and even errors when running experiments. To avoid such issues, the easiest way is to always remember to add :func:`nni.trace ` to non-primitive objects. -.. note:: In Retiarii, serializer will throw exception when one of an single object in the recursive serialization is larger than 64 KB when binary serialized. This indicates that such object needs to be wrapped by ``nni.trace``. In rare cases, if you insist on pickling large data, the limit can be overridden by setting an environment variable ``PICKLE_SIZE_LIMIT``, whose unit is byte. Please note that even if the experiment might be able to run, this can still cause performance issues and even the crash of NNI experiment. +.. note:: In Retiarii, serializer will throw exception when one of an single object in the recursive serialization is larger than 64 KB when binary serialized. This indicates that such object needs to be wrapped by :func:`nni.trace `. In rare cases, if you insist on pickling large data, the limit can be overridden by setting an environment variable ``PICKLE_SIZE_LIMIT``, whose unit is byte. Please note that even if the experiment might be able to run, this can still cause performance issues and even the crash of NNI experiment. To trace a function or class, users can use decorator like, @@ -26,11 +26,15 @@ To trace a function or class, users can use decorator like, class MyClass: ... -Inline trace that traces instantly on the object instantiation or function invoke is also acceptable: ``nni.trace(MyClass)(parameters)``. +Inline trace that traces instantly on the object instantiation or function invoke is also acceptable: -Assuming a class ``cls`` is already traced, when it is serialized, its class type along with initialization parameters will be dumped. As the parameters are possibly class instances (if not primitive types like ``int`` and ``str``), their serialization will be a similar problem. We recommend decorate them with ``nni.trace`` as well. In other words, ``nni.trace`` should be applied recursively if necessary. +.. code-block:: python + + nni.trace(MyClass)(parameters) + +Assuming a class ``cls`` is already traced, when it is serialized, its class type along with initialization parameters will be dumped. As the parameters are possibly class instances (if not primitive types like ``int`` and ``str``), their serialization will be a similar problem. We recommend decorate them with :func:`nni.trace ` as well. In other words, :func:`nni.trace ` should be applied recursively if necessary. -Below is an example, ``transforms.Compose``, ``transforms.Normalize``, and ``MNIST`` are serialized manually using ``nni.trace``. ``nni.trace`` takes a class / function as its argument, and returns a wrapped class and function that has the same behavior with the original class / function. The usage of the wrapped class / function is also identical to the original one, except that the arguments are recorded. No need to apply ``nni.trace`` to ``pl.Classification`` and ``pl.DataLoader`` because they are already traced. +Below is an example, ``transforms.Compose``, ``transforms.Normalize``, and ``MNIST`` are serialized manually using :func:`nni.trace `. :func:`nni.trace ` takes a class / function as its argument, and returns a wrapped class and function that has the same behavior with the original class / function. The usage of the wrapped class / function is also identical to the original one, except that the arguments are recorded. No need to apply :func:`nni.trace ` to :class:`pl.Classification ` and :class:`pl.DataLoader ` because they are already traced. .. code-block:: python @@ -57,6 +61,6 @@ Below is an example, ``transforms.Compose``, ``transforms.Normalize``, and ``MNI **What's the relationship between model_wrapper, basic_unit and nni.trace?** - They are fundamentally different. ``model_wrapper`` is used to wrap a base model (search space), ``basic_unit`` to annotate a module as primitive. ``nni.trace`` is to enable serialization of general objects. Though they share similar underlying implementations, but do keep in mind that you will experience errors if you mix them up. + They are fundamentally different. :func:`model_wrapper ` is used to wrap a base model (search space), :func:`basic_unit ` to annotate a module as primitive. :func:`nni.trace ` is to enable serialization of general objects. Though they share similar underlying implementations, but do keep in mind that you will experience errors if you mix them up. - .. seealso:: Please refer to API reference of :meth:`nni.retiarii.model_wrapper`, :meth:`nni.retiarii.basic_unit`, and :meth:`nni.trace`. + Please refer to API reference of :meth:`nni.retiarii.model_wrapper`, :meth:`nni.retiarii.basic_unit`, and :func:`nni.trace `. diff --git a/docs/source/nas/toctree.rst b/docs/source/nas/toctree.rst new file mode 100644 index 0000000000000000000000000000000000000000..0307bea2f80a56f2f09f2a34cc3dc3beefd06f80 --- /dev/null +++ b/docs/source/nas/toctree.rst @@ -0,0 +1,12 @@ +Neural Architecture Search +========================== + +.. toctree:: + :hidden: + + overview + Quickstart + construct_space + exploration_strategy + evaluator + advanced_usage diff --git a/docs/source/nas_zh.rst b/docs/source/nas_zh.rst deleted file mode 100644 index 42484805f1637363bfcee467ff7192d0f695e8b4..0000000000000000000000000000000000000000 --- a/docs/source/nas_zh.rst +++ /dev/null @@ -1,36 +0,0 @@ -.. 0b36fb7844fd9cc88c4e74ad2c6b9ece - -########################## -神经网络架构搜索 -########################## - -自动化的神经网络架构(NAS)搜索在寻找更好的模型方面发挥着越来越重要的作用。 -最近的研究工作证明了自动化 NAS 的可行性,并发现了一些超越手动调整的模型。 -代表工作有 NASNet, ENAS, DARTS, Network Morphism, 以及 Evolution 等。 此外,新的创新不断涌现。 - -但是,要实现 NAS 算法需要花费大量的精力,并且很难在新算法中重用现有算法的代码。 -为了促进 NAS 创新 (如, 设计实现新的 NAS 模型,比较不同的 NAS 模型), -易于使用且灵活的编程接口非常重要。 - -因此,NNI 设计了 `Retiarii `__, 它是一个深度学习框架,支持在神经网络模型空间,而不是单个神经网络模型上进行探索性训练。 -Retiarii 的探索性训练允许用户以高度灵活的方式表达 *神经网络架构搜索* 和 *超参数调整* 的各种搜索空间。 - -本文档中的一些常用术语: - -* *Model search space(模型搜索空间)* :它意味着一组模型,用于从中探索/搜索出最佳模型。 有时我们简称为 *search space(搜索空间)* 或 *model space(模型空间)* 。 -* *Exploration strategy(探索策略)*:用于探索模型搜索空间的算法。 -* *Model evaluator(模型评估器)*:用于训练模型并评估模型的性能。 - -按照以下说明开始您的 Retiarii 之旅。 - -.. toctree:: - :maxdepth: 2 - - 概述 - 快速入门 - 构建模型空间 - Multi-trial NAS - One-Shot NAS - 硬件相关 NAS - NAS 基准测试 - NAS API 参考 diff --git a/docs/source/nnSpider.rst b/docs/source/nnSpider.rst deleted file mode 100644 index 0290bce29d337e9377bdc51978802c5a3dc12be2..0000000000000000000000000000000000000000 --- a/docs/source/nnSpider.rst +++ /dev/null @@ -1,90 +0,0 @@ -:orphan: - - -.. raw:: html - -

nnSpider emoticons

- diff --git a/docs/source/nnSpider/comfort.rst b/docs/source/nnSpider/comfort.rst deleted file mode 100644 index 39b266079b6a83557a1598a339dab74d7c3bf67b..0000000000000000000000000000000000000000 --- a/docs/source/nnSpider/comfort.rst +++ /dev/null @@ -1,9 +0,0 @@ -:orphan: - - -.. raw:: html - -

Comfort

-
- Comfort -
diff --git a/docs/source/nnSpider/crying.rst b/docs/source/nnSpider/crying.rst deleted file mode 100644 index 614fff6974c04606099695b98c5dcdbb01e05070..0000000000000000000000000000000000000000 --- a/docs/source/nnSpider/crying.rst +++ /dev/null @@ -1,9 +0,0 @@ -:orphan: - - -.. raw:: html - -

Crying

-
- Crying -
diff --git a/docs/source/nnSpider/cut.rst b/docs/source/nnSpider/cut.rst deleted file mode 100644 index b0bc4775bc4727075d2bdf9f32ba4f86a79ecce4..0000000000000000000000000000000000000000 --- a/docs/source/nnSpider/cut.rst +++ /dev/null @@ -1,9 +0,0 @@ -:orphan: - - -.. raw:: html - -

Cut

-
- Cut -
diff --git a/docs/source/nnSpider/errorEmotion.rst b/docs/source/nnSpider/errorEmotion.rst deleted file mode 100644 index 0bb8992cfbee1f44c5f26470f941487b4de0440a..0000000000000000000000000000000000000000 --- a/docs/source/nnSpider/errorEmotion.rst +++ /dev/null @@ -1,9 +0,0 @@ -:orphan: - - -.. raw:: html - -

Error

-
- Error -
diff --git a/docs/source/nnSpider/holiday.rst b/docs/source/nnSpider/holiday.rst deleted file mode 100644 index 758e33069102940187eeb9a6180719a68b5c20d0..0000000000000000000000000000000000000000 --- a/docs/source/nnSpider/holiday.rst +++ /dev/null @@ -1,9 +0,0 @@ -:orphan: - - -.. raw:: html - -

Holiday

-
- NoBug -
diff --git a/docs/source/nnSpider/nobug.rst b/docs/source/nnSpider/nobug.rst deleted file mode 100644 index 9fe2b3219293dadcc1fa9b4f7b10649b12119329..0000000000000000000000000000000000000000 --- a/docs/source/nnSpider/nobug.rst +++ /dev/null @@ -1,9 +0,0 @@ -:orphan: - - -.. raw:: html - -

NoBug

-
- NoBug -
diff --git a/docs/source/nnSpider/sign.rst b/docs/source/nnSpider/sign.rst deleted file mode 100644 index 2b4aa24553ae92bfc2786f5ac55f50d06c1924b5..0000000000000000000000000000000000000000 --- a/docs/source/nnSpider/sign.rst +++ /dev/null @@ -1,9 +0,0 @@ -:orphan: - - -.. raw:: html - -

Sign

-
- Sign -
diff --git a/docs/source/nnSpider/sweat.rst b/docs/source/nnSpider/sweat.rst deleted file mode 100644 index 9d81ee62a9fbd9ecc9755df3def0e7ca6aaa094a..0000000000000000000000000000000000000000 --- a/docs/source/nnSpider/sweat.rst +++ /dev/null @@ -1,9 +0,0 @@ -:orphan: - - -.. raw:: html - -

Sweat

-
- Sweat -
diff --git a/docs/source/nnSpider/weaving.rst b/docs/source/nnSpider/weaving.rst deleted file mode 100644 index d6e75334ddfe82f5abfc947217ed83aff811ef8c..0000000000000000000000000000000000000000 --- a/docs/source/nnSpider/weaving.rst +++ /dev/null @@ -1,9 +0,0 @@ -:orphan: - - -.. raw:: html - -

Weaving

-
- Weaving -
diff --git a/docs/source/nnSpider/working.rst b/docs/source/nnSpider/working.rst deleted file mode 100644 index 92d91e64c8099a1ccc1287bf757e9466935d59f0..0000000000000000000000000000000000000000 --- a/docs/source/nnSpider/working.rst +++ /dev/null @@ -1,9 +0,0 @@ -:orphan: - - -.. raw:: html - -

Working

-
- Working -
diff --git a/docs/source/notes/architecture_overview.rst b/docs/source/notes/architecture_overview.rst new file mode 100644 index 0000000000000000000000000000000000000000..472676eb883ff88ff31e41b11348f6c50790e90a --- /dev/null +++ b/docs/source/notes/architecture_overview.rst @@ -0,0 +1,85 @@ +:orphan: + +Architecture Overview +===================== + +NNI (Neural Network Intelligence) is a toolkit to help users design and tune machine learning models (e.g., hyperparameters), neural network architectures, or complex system's parameters, in an efficient and automatic way. NNI has several appealing properties: ease-of-use, scalability, flexibility, and efficiency. + +* **Ease-of-use**: NNI can be easily installed through python pip. Only several lines need to be added to your code in order to use NNI's power. You can use both the commandline tool and WebUI to work with your experiments. +* **Scalability**: Tuning hyperparameters or the neural architecture often demands a large number of computational resources, while NNI is designed to fully leverage different computation resources, such as remote machines, training platforms (e.g., OpenPAI, Kubernetes). Hundreds of trials could run in parallel by depending on the capacity of your configured training platforms. +* **Flexibility**: Besides rich built-in algorithms, NNI allows users to customize various hyperparameter tuning algorithms, neural architecture search algorithms, early stopping algorithms, etc. Users can also extend NNI with more training platforms, such as virtual machines, kubernetes service on the cloud. Moreover, NNI can connect to external environments to tune special applications/models on them. +* **Efficiency**: We are intensively working on more efficient model tuning on both the system and algorithm level. For example, we leverage early feedback to speedup the tuning procedure. + +The figure below shows high-level architecture of NNI. + + +.. image:: https://user-images.githubusercontent.com/16907603/92089316-94147200-ee00-11ea-9944-bf3c4544257f.png + :width: 700 + +Key Concepts +------------ + +* *Experiment*: One task of, for example, finding out the best hyperparameters of a model, finding out the best neural network architecture, etc. It consists of trials and AutoML algorithms. + +* *Search Space*: The feasible region for tuning the model. For example, the value range of each hyperparameter. + +* *Configuration*: An instance from the search space, that is, each hyperparameter has a specific value. + +* *Trial*: An individual attempt at applying a new configuration (e.g., a set of hyperparameter values, a specific neural architecture, etc.). Trial code should be able to run with the provided configuration. + +* *Tuner*: An AutoML algorithm, which generates a new configuration for the next try. A new trial will run with this configuration. + +* *Assessor*: Analyze a trial's intermediate results (e.g., periodically evaluated accuracy on test dataset) to tell whether this trial can be early stopped or not. + +* *Training Platform*: Where trials are executed. Depending on your experiment's configuration, it could be your local machine, or remote servers, or large-scale training platform (e.g., OpenPAI, Kubernetes). + +Basically, an experiment runs as follows: Tuner receives search space and generates configurations. These configurations will be submitted to training platforms, such as the local machine, remote machines, or training clusters. Their performances are reported back to Tuner. Then, new configurations are generated and submitted. + +For each experiment, the user only needs to define a search space and update a few lines of code, and then leverage NNI built-in Tuner/Assessor and training platforms to search the best hyperparameters and/or neural architecture. There are basically 3 steps: + +* Step 1: :doc:`Define search space <../hpo/search_space>` + +* Step 2: Update model codes + +* Step 3: :doc:`Define Experiment <../reference/experiment_config>` + +.. image:: https://user-images.githubusercontent.com/23273522/51816627-5d13db80-2302-11e9-8f3e-627e260203d5.jpg + +For more details about how to run an experiment, please refer to :doc:`Quickstart <../tutorials/hpo_quickstart_pytorch/main>`. + +Core Features +------------- + +NNI provides a key capacity to run multiple instances in parallel to find the best combinations of parameters. This feature can be used in various domains, like finding the best hyperparameters for a deep learning model or finding the best configuration for database and other complex systems with real data. + +NNI also provides algorithm toolkits for machine learning and deep learning, especially neural architecture search (NAS) algorithms, model compression algorithms, and feature engineering algorithms. + +Hyperparameter Tuning +^^^^^^^^^^^^^^^^^^^^^ + +This is a core and basic feature of NNI, we provide many popular :doc:`automatic tuning algorithms <../hpo/tuners>` (i.e., tuner) and :doc:`early stop algorithms <../hpo/assessors>` (i.e., assessor). You can follow :doc:`Quickstart <../tutorials/hpo_quickstart_pytorch/main>` to tune your model (or system). Basically, there are the above three steps and then starting an NNI experiment. + +General NAS Framework +^^^^^^^^^^^^^^^^^^^^^ + +This NAS framework is for users to easily specify candidate neural architectures, for example, one can specify multiple candidate operations (e.g., separable conv, dilated conv) for a single layer, and specify possible skip connections. NNI will find the best candidate automatically. On the other hand, the NAS framework provides a simple interface for another type of user (e.g., NAS algorithm researchers) to implement new NAS algorithms. A detailed description of NAS and its usage can be found :doc:`here
`. + +NNI has support for many one-shot NAS algorithms such as ENAS and DARTS through NNI trial SDK. To use these algorithms you do not have to start an NNI experiment. Instead, import an algorithm in your trial code and simply run your trial code. If you want to tune the hyperparameters in the algorithms or want to run multiple instances, you can choose a tuner and start an NNI experiment. + +Other than one-shot NAS, NAS can also run in a classic mode where each candidate architecture runs as an independent trial job. In this mode, similar to hyperparameter tuning, users have to start an NNI experiment and choose a tuner for NAS. + +Model Compression +^^^^^^^^^^^^^^^^^ + +NNI provides an easy-to-use model compression framework to compress deep neural networks, the compressed networks typically have much smaller model size and much faster +inference speed without losing performance significantlly. Model compression on NNI includes pruning algorithms and quantization algorithms. NNI provides many pruning and +quantization algorithms through NNI trial SDK. Users can directly use them in their trial code and run the trial code without starting an NNI experiment. Users can also use NNI model compression framework to customize their own pruning and quantization algorithms. + +A detailed description of model compression and its usage can be found :doc:`here <../compression/overview>`. + +Automatic Feature Engineering +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Automatic feature engineering is for users to find the best features for their tasks. A detailed description of automatic feature engineering and its usage can be found :doc:`here <../feature_engineering/overview>`. It is supported through NNI trial SDK, which means you do not have to create an NNI experiment. Instead, simply import a built-in auto-feature-engineering algorithm in your trial code and directly run your trial code. + +The auto-feature-engineering algorithms usually have a bunch of hyperparameters themselves. If you want to automatically tune those hyperparameters, you can leverage hyperparameter tuning of NNI, that is, choose a tuning algorithm (i.e., tuner) and start an NNI experiment for it. diff --git a/docs/source/notes/build_from_source.rst b/docs/source/notes/build_from_source.rst new file mode 100644 index 0000000000000000000000000000000000000000..ea3f9aae65e2e5cda17b61f510818710a69a9eae --- /dev/null +++ b/docs/source/notes/build_from_source.rst @@ -0,0 +1,123 @@ +Build from Source +================= + +This article describes how to build and install NNI from `source code `__. + +Preparation +----------- + +Fetch source code from GitHub: + +.. code-block:: bash + + git clone https://github.com/microsoft/nni.git + cd nni + +Upgrade to latest toolchain: + +.. code-block:: text + + pip install --upgrade setuptools pip wheel + +.. note:: + + Please make sure ``python`` and ``pip`` executables have correct Python version. + + For Apple Silicon M1, if ``python`` command is not available, you may need to manually fix dependency building issues. + (`GitHub issue `__ | + `Stack Overflow question `__) + +Development Build +----------------- + +If you want to build NNI for your own use, we recommend using `development mode`_. + +.. code-block:: text + + python setup.py develop + +This will install NNI as symlink, and the version number will be ``999.dev0``. + +.. _development mode: https://setuptools.pypa.io/en/latest/userguide/development_mode.html + +Then if you want to modify NNI source code, please check :doc:`contribution guide `. + +Release Build +------------- + +To install in release mode, you must first build a wheel. +NNI does not support setuptools' "install" command. + +A release package requires jupyterlab to build the extension: + +.. code-block:: text + + pip install jupyterlab==3.0.9 + +You need to set ``NNI_RELEASE`` environment variable to the version number, +and compile TypeScript modules before "bdist_wheel". + +In bash: + +.. code-block:: bash + + export NNI_RELEASE=2.0 + python setup.py build_ts + python bdist_wheel + +In PowerShell: + +.. code-block:: powershell + + $env:NNI_RELEASE=2.0 + python setup.py build_ts + python bdist_wheel + +If successful, you will find the wheel in ``dist`` directory. + +.. note:: + + NNI's build process is somewhat complicated. + This is due to setuptools and TypeScript not working well together. + + Setuptools require to provide ``package_data``, the full list of package files, before running any command. + However it is nearly impossible to predict what files will be generated before invoking TypeScript compiler. + + If you have any solution for this problem, please open an issue to let us know. + +Build Docker Image +------------------ + +You can build a Docker image with :githublink:`Dockerfile `: + +.. code-block:: bash + + export NNI_RELEASE=2.7 + python setup.py build_ts + python setup.py bdist_wheel -p manylinux1_x86_64 + docker build --build-arg NNI_RELEASE=${NNI_RELEASE} -t my/nni . + +To build image for other platforms, please edit Dockerfile yourself. + +Other Commands and Options +-------------------------- + +Clean +^^^^^ + +If the build fails, please clean up and try again: + +.. code:: text + + python setup.py clean + +Skip compiling TypeScript modules +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This is useful when you have uninstalled NNI from development mode and want to install again. + +It will not work if you have never built TypeScript modules before. + +.. code:: text + + python setup.py develop --skip-ts diff --git a/docs/source/notes/contributing.rst b/docs/source/notes/contributing.rst new file mode 100644 index 0000000000000000000000000000000000000000..73ecd54c6c4f120a6bc421df3df9b5f30b6aacb0 --- /dev/null +++ b/docs/source/notes/contributing.rst @@ -0,0 +1,344 @@ +Contribution Guide +================== + +Great! We are always on the lookout for more contributors to our code base. + +Firstly, if you are unsure or afraid of anything, just ask or submit the issue or pull request anyways. You won't be yelled at for giving your best effort. The worst that can happen is that you'll be politely asked to change something. We appreciate any sort of contributions and don't want a wall of rules to get in the way of that. + +However, for those individuals who want a bit more guidance on the best way to contribute to the project, read on. This document will cover all the points we're looking for in your contributions, raising your chances of quickly merging or addressing your contributions. + +There are a few simple guidelines that you need to follow before providing your hacks. + +Bug Reports and Feature Requests +-------------------------------- + +If you encountered a problem when using NNI, or have an idea for a new feature, your feedbacks are always welcome. Here are some possible channels: + +* `File an issue `_ on GitHub. +* Open or participate in a `discussion `_. +* Discuss on the NNI `Gitter `_ in NNI. +* Join IM discussion groups: + + .. list-table:: + :widths: 50 50 + :header-rows: 1 + + * - Gitter + - WeChat + * - .. image:: https://user-images.githubusercontent.com/39592018/80665738-e0574a80-8acc-11ea-91bc-0836dc4cbf89.png + - .. image:: https://github.com/scarlett2018/nniutil/raw/master/wechat.png + +Looking for an existing issue +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Before you create a new issue, please do a search in `open issues `_ to see if the issue or feature request has already been filed. + +Be sure to scan through the `most popular `_ feature requests. + +If you find your issue already exists, make relevant comments and add your `reaction `_. Use a reaction in place of a "+1" comment: + +* 👍 - upvote +* 👎 - downvote + +If you cannot find an existing issue that describes your bug or feature, create a new issue following the guidelines below. + +Writing good bug reports or feature requests +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* File a single issue per problem and feature request. Do not enumerate multiple bugs or feature requests in the same issue. + +* Provide as much information as you think might relevant to the context (thinking the issue is assigning to you, what kinds of info you will need to debug it!!!). To give you a general idea about what kinds of info are useful for developers to dig out the issue, we had provided issue template for you. + +* Once you had submitted an issue, be sure to follow it for questions and discussions. + +* Once the bug is fixed or feature is addressed, be sure to close the issue. + +Writing code +------------ + +There is always something more that is required, to make it easier to suit your use-cases. +Before starting to write code, we recommend checking for `issues `_ on GitHub or open a new issue to initiate a discussion. There could be cases where people are already working on a fix, or similar features have already been under discussion. + +To contribute code, you first need to find the NNI code repo located on `GitHub `_. Firstly, fork the repository under your own GitHub handle. After cloning the repository, add, commit, push and squash (if necessary) the changes with detailed commit messages to your fork. From where you can proceed to making a pull request. The pull request will then be reviewed by our core maintainers before merging into master branch. `Here `_ is a step-by-step guide for this process. + +Contributions to NNI should follow our code of conduct. Please see details :ref:`here `. + +Find the code snippet that concerns you +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The NNI repository is large code-base. High-level speaking, it can be decomposed into several core parts: + +* ``nni``: the core Python package that contains most features of hyper-parameter tuner, neural architecture search, model compression. +* ``ts``: contains ``nni_manager`` that manages experiments and training services, and ``webui`` for visualization. +* ``pipelines`` and ``test``: unit test and integration test, alongside their configurations. + +See :doc:`./architecture_overview` if you are interested in details. + +.. _get-started-dev: + +Get started with development +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +NNI development environment supports Ubuntu 1604 (or above), and Windows 10 with Python 3.7+ (documentation build requires Python 3.8+). We recommend using `conda `_ on Windows. + +1. Fork the NNI's GitHub repository and clone the forked repository to your machine. + + .. code-block:: bash + + git clone https://github.com//nni.git + +2. Create a new working branch. Use any name you like. + + .. code-block:: bash + + cd nni + git checkout -b feature-xyz + +3. Install NNI from source code if you need to modify the source code, and test it. + + .. code-block:: bash + + python3 -m pip install -U -r dependencies/setup.txt + python3 -m pip install -r dependencies/develop.txt + python3 setup.py develop + + This installs NNI in `development mode `_, + so you don't need to reinstall it after edit. + +4. Try to start an experiment to check if your environment is ready. For example, run the command + + .. code-block:: bash + + nnictl create --config examples/trials/mnist-pytorch/config.yml + + And open WebUI to check if everything is OK. Or check the version of installed NNI, + + .. code-block:: python + + >>> import nni + >>> nni.__version__ + '999.dev0' + + .. note:: Please don't run test under the same folder where the NNI repository is located. As the repository is probably also called ``nni``, it could import the wrong ``nni`` package. + +5. Write your code along with tests to verify whether the bug is fixed, or the feature works as expected. + +6. Reload changes. For Python, nothing needs to be done, because the code is already linked to package folders. For TypeScript on Linux and MacOS, + + * If ``ts/nni_manager`` is changed, run ``yarn watch`` under this folder. It will watch and build code continually. The ``nnictl`` need to be restarted to reload NNI manager. + * If ``ts/webui`` is changed, run ``yarn dev``\ , which will run a mock API server and a webpack dev server simultaneously. Use ``EXPERIMENT`` environment variable (e.g., ``mnist-tfv1-running``\ ) to specify the mock data being used. Built-in mock experiments are listed in ``src/webui/mock``. An example of the full command is ``EXPERIMENT=mnist-tfv1-running yarn dev``. + + For TypeScript on Windows, currently you must rebuild TypeScript modules with `python3 setup.py build_ts` after edit. + +7. Commit and push your changes, and submit your pull request! + +Coding Tips +----------- + +We expect all contributors to respect the following coding styles and naming conventions upon their contribution. + +Python +^^^^^^ + +* We follow `PEP8 `__ for Python code and naming conventions, do try to adhere to the same when making a pull request. Our pull request has a mandatory code scan with ``pylint`` and ``flake8``. + + .. note:: To scan your own code locally, run + + .. code-block:: bash + + python -m pylint --rcfile pylintrc nni + + .. tip:: One can also take the help of auto-format tools such as `autopep8 `_, which will automatically resolve most of the styling issues. + +* We recommend documenting all the methods and classes in your code. Follow `NumPy Docstring Style `__ for Python Docstring Conventions. + + * For function docstring, **description**, **Parameters**, and **Returns** are mandatory. + * For class docstring, **description** is mandatory. Optionally **Parameters** and **Attributes**. The parameters of ``__init__`` should be documented in the docstring of class. + * For docstring to describe ``dict``, which is commonly used in our hyper-parameter format description, please refer to `Internal Guideline on Writing Standards `_. + + .. tip:: Basically, you can use :ref:`ReStructuredText ` syntax in docstrings, without some exceptions. For example, custom headings are not allowed in docstrings. + +TypeScript +^^^^^^^^^^ + +TypeScript code checks can be done with, + +.. code-block:: bash + + # for nni manager + cd ts/nni_manager + yarn eslint + + # for webui + cd ts/webui + yarn sanity-check + +Tests +----- + +When a new feature is added or a bug is fixed, tests are highly recommended to make sure that the fix is effective or the feature won't break in future. There are two types of tests in NNI: + +* Unit test (**UT**): each test targets at a specific class / function / module. +* Integration test (**IT**): each test is an end-to-end example / demo. + +Unit test (Python) +^^^^^^^^^^^^^^^^^^ + +Python UT are located in ``test/ut/`` folder. We use `pytest `_ to launch the tests, and the working directory is ``test/ut/``. + +.. tip:: pytest can be used on a single file or a single test function. + + .. code-block:: bash + + pytest sdk/test_tuner.py + pytest sdk/test_tuner.py::test_tpe + +Unit test (TypeScript) +^^^^^^^^^^^^^^^^^^^^^^ + +TypeScript UT are paired with TypeScript code. Use ``yarn test`` to run them. + +Integration test +^^^^^^^^^^^^^^^^ + +The integration tests can be found in ``pipelines/`` folder. + +The integration tests are run on Azure DevOps platform on a daily basis, in order to make sure that our examples and training service integrations work properly. However, for critical changes that have impacts on the core functionalities of NNI, we recommend to `trigger the pipeline on the pull request branch `_. + +The integration tests won't be automatically triggered on pull requests. You might need to contact the core developers to help you trigger the tests. + +Documentation +------------- + +Build and check documentation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Our documentation is located under ``docs/`` folder. The following command can be used to build the documentation. + +.. code-block:: bash + + cd docs + make html + +.. note:: + + If you experience issues in building documentation, and see errors like: + + * ``Could not import extension xxx (exception: No module named 'xxx')`` : please check your development environment and make sure dependencies have been properly installed: :ref:`get-started-dev`. + * ``unsupported pickle protocol: 5``: please upgrade to Python 3.8. + * ``autodoc: No module named 'xxx'``: some dependencies in ``dependencies/`` are not installed. In this case, documentation can be still mostly successfully built, but some API reference could be missing. + +It's also highly recommended taking care of **every WARNING** during the build, which is very likely the signal of a **deadlink** and other annoying issues. Our code check will also make sure that the documentation build completes with no warning. + +The built documentation can be found in ``docs/build/html`` folder. + +.. attention:: Always use your web browser to check the documentation before committing your change. + +.. tip:: `Live Server `_ is a great extension if you are looking for a static-files server to serve contents in ``docs/build/html``. + +Writing new documents +^^^^^^^^^^^^^^^^^^^^^ + +.. |link_example| raw:: html + + `Link text <https://domain.invalid/>`_ + +.. |link_example_2| raw:: html + + `Link text <https://domain.invalid/>`__ + +.. |link_example_3| raw:: html + + :doc:`./relative/to/my_doc` + +.. |githublink_example| raw:: html + + :githublink:`path/to/file.ext` + +.. |githublink_example_2| raw:: html + + :githublink:`text <path/to/file.ext>` + +.. _restructuredtext-intro: + +`ReStructuredText `_ is our documentation language. Please find the reference of RST `here `__. + +.. tip:: Sphinx has `an excellent cheatsheet of rst `_ which contains almost everything you might need to know to write a elegant document. + +**Dealing with sections.** ``=`` for sections. ``-`` for subsections. ``^`` for subsubsections. ``"`` for paragraphs. + +**Dealing with images.** Images should be put into ``docs/img`` folder. Then, reference the image in the document with relative links. For example, ``.. image:: ../../img/example.png``. + +**Dealing with codes.** We recommend using ``.. code-block:: python`` to start a code block. The ``python`` here annotates the syntax highlighting. + +**Dealing with links.** Use |link_example_3| for links to another doc (no suffix like ``.rst``). To reference a specific section, please use ``:ref:`` (see `Cross-referencing arbitrary locations `_). For general links that ``:doc:`` and ``:ref:`` can't handle, you can also use |link_example| for inline web links. Note that use one underline might cause `"duplicated target name" error `_ when multiple targets share the same name. In that case, use double-underline to avoid the error: |link_example_2|. + +Other than built-in directives provided by Sphinx, we also provide some custom directives: + +* ``.. cardlinkitem::``: A tutorial card, useful in :doc:`/examples`. +* |githublink_example| or |githublink_example_2|: reference a file on the GitHub. Linked to the same commit id as where the documentation is built. + +Writing new tutorials +^^^^^^^^^^^^^^^^^^^^^ + +Our tutorials are powered by `sphinx-gallery `. Sphinx-gallery is an extension that builds an HTML gallery of examples from any set of Python scripts. + +To contribute a new tutorial, here are the steps to follow: + +1. Create a notebook styled python file. If you want it executed while inserted into documentation, save the file under ``examples/tutorials/``. If your tutorial contains other auxiliary scripts which are not intended to be included into documentation, save them under ``examples/tutorials/scripts/``. + + .. tip:: The syntax to write a "notebook styled python file" is very simple. In essence, you only need to write a slightly well formatted python file. Here is a useful guide of `how to structure your Python scripts for Sphinx-Gallery `_. + +2. Put the tutorials into ``docs/source/tutorials.rst``. You should add it both in ``toctree`` (to make it appear in the sidebar content table), and ``cardlinkitem`` (to create a card link), and specify the appropriate ``header``, ``description``, ``link``, ``image``, ``background`` (for image) and ``tags``. + + ``link`` are the generated link, which is usually ``tutorials/.html``. Some useful images can be found in ``docs/img/thumbnails``, but you can always use your own. Available background colors are: ``red``, ``pink``, ``purple``, ``deep-purple``, ``blue``, ``light-blue``, ``cyan``, ``teal``, ``green``, ``deep-orange``, ``brown``, ``indigo``. + + In case you prefer to write your tutorial in jupyter, you can use `this script `_ to convert the notebook to python file. After conversion and addition to the project, please make sure the sections headings etc are in logical order. + +3. Build the tutorials. Since some of the tutorials contain complex AutoML examples, it's very inefficient to build them over and over again. Therefore, we cache the built tutorials in ``docs/source/tutorials``, so that the unchanged tutorials won't be rebuilt. To trigger the build, run ``make html``. This will execute the tutorials and convert the scripts into HTML files. How long it takes depends on your tutorial. As ``make html`` is not very debug-friendly, we suggest making the script runnable by itself before using this building tool. + +.. note:: + + Some useful HOW-TOs in writing new tutorials: + + * `How to force rebuilding one tutorial `_. + * `How to add images to notebooks `_. + * `How to reference a tutorial in documentation `_. + +Translation (i18n) +^^^^^^^^^^^^^^^^^^ + +We only maintain `a partial set of documents `_ with translation. Currently, translation is provided in Simplified Chinese only. + +* If you want to update the translation of an existing document, please update messages in ``docs/source/locales``. +* If you have updated a translated English document, we require that the corresponding translated documents to be updated (at least the update should be triggered). Please follow these steps: + + 1. Run ``make i18n`` under ``docs`` folder. + 2. Verify that there are new messages in ``docs/source/locales``. + 3. Translate the messages. + +* If you intend to translate a new document: + + 1. Update ``docs/source/conf.py`` to make ``gettext_documents`` include your document (probably adding a new regular expression). + 2. See the steps above. + + +To build the translated documentation (for example Chinese documentation), please run: + +.. code-block:: bash + + make -e SPHINXOPTS="-D language='zh'" html + +If you ever encountered problems for translation builds, try to remove the previous build via ``rm -r docs/build/``. + +.. _code-of-conduct: + +Code of Conduct +--------------- + +This project has adopted the `Microsoft Open Source Code of Conduct `_. +For more information see the `Code of Conduct FAQ `_ or contact `opencode@microsoft.com `_ with any additional questions or comments. + +Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. + +When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. diff --git a/docs/source/ResearchPublications.rst b/docs/source/notes/research_publications.rst similarity index 100% rename from docs/source/ResearchPublications.rst rename to docs/source/notes/research_publications.rst diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst new file mode 100644 index 0000000000000000000000000000000000000000..1abd8bdaeb478e2db41877d409d3c5fc6da788b0 --- /dev/null +++ b/docs/source/quickstart.rst @@ -0,0 +1,23 @@ +Quickstart +========== + +.. cardlinkitem:: + :header: Hyperparameter Optimization Quickstart with PyTorch + :description: Use Hyperparameter Optimization (HPO) to tune a PyTorch FashionMNIST model. + :link: tutorials/hpo_quickstart_pytorch/main + :image: ../img/thumbnails/hpo-pytorch.svg + :background: purple + +.. cardlinkitem:: + :header: Neural Architecture Search Quickstart + :description: Beginners' NAS tutorial on how to search for neural architectures for MNIST dataset. + :link: tutorials/hello_nas + :image: ../img/thumbnails/nas-tutorial.svg + :background: cyan + +.. cardlinkitem:: + :header: Model Compression Quickstart + :description: Familiarize yourself with pruning to compress your model. + :link: tutorials/pruning_quick_start_mnist + :image: ../img/thumbnails/pruning-tutorial.svg + :background: blue diff --git a/docs/source/quickstart_zh.rst b/docs/source/quickstart_zh.rst new file mode 100644 index 0000000000000000000000000000000000000000..1396ca11fedaa43465292de79c5d40c98c3a8fe3 --- /dev/null +++ b/docs/source/quickstart_zh.rst @@ -0,0 +1,25 @@ +.. ccd00e2e56b44cf452b0afb81e8cecff + +快速入门 +========== + +.. cardlinkitem:: + :header: 超参调优快速入门(以 PyTorch 框架为例) + :description: 使用超参数调优 (HPO) 为一个 PyTorch FashionMNIST 模型调参. + :link: tutorials/hpo_quickstart_pytorch/main + :image: ../img/thumbnails/hpo-pytorch.svg + :background: purple + +.. cardlinkitem:: + :header: 神经架构搜索快速入门 + :description: 为初学者讲解如何使用 NNI 在 MNIST 数据集上搜索一个网络结构。 + :link: tutorials/hello_nas + :image: ../img/thumbnails/nas-tutorial.svg + :background: cyan + +.. cardlinkitem:: + :header: 模型压缩快速入门 + :description: 学习剪枝以压缩您的模型。 + :link: tutorials/pruning_quick_start_mnist + :image: ../img/thumbnails/pruning-tutorial.svg + :background: blue diff --git a/docs/source/reference.rst b/docs/source/reference.rst deleted file mode 100644 index 75214cbde7750a1cf238b3b85e6ccb03afe233f6..0000000000000000000000000000000000000000 --- a/docs/source/reference.rst +++ /dev/null @@ -1,16 +0,0 @@ -References -================== - -.. toctree:: - :maxdepth: 2 - - nnictl Commands - Experiment Configuration - Experiment Configuration (legacy) - Search Space - NNI Annotation - SDK API References - Supported Framework Library - Launch from Python - Shared Storage - Tensorboard diff --git a/docs/source/reference/compression/framework.rst b/docs/source/reference/compression/framework.rst new file mode 100644 index 0000000000000000000000000000000000000000..5ab0105c3c7cc175f4e364499ab3f6a1bb2600bf --- /dev/null +++ b/docs/source/reference/compression/framework.rst @@ -0,0 +1,67 @@ +Framework Related +================= + +Pruner +------ + +.. autoclass:: nni.algorithms.compression.v2.pytorch.base.Pruner + :members: + +PrunerModuleWrapper +------------------- + +.. autoclass:: nni.algorithms.compression.v2.pytorch.base.PrunerModuleWrapper + +BasicPruner +----------- + +.. autoclass:: nni.algorithms.compression.v2.pytorch.pruning.basic_pruner.BasicPruner + :members: + +DataCollector +------------- + +.. autoclass:: nni.algorithms.compression.v2.pytorch.pruning.tools.DataCollector + :members: + +MetricsCalculator +----------------- + +.. autoclass:: nni.algorithms.compression.v2.pytorch.pruning.tools.MetricsCalculator + :members: + +SparsityAllocator +----------------- + +.. autoclass:: nni.algorithms.compression.v2.pytorch.pruning.tools.SparsityAllocator + :members: + +BasePruningScheduler +-------------------- + +.. autoclass:: nni.algorithms.compression.v2.pytorch.base.BasePruningScheduler + :members: + +TaskGenerator +------------- + +.. autoclass:: nni.algorithms.compression.v2.pytorch.pruning.tools.TaskGenerator + :members: + +Quantizer +--------- + +.. autoclass:: nni.compression.pytorch.compressor.Quantizer + :members: + +QuantizerModuleWrapper +---------------------- + +.. autoclass:: nni.compression.pytorch.compressor.QuantizerModuleWrapper + :members: + +QuantGrad +--------- + +.. autoclass:: nni.compression.pytorch.compressor.QuantGrad + :members: diff --git a/docs/source/reference/compression/pruner.rst b/docs/source/reference/compression/pruner.rst new file mode 100644 index 0000000000000000000000000000000000000000..8088cbacfe90f7dd084dffbdbce536ffb3779c24 --- /dev/null +++ b/docs/source/reference/compression/pruner.rst @@ -0,0 +1,123 @@ +Pruner +====== + +Basic Pruner +------------ + +.. _level-pruner: + +Level Pruner +^^^^^^^^^^^^ + +.. autoclass:: nni.compression.pytorch.pruning.LevelPruner + +.. _l1-norm-pruner: + +L1 Norm Pruner +^^^^^^^^^^^^^^ + +.. autoclass:: nni.compression.pytorch.pruning.L1NormPruner + +.. _l2-norm-pruner: + +L2 Norm Pruner +^^^^^^^^^^^^^^ + +.. autoclass:: nni.compression.pytorch.pruning.L2NormPruner + +.. _fpgm-pruner: + +FPGM Pruner +^^^^^^^^^^^ + +.. autoclass:: nni.compression.pytorch.pruning.FPGMPruner + +.. _slim-pruner: + +Slim Pruner +^^^^^^^^^^^ + +.. autoclass:: nni.compression.pytorch.pruning.SlimPruner + +.. _activation-apoz-rank-pruner: + +Activation APoZ Rank Pruner +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: nni.compression.pytorch.pruning.ActivationAPoZRankPruner + +.. _activation-mean-rank-pruner: + +Activation Mean Rank Pruner +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: nni.compression.pytorch.pruning.ActivationMeanRankPruner + +.. _taylor-fo-weight-pruner: + +Taylor FO Weight Pruner +^^^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: nni.compression.pytorch.pruning.TaylorFOWeightPruner + +.. _admm-pruner: + +ADMM Pruner +^^^^^^^^^^^ + +.. autoclass:: nni.compression.pytorch.pruning.ADMMPruner + +Scheduled Pruners +----------------- + +.. _linear-pruner: + +Linear Pruner +^^^^^^^^^^^^^ + +.. autoclass:: nni.compression.pytorch.pruning.LinearPruner + +.. _agp-pruner: + +AGP Pruner +^^^^^^^^^^ + +.. autoclass:: nni.compression.pytorch.pruning.AGPPruner + +.. _lottery-ticket-pruner: + +Lottery Ticket Pruner +^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: nni.compression.pytorch.pruning.LotteryTicketPruner + +.. _simulated-annealing-pruner: + +Simulated Annealing Pruner +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: nni.compression.pytorch.pruning.SimulatedAnnealingPruner + +.. _auto-compress-pruner: + +Auto Compress Pruner +^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: nni.compression.pytorch.pruning.AutoCompressPruner + +.. _amc-pruner: + +AMC Pruner +^^^^^^^^^^ + +.. autoclass:: nni.compression.pytorch.pruning.AMCPruner + +Other Pruner +------------ + +.. _movement-pruner: + +Movement Pruner +^^^^^^^^^^^^^^^ + +.. autoclass:: nni.compression.pytorch.pruning.MovementPruner \ No newline at end of file diff --git a/docs/source/reference/compression/pruning_speedup.rst b/docs/source/reference/compression/pruning_speedup.rst new file mode 100644 index 0000000000000000000000000000000000000000..f0c322aae84af4b3ef5a4302ed73ef920e2885bb --- /dev/null +++ b/docs/source/reference/compression/pruning_speedup.rst @@ -0,0 +1,5 @@ +Pruning Speedup +=============== + +.. autoclass:: nni.compression.pytorch.speedup.ModelSpeedup + :members: diff --git a/docs/source/reference/compression/quantization_speedup.rst b/docs/source/reference/compression/quantization_speedup.rst new file mode 100644 index 0000000000000000000000000000000000000000..5b8ffa224cd6bd61a899cb4b0f8aae9a0b915b12 --- /dev/null +++ b/docs/source/reference/compression/quantization_speedup.rst @@ -0,0 +1,5 @@ +Quantization Speedup +==================== + +.. autoclass:: nni.compression.pytorch.quantization_speedup.ModelSpeedupTensorRT + :members: diff --git a/docs/source/reference/compression/quantizer.rst b/docs/source/reference/compression/quantizer.rst new file mode 100644 index 0000000000000000000000000000000000000000..d56c3b1f8f9318975ddaf2c578e16c6f77a60fe3 --- /dev/null +++ b/docs/source/reference/compression/quantizer.rst @@ -0,0 +1,44 @@ +Quantizer +========= + +.. _naive-quantizer: + +Naive Quantizer +^^^^^^^^^^^^^^^ + +.. autoclass:: nni.algorithms.compression.pytorch.quantization.NaiveQuantizer + +.. _qat-quantizer: + +QAT Quantizer +^^^^^^^^^^^^^ + +.. autoclass:: nni.algorithms.compression.pytorch.quantization.QAT_Quantizer + +.. _dorefa-quantizer: + +DoReFa Quantizer +^^^^^^^^^^^^^^^^ + +.. autoclass:: nni.algorithms.compression.pytorch.quantization.DoReFaQuantizer + +.. _bnn-quantizer: + +BNN Quantizer +^^^^^^^^^^^^^ + +.. autoclass:: nni.algorithms.compression.pytorch.quantization.BNNQuantizer + +.. _lsq-quantizer: + +LSQ Quantizer +^^^^^^^^^^^^^ + +.. autoclass:: nni.algorithms.compression.pytorch.quantization.LsqQuantizer + +.. _observer-quantizer: + +Observer Quantizer +^^^^^^^^^^^^^^^^^^ + +.. autoclass:: nni.algorithms.compression.pytorch.quantization.ObserverQuantizer diff --git a/docs/source/reference/compression/toctree.rst b/docs/source/reference/compression/toctree.rst new file mode 100644 index 0000000000000000000000000000000000000000..72e7e425aa8aa5848f677f9667548c45c882b184 --- /dev/null +++ b/docs/source/reference/compression/toctree.rst @@ -0,0 +1,12 @@ +Compression API Reference +========================= + +.. toctree:: + :maxdepth: 1 + + Pruner + Quantizer + Pruning Speedup + Quantization Speedup + Compression Utilities + Framework Related diff --git a/docs/source/reference/compression/utils.rst b/docs/source/reference/compression/utils.rst new file mode 100644 index 0000000000000000000000000000000000000000..7b0e8459ea71e0aac10222beb91821b8351efb9c --- /dev/null +++ b/docs/source/reference/compression/utils.rst @@ -0,0 +1,42 @@ +Compression Utilities +===================== + +SensitivityAnalysis +------------------- + +.. autoclass:: nni.compression.pytorch.utils.SensitivityAnalysis + :members: + +ChannelDependency +----------------- + +.. autoclass:: nni.compression.pytorch.utils.ChannelDependency + :members: + +GroupDependency +--------------- + +.. autoclass:: nni.compression.pytorch.utils.GroupDependency + :members: + +ChannelMaskConflict +------------------- + +.. autoclass:: nni.compression.pytorch.utils.ChannelMaskConflict + :members: + +GroupMaskConflict +----------------- + +.. autoclass:: nni.compression.pytorch.utils.GroupMaskConflict + :members: + +count_flops_params +------------------ + +.. autofunction:: nni.compression.pytorch.utils.count_flops_params + +compute_sparsity +---------------- + +.. autofunction:: nni.algorithms.compression.v2.pytorch.utils.pruning.compute_sparsity diff --git a/docs/source/reference/experiment.rst b/docs/source/reference/experiment.rst new file mode 100644 index 0000000000000000000000000000000000000000..5d99324dacee52ace4b400a26eefbc0005973086 --- /dev/null +++ b/docs/source/reference/experiment.rst @@ -0,0 +1,5 @@ +Experiment API Reference +======================== + +.. autoclass:: nni.experiment.Experiment + :members: diff --git a/docs/source/reference/experiment_config.rst b/docs/source/reference/experiment_config.rst index 8bc52e71c57b1048a56deaa031a4e494f1cc7a74..76541573ca9d1342f3453fe6ecd9c02b03f64f55 100644 --- a/docs/source/reference/experiment_config.rst +++ b/docs/source/reference/experiment_config.rst @@ -20,11 +20,6 @@ A config file is needed when creating an experiment. This document describes the 4. Setting a field to ``None`` or ``null`` is equivalent to not setting the field. -.. contents:: Contents - :local: - :depth: 3 - - Examples ======== @@ -120,13 +115,13 @@ ExperimentConfig * - searchSpaceFile - ``str``, optional - Path_ to the JSON file containing the search space. - Search space format is determined by tuner. The common format for built-in tuners is documented `here <../Tutorial/SearchSpaceSpec.rst>`__. + Search space format is determined by tuner. The common format for built-in tuners is documented :doc:`here `. Mutually exclusive to ``searchSpace``. * - searchSpace - ``JSON``, optional - Search space object. - The format is determined by tuner. Common format for built-in tuners is documented `here <../Tutorial/SearchSpaceSpec.rst>`__. + The format is determined by tuner. Common format for built-in tuners is documented :doc:`here `. Note that ``None`` means "no such field" so empty search space should be written as ``{}``. Mutually exclusive to ``searchSpaceFile``. @@ -151,7 +146,7 @@ ExperimentConfig - ``int`` or ``None``, optional - Default: None. This field might have slightly different meanings for various training services, especially when set to ``0`` or ``None``. - See `training service's document <../training_services.rst>`__ for details. + See :doc:`training service's document ` for details. In local mode, setting the field to ``0`` will prevent trials from accessing GPU (by empty ``CUDA_VISIBLE_DEVICES``). And when set to ``None``, trials will be created and scheduled as if they did not use GPU, @@ -183,7 +178,7 @@ ExperimentConfig * - useAnnotation - ``bool``, optional - - Default: ``False``. Enable `annotation <../Tutorial/AnnotationSpec.rst>`__. + - Default: ``False``. Enable :doc:`annotation `. When using annotation, ``searchSpace`` and ``searchSpaceFile`` should not be specified manually. * - debug @@ -215,25 +210,25 @@ ExperimentConfig * - tuner - ``AlgorithmConfig``, optional - Specify the tuner. - The built-in tuners can be found `here <../builtin_tuner.rst>`__ and you can follow `this tutorial <../Tuner/CustomizeTuner.rst>`__ to customize a new tuner. + The built-in tuners can be found :doc:`here ` and you can follow :doc:`this tutorial ` to customize a new tuner. * - assessor - ``AlgorithmConfig``, optional - Specify the assessor. - The built-in assessors can be found `here <../builtin_assessor.rst>`__ and you can follow `this tutorial <../Assessor/CustomizeAssessor.rst>`__ to customize a new assessor. + The built-in assessors can be found :doc:`here ` and you can follow :doc:`this tutorial ` to customize a new assessor. * - advisor - ``AlgorithmConfig``, optional - Specify the advisor. - NNI provides two built-in advisors: `BOHB <../Tuner/BohbAdvisor.rst>`__ and `Hyperband <../Tuner/HyperbandAdvisor.rst>`__, and you can follow `this tutorial <../Tuner/CustomizeAdvisor.rst>`__ to customize a new advisor. + NNI provides two built-in advisors: :class:`BOHB ` and :class:`Hyperband `. * - trainingService - ``TrainingServiceConfig`` - - Specify the `training service <../TrainingService/Overview.rst>`__. + - Specify the :doc:`training service `. * - sharedStorage - ``SharedStorageConfig``, optional - - Configure the shared storage, detailed usage can be found `here <../Tutorial/HowToUseSharedStorage.rst>`__. + - Configure the shared storage, detailed usage can be found :doc:`here `. AlgorithmConfig ^^^^^^^^^^^^^^^ @@ -242,9 +237,9 @@ AlgorithmConfig For customized algorithms, there are two ways to describe them: - 1. `Register the algorithm <../Tutorial/InstallCustomizedAlgos.rst>`__ to use it like built-in. (preferred) +1. :doc:`Register the algorithm ` to use it like built-in. (preferred) - 2. Specify code directory and class name directly. +2. Specify code directory and class name directly. .. list-table:: :widths: 10 10 80 @@ -286,13 +281,15 @@ One of the following: - `AmlConfig`_ - `DlcConfig`_ - `HybridConfig`_ +- :doc:`FrameworkControllerConfig ` +- :doc:`KubeflowConfig ` -For `Kubeflow <../TrainingService/KubeflowMode.rst>`_, `FrameworkController <../TrainingService/FrameworkControllerMode.rst>`_, and `AdaptDL <../TrainingService/AdaptDLMode.rst>`_ training platforms, it is suggested to use `v1 config schema <../Tutorial/ExperimentConfig.rst>`_ for now. +.. _reference-local-config-label: LocalConfig ----------- -Detailed usage can be found `here <../TrainingService/LocalMode.rst>`__. +Introduction of the corresponding local training service can be found :doc:`/experiment/training_service/local`. .. list-table:: :widths: 10 10 80 @@ -330,10 +327,12 @@ Detailed usage can be found `here <../TrainingService/LocalMode.rst>`__. If ``trialGpuNumber`` is less than the length of this value, only a subset will be visible to each trial. This will be used as ``CUDA_VISIBLE_DEVICES`` environment variable. +.. _reference-remote-config-label: + RemoteConfig ------------ -Detailed usage can be found `here <../TrainingService/RemoteMachineMode.rst>`__. +Detailed usage can be found :doc:`/experiment/training_service/remote`. .. list-table:: :widths: 10 10 80 @@ -353,7 +352,7 @@ Detailed usage can be found `here <../TrainingService/RemoteMachineMode.rst>`__. * - reuseMode - ``bool``, optional - - Default: ``True``. Enable `reuse mode <../TrainingService/Overview.rst#training-service-under-reuse-mode>`__. + - Default: ``True``. Enable :ref:`reuse mode `. RemoteMachineConfig """"""""""""""""""" @@ -433,7 +432,7 @@ RemoteMachineConfig OpenpaiConfig ------------- -Detailed usage can be found `here <../TrainingService/PaiMode.rst>`__. +Detailed usage can be found :doc:`here `. .. list-table:: :widths: 10 10 80 @@ -491,7 +490,7 @@ Detailed usage can be found `here <../TrainingService/PaiMode.rst>`__. * - reuseMode - ``bool``, optional - - Default: ``True``. Enable `reuse mode <../TrainingService/Overview.rst#training-service-under-reuse-mode>`__. + - Default: ``True``. Enable :ref:`reuse mode `. * - openpaiConfig - ``JSON``, optional @@ -505,7 +504,7 @@ Detailed usage can be found `here <../TrainingService/PaiMode.rst>`__. AmlConfig --------- -Detailed usage can be found `here <../TrainingService/AMLMode.rst>`__. +Detailed usage can be found :doc:`here `. .. list-table:: :widths: 10 10 80 @@ -542,7 +541,7 @@ Detailed usage can be found `here <../TrainingService/AMLMode.rst>`__. DlcConfig --------- -Detailed usage can be found `here <../TrainingService/DlcMode.rst>`__. +Detailed usage can be found :doc:`here `. .. list-table:: :widths: 10 10 80 @@ -607,14 +606,16 @@ Detailed usage can be found `here <../TrainingService/DlcMode.rst>`__. HybridConfig ------------ -Currently only support `LocalConfig`_, `RemoteConfig`_, `OpenpaiConfig`_ and `AmlConfig`_ . Detailed usage can be found `here <../TrainingService/HybridMode.rst>`__. +Currently only support `LocalConfig`_, `RemoteConfig`_, `OpenpaiConfig`_ and `AmlConfig`_ . Detailed usage can be found :doc:`here `. + +.. _reference-sharedstorage-config-label: SharedStorageConfig ^^^^^^^^^^^^^^^^^^^ -Detailed usage can be found `here <../Tutorial/HowToUseSharedStorage.rst>`__. +Detailed usage can be found :doc:`here `. -nfsConfig +NfsConfig --------- .. list-table:: @@ -653,7 +654,7 @@ nfsConfig - ``str`` - Exported directory of NFS server, detailed `here `_. -azureBlobConfig +AzureBlobConfig --------------- .. list-table:: diff --git a/docs/source/reference/hpo.rst b/docs/source/reference/hpo.rst new file mode 100644 index 0000000000000000000000000000000000000000..7bd6b93a0493e130ec4bcc276377e7950f1f661e --- /dev/null +++ b/docs/source/reference/hpo.rst @@ -0,0 +1,93 @@ +HPO API Reference +================= + +Trial APIs +---------- + +.. autofunction:: nni.get_experiment_id +.. autofunction:: nni.get_next_parameter +.. autofunction:: nni.get_sequence_id +.. autofunction:: nni.get_trial_id +.. autofunction:: nni.report_final_result +.. autofunction:: nni.report_intermediate_result + +Tuners +------ + +Batch Tuner +^^^^^^^^^^^ +.. autoclass:: nni.algorithms.hpo.batch_tuner.BatchTuner + +BOHB Tuner +^^^^^^^^^^ +.. autoclass:: nni.algorithms.hpo.bohb_advisor.BOHB + +DNGO Tuner +^^^^^^^^^^ +.. autoclass:: nni.algorithms.hpo.dngo_tuner.DNGOTuner + +Evolution Tuner +^^^^^^^^^^^^^^^ +.. autoclass:: nni.algorithms.hpo.evolution_tuner.EvolutionTuner + +GP Tuner +^^^^^^^^ +.. autoclass:: nni.algorithms.hpo.gp_tuner.GPTuner + +Grid Search Tuner +^^^^^^^^^^^^^^^^^ +.. autoclass:: nni.algorithms.hpo.gridsearch_tuner.GridSearchTuner + +Hyperband Tuner +^^^^^^^^^^^^^^^ +.. autoclass:: nni.algorithms.hpo.hyperband_advisor.Hyperband + +Hyperopt Tuner +^^^^^^^^^^^^^^ +.. autoclass:: nni.algorithms.hpo.hyperopt_tuner.HyperoptTuner + +Metis Tuner +^^^^^^^^^^^ +.. autoclass:: nni.algorithms.hpo.metis_tuner.MetisTuner + +PBT Tuner +^^^^^^^^^ +.. autoclass:: nni.algorithms.hpo.pbt_tuner.PBTTuner + +PPO Tuner +^^^^^^^^^ +.. autoclass:: nni.algorithms.hpo.ppo_tuner.PPOTuner + +Random Tuner +^^^^^^^^^^^^ +.. autoclass:: nni.algorithms.hpo.random_tuner.RandomTuner + +SMAC Tuner +^^^^^^^^^^ +.. autoclass:: nni.algorithms.hpo.smac_tuner.SMACTuner + +TPE Tuner +^^^^^^^^^ +.. autoclass:: nni.algorithms.hpo.tpe_tuner.TpeTuner +.. autoclass:: nni.algorithms.hpo.tpe_tuner.TpeArguments + +Assessors +--------- + +Curve Fitting Assessor +^^^^^^^^^^^^^^^^^^^^^^ +.. autoclass:: nni.algorithms.hpo.curvefitting_assessor.CurvefittingAssessor + +Median Stop Assessor +^^^^^^^^^^^^^^^^^^^^ +.. autoclass:: nni.algorithms.hpo.medianstop_assessor.MedianstopAssessor + +Customization +------------- + +.. autoclass:: nni.assessor.AssessResult + :members: +.. autoclass:: nni.assessor.Assessor + :members: +.. autoclass:: nni.tuner.Tuner + :members: diff --git a/docs/source/reference/nas/evaluator.rst b/docs/source/reference/nas/evaluator.rst new file mode 100644 index 0000000000000000000000000000000000000000..deae73f702ad4c93e21089da6a1c34c3f1b5068e --- /dev/null +++ b/docs/source/reference/nas/evaluator.rst @@ -0,0 +1,46 @@ +Evaluator +========= + +FunctionalEvaluator +------------------- + +.. autoclass:: nni.retiarii.evaluator.FunctionalEvaluator + :members: + +Classification +-------------- + +.. autoclass:: nni.retiarii.evaluator.pytorch.Classification + :members: + +Regression +---------- + +.. autoclass:: nni.retiarii.evaluator.pytorch.Regression + :members: + +Utilities +--------- + +.. autoclass:: nni.retiarii.evaluator.pytorch.Trainer + +.. autoclass:: nni.retiarii.evaluator.pytorch.DataLoader + +Customization +------------- + +.. autoclass:: nni.retiarii.evaluator.pytorch.Lightning + +.. autoclass:: nni.retiarii.evaluator.pytorch.LightningModule + +Cross-graph Optimization (experimental) +--------------------------------------- + +.. autoclass:: nni.retiarii.evaluator.pytorch.cgo.evaluator.MultiModelSupervisedLearningModule + :members: + +.. autoclass:: nni.retiarii.evaluator.pytorch.cgo.evaluator.Classification + :members: + +.. autoclass:: nni.retiarii.evaluator.pytorch.cgo.evaluator.Regression + :members: diff --git a/docs/source/reference/nas/others.rst b/docs/source/reference/nas/others.rst new file mode 100644 index 0000000000000000000000000000000000000000..409cdc662cd0a1e07981c95a50db864c47c1c4a0 --- /dev/null +++ b/docs/source/reference/nas/others.rst @@ -0,0 +1,60 @@ +Uncategorized Modules +===================== + +Experiment +---------- + +.. autoclass:: nni.retiarii.experiment.pytorch.RetiariiExeConfig + :members: + +.. autoclass:: nni.retiarii.experiment.pytorch.RetiariiExperiment + :members: + +NAS Benchmarks +-------------- + +.. _nas-bench-101-reference: + +NAS-Bench-101 +^^^^^^^^^^^^^ + +.. automodule:: nni.nas.benchmarks.nasbench101 + :members: + :imported-members: + +.. _nas-bench-201-reference: + +NAS-Bench-201 +^^^^^^^^^^^^^ + +.. automodule:: nni.nas.benchmarks.nasbench201 + :members: + :imported-members: + +.. _nds-reference: + +NDS +^^^ + +.. automodule:: nni.nas.benchmarks.nds + :members: + :imported-members: + +Retrain (Architecture Evaluation) +--------------------------------- + +.. autofunction:: nni.retiarii.fixed_arch + +Utilities +--------- + +.. autofunction:: nni.retiarii.basic_unit + +.. autofunction:: nni.retiarii.model_wrapper + +.. automodule:: nni.retiarii.nn.pytorch.mutation_utils + :imported-members: + :members: + +.. automodule:: nni.retiarii.utils + :members: diff --git a/docs/source/reference/nas/search_space.rst b/docs/source/reference/nas/search_space.rst new file mode 100644 index 0000000000000000000000000000000000000000..8269c01d6098ea9d1550fd5967207c4cf205fcb9 --- /dev/null +++ b/docs/source/reference/nas/search_space.rst @@ -0,0 +1,111 @@ +Search Space +============ + +.. _mutation-primitives: + +Mutation Pritimives +------------------- + +LayerChoice +^^^^^^^^^^^ + +.. autoclass:: nni.retiarii.nn.pytorch.LayerChoice + :members: + + +InputChoice +^^^^^^^^^^^ + +.. autoclass:: nni.retiarii.nn.pytorch.InputChoice + :members: + +.. autoclass:: nni.retiarii.nn.pytorch.ChosenInputs + :members: + +ValueChoice +^^^^^^^^^^^ + +.. autoclass:: nni.retiarii.nn.pytorch.ValueChoice + :members: + :inherited-members: Module + +ModelParameterChoice +^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: nni.retiarii.nn.pytorch.ModelParameterChoice + :members: + :inherited-members: Module + +Repeat +^^^^^^ + +.. autoclass:: nni.retiarii.nn.pytorch.Repeat + :members: + +Cell +^^^^ + +.. autoclass:: nni.retiarii.nn.pytorch.Cell + :members: + +NasBench101Cell +^^^^^^^^^^^^^^^ + +.. autoclass:: nni.retiarii.nn.pytorch.NasBench101Cell + :members: + +NasBench201Cell +^^^^^^^^^^^^^^^ + +.. autoclass:: nni.retiarii.nn.pytorch.NasBench201Cell + :members: + +.. _hyper-modules: + +Hyper-module Library (experimental) +----------------------------------- + +AutoActivation +^^^^^^^^^^^^^^ + +.. autoclass:: nni.retiarii.nn.pytorch.AutoActivation + :members: + +Mutators (advanced) +------------------- + +Mutator +^^^^^^^ + +.. autoclass:: nni.retiarii.Mutator + :members: + +.. autoclass:: nni.retiarii.Sampler + :members: + +.. autoclass:: nni.retiarii.InvalidMutation + :members: + +Placeholder +^^^^^^^^^^^ + +.. autoclass:: nni.retiarii.nn.pytorch.Placeholder + :members: + +Graph +^^^^^ + +.. autoclass:: nni.retiarii.Model + :members: + +.. autoclass:: nni.retiarii.Graph + :members: + +.. autoclass:: nni.retiarii.Node + :members: + +.. autoclass:: nni.retiarii.Edge + :members: + +.. autoclass:: nni.retiarii.Operation + :members: diff --git a/docs/source/reference/nas/strategy.rst b/docs/source/reference/nas/strategy.rst new file mode 100644 index 0000000000000000000000000000000000000000..2393ab23e72ec498096fc6468345879473c9bf5b --- /dev/null +++ b/docs/source/reference/nas/strategy.rst @@ -0,0 +1,426 @@ +Strategy +======== + +.. _multi-trial-nas-reference: + +Multi-trial Strategy +-------------------- + +Random +^^^^^^ + +.. autoclass:: nni.retiarii.strategy.Random + :members: + +GridSearch +^^^^^^^^^^ + +.. autoclass:: nni.retiarii.strategy.GridSearch + :members: + +RegularizedEvolution +^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: nni.retiarii.strategy.RegularizedEvolution + :members: + +TPE +^^^ + +.. autoclass:: nni.retiarii.strategy.TPE + :members: + +PolicyBasedRL +^^^^^^^^^^^^^ + +.. autoclass:: nni.retiarii.strategy.PolicyBasedRL + :members: + +.. _one-shot-strategy-reference: + +One-shot Strategy +----------------- + +.. _darts-strategy: + +DARTS +^^^^^ + +The paper `DARTS: Differentiable Architecture Search `__ addresses the scalability challenge of architecture search by formulating the task in a differentiable manner. Their method is based on the continuous relaxation of the architecture representation, allowing efficient search of the architecture using gradient descent. + +Authors' code optimizes the network weights and architecture weights alternatively in mini-batches. They further explore the possibility that uses second order optimization (unroll) instead of first order, to improve the performance. + +Implementation on NNI is based on the `official implementation `__ and a `popular 3rd-party repo `__. DARTS on NNI is designed to be general for arbitrary search space. A CNN search space tailored for CIFAR10, same as the original paper, is implemented as a use case of DARTS. + +.. autoclass:: nni.retiarii.oneshot.pytorch.DartsTrainer + +Reproduction Results +"""""""""""""""""""" + +The above-mentioned example is meant to reproduce the results in the paper, we do experiments with first and second order optimization. Due to the time limit, we retrain *only the best architecture* derived from the search phase and we repeat the experiment *only once*. Our results is currently on par with the results reported in paper. We will add more results later when ready. + +.. list-table:: + :header-rows: 1 + :widths: auto + + * - + - In paper + - Reproduction + * - First order (CIFAR10) + - 3.00 +/- 0.14 + - 2.78 + * - Second order (CIFAR10) + - 2.76 +/- 0.09 + - 2.80 + +Examples +"""""""" + +:githublink:`Example code ` + +.. code-block:: bash + + # In case NNI code is not cloned. If the code is cloned already, ignore this line and enter code folder. + git clone https://github.com/Microsoft/nni.git + + # search the best architecture + cd examples/nas/oneshot/darts + python3 search.py + + # train the best architecture + python3 retrain.py --arc-checkpoint ./checkpoints/epoch_49.json + +Limitations +""""""""""" + +* DARTS doesn't support DataParallel and needs to be customized in order to support DistributedDataParallel. + +.. _enas-strategy: + +ENAS +^^^^ + +The paper `Efficient Neural Architecture Search via Parameter Sharing `__ uses parameter sharing between child models to accelerate the NAS process. In ENAS, a controller learns to discover neural network architectures by searching for an optimal subgraph within a large computational graph. The controller is trained with policy gradient to select a subgraph that maximizes the expected reward on the validation set. Meanwhile the model corresponding to the selected subgraph is trained to minimize a canonical cross entropy loss. + +Implementation on NNI is based on the `official implementation in Tensorflow `__, including a general-purpose Reinforcement-learning controller and a trainer that trains target network and this controller alternatively. Following paper, we have also implemented macro and micro search space on CIFAR10 to demonstrate how to use these trainers. Since code to train from scratch on NNI is not ready yet, reproduction results are currently unavailable. + +.. autoclass:: nni.retiarii.oneshot.pytorch.EnasTrainer + +Examples +"""""""" + +:githublink:`Example code ` + +.. code-block:: bash + + # In case NNI code is not cloned. If the code is cloned already, ignore this line and enter code folder. + git clone https://github.com/Microsoft/nni.git + + # search the best architecture + cd examples/nas/oneshot/enas + + # search in macro search space + python3 search.py --search-for macro + + # search in micro search space + python3 search.py --search-for micro + + # view more options for search + python3 search.py -h + +.. _fbnet-strategy: + +FBNet +^^^^^ + +.. note:: This one-shot NAS is still implemented under NNI NAS 1.0, and will `be migrated to Retiarii framework in near future `__. + +For the mobile application of facial landmark, based on the basic architecture of PFLD model, we have applied the FBNet (Block-wise DNAS) to design an concise model with the trade-off between latency and accuracy. References are listed as below: + +* `FBNet: Hardware-Aware Efficient ConvNet Design via Differentiable Neural Architecture Search `__ +* `PFLD: A Practical Facial Landmark Detector `__ + +FBNet is a block-wise differentiable NAS method (Block-wise DNAS), where the best candidate building blocks can be chosen by using Gumbel Softmax random sampling and differentiable training. At each layer (or stage) to be searched, the diverse candidate blocks are side by side planned (just like the effectiveness of structural re-parameterization), leading to sufficient pre-training of the supernet. The pre-trained supernet is further sampled for finetuning of the subnet, to achieve better performance. + +.. image:: ../../../img/fbnet.png + :width: 800 + :align: center + +PFLD is a lightweight facial landmark model for realtime application. The architecture of PLFD is firstly simplified for acceleration, by using the stem block of PeleeNet, average pooling with depthwise convolution and eSE module. + +To achieve better trade-off between latency and accuracy, the FBNet is further applied on the simplified PFLD for searching the best block at each specific layer. The search space is based on the FBNet space, and optimized for mobile deployment by using the average pooling with depthwise convolution and eSE module etc. + +Experiments +""""""""""" + +To verify the effectiveness of FBNet applied on PFLD, we choose the open source dataset with 106 landmark points as the benchmark: + +* `Grand Challenge of 106-Point Facial Landmark Localization `__ + +The baseline model is denoted as MobileNet-V3 PFLD (`Reference baseline `__), and the searched model is denoted as Subnet. The experimental results are listed as below, where the latency is tested on Qualcomm 625 CPU (ARMv8): + +.. list-table:: + :header-rows: 1 + :widths: auto + + * - Model + - Size + - Latency + - Validation NME + * - MobileNet-V3 PFLD + - 1.01MB + - 10ms + - 6.22% + * - Subnet + - 693KB + - 1.60ms + - 5.58% + +Example +""""""" + +`Example code `__ + +Please run the following scripts at the example directory. + +The Python dependencies used here are listed as below: + +.. code-block:: bash + + numpy==1.18.5 + opencv-python==4.5.1.48 + torch==1.6.0 + torchvision==0.7.0 + onnx==1.8.1 + onnx-simplifier==0.3.5 + onnxruntime==1.7.0 + +To run the tutorial, follow the steps below: + +1. **Data Preparation**: Firstly, you should download the dataset `106points dataset `__ to the path ``./data/106points`` . The dataset includes the train-set and test-set: + + .. code-block:: bash + + ./data/106points/train_data/imgs + ./data/106points/train_data/list.txt + ./data/106points/test_data/imgs + ./data/106points/test_data/list.txt + +2. **Search**: Based on the architecture of simplified PFLD, the setting of multi-stage search space and hyper-parameters for searching should be firstly configured to construct the supernet. For example, + + .. code-block:: + + from lib.builder import search_space + from lib.ops import PRIMITIVES + from lib.supernet import PFLDInference, AuxiliaryNet + from nni.algorithms.nas.pytorch.fbnet import LookUpTable, NASConfig, + + # configuration of hyper-parameters + # search_space defines the multi-stage search space + nas_config = NASConfig( + model_dir="./ckpt_save", + nas_lr=0.01, + mode="mul", + alpha=0.25, + beta=0.6, + search_space=search_space, + ) + # lookup table to manage the information + lookup_table = LookUpTable(config=nas_config, primitives=PRIMITIVES) + # created supernet + pfld_backbone = PFLDInference(lookup_table) + + After creation of the supernet with the specification of search space and hyper-parameters, we can run below command to start searching and training of the supernet: + + .. code-block:: bash + + python train.py --dev_id "0,1" --snapshot "./ckpt_save" --data_root "./data/106points" + + The validation accuracy will be shown during training, and the model with best accuracy will be saved as ``./ckpt_save/supernet/checkpoint_best.pth``. + +3. **Finetune**: After pre-training of the supernet, we can run below command to sample the subnet and conduct the finetuning: + + .. code-block:: bash + + python retrain.py --dev_id "0,1" --snapshot "./ckpt_save" --data_root "./data/106points" \ + --supernet "./ckpt_save/supernet/checkpoint_best.pth" + + The validation accuracy will be shown during training, and the model with best accuracy will be saved as ``./ckpt_save/subnet/checkpoint_best.pth``. + +4. **Export**: After the finetuning of subnet, we can run below command to export the ONNX model: + + .. code-block:: bash + + python export.py --supernet "./ckpt_save/supernet/checkpoint_best.pth" \ + --resume "./ckpt_save/subnet/checkpoint_best.pth" + + ONNX model is saved as ``./output/subnet.onnx``, which can be further converted to the mobile inference engine by using `MNN `__ . + The checkpoints of pre-trained supernet and subnet are offered as below: + + * `Supernet `__ + * `Subnet `__ + * `ONNX model `__ + +.. _spos-strategy: + +SPOS +^^^^ + +Proposed in `Single Path One-Shot Neural Architecture Search with Uniform Sampling `__ is a one-shot NAS method that addresses the difficulties in training One-Shot NAS models by constructing a simplified supernet trained with an uniform path sampling method, so that all underlying architectures (and their weights) get trained fully and equally. An evolutionary algorithm is then applied to efficiently search for the best-performing architectures without any fine tuning. + +Implementation on NNI is based on `official repo `__. We implement a trainer that trains the supernet and a evolution tuner that leverages the power of NNI framework that speeds up the evolutionary search phase. + +.. autoclass:: nni.retiarii.oneshot.pytorch.SinglePathTrainer + +Examples +"""""""" + +Here is a use case, which is the search space in paper. However, we applied latency limit instead of flops limit to perform the architecture search phase. + +:githublink:`Example code ` + +**Requirements:** Prepare ImageNet in the standard format (follow the script `here `__). Linking it to ``data/imagenet`` will be more convenient. Download the checkpoint file from `here `__ (maintained by `Megvii `__) if you don't want to retrain the supernet. Put ``checkpoint-150000.pth.tar`` under ``data`` directory. After preparation, it's expected to have the following code structure: + +.. code-block:: bash + + spos + ├── architecture_final.json + ├── blocks.py + ├── data + │ ├── imagenet + │ │ ├── train + │ │ └── val + │ └── checkpoint-150000.pth.tar + ├── network.py + ├── readme.md + ├── supernet.py + ├── evaluation.py + ├── search.py + └── utils.py + +Then follow the 3 steps: + +1. **Train Supernet**: + + .. code-block:: bash + + python supernet.py + + This will export the checkpoint to ``checkpoints`` directory, for the next step. + + .. note:: The data loading used in the official repo is `slightly different from usual `__, as they use BGR tensor and keep the values between 0 and 255 intentionally to align with their own DL framework. The option ``--spos-preprocessing`` will simulate the behavior used originally and enable you to use the checkpoints pretrained. + +2. **Evolution Search**: Single Path One-Shot leverages evolution algorithm to search for the best architecture. In the paper, the search module, which is responsible for testing the sampled architecture, recalculates all the batch norm for a subset of training images, and evaluates the architecture on the full validation set. + In this example, it will inherit the ``state_dict`` of supernet from `./data/checkpoint-150000.pth.tar`, and search the best architecture with the regularized evolution strategy. Search in the supernet with the following command + + .. code-block:: bash + + python search.py + + NNI support a latency filter to filter unsatisfied model from search phase. Latency is predicted by Microsoft nn-Meter (https://github.com/microsoft/nn-Meter). To apply the latency filter, users could run search.py with additional arguments ``--latency-filter``. Here is an example: + + .. code-block:: bash + + python search.py --latency-filter cortexA76cpu_tflite21 + + Note that the latency filter is only supported for base execution engine. + + The final architecture exported from every epoch of evolution can be found in ``trials`` under the working directory of your tuner, which, by default, is ``$HOME/nni-experiments/your_experiment_id/trials``. + +3. **Train for Evaluation**: + + .. code-block:: bash + + python evaluation.py + + By default, it will use ``architecture_final.json``. This architecture is provided by the official repo (converted into NNI format). You can use any architecture (e.g., the architecture found in step 2) with ``--fixed-arc`` option. + +Known Limitations +""""""""""""""""" + +* Block search only. Channel search is not supported yet. + +Current Reproduction Results +"""""""""""""""""""""""""""" + +Reproduction is still undergoing. Due to the gap between official release and original paper, we compare our current results with official repo (our run) and paper. + +* Evolution phase is almost aligned with official repo. Our evolution algorithm shows a converging trend and reaches ~65% accuracy at the end of search. Nevertheless, this result is not on par with paper. For details, please refer to `this issue `__. +* Retrain phase is not aligned. Our retraining code, which uses the architecture released by the authors, reaches 72.14% accuracy, still having a gap towards 73.61% by official release and 74.3% reported in original paper. + +.. _proxylessnas-strategy: + +ProxylessNAS +^^^^^^^^^^^^ + +The paper `ProxylessNAS: Direct Neural Architecture Search on Target Task and Hardware `__ removes proxy, it directly learns the architectures for large-scale target tasks and target hardware platforms. They address high memory consumption issue of differentiable NAS and reduce the computational cost to the same level of regular training while still allowing a large candidate set. Please refer to the paper for the details. + +.. autoclass:: nni.retiarii.oneshot.pytorch.ProxylessTrainer + +To use ProxylessNAS training/searching approach, users need to specify search space in their model using :doc:`NNI NAS interface
`, e.g., ``LayerChoice``, ``InputChoice``. After defining and instantiating the model, the following work can be leaved to ProxylessNasTrainer by instantiating the trainer and passing the model to it. + +.. code-block:: python + + trainer = ProxylessTrainer(model, + loss=LabelSmoothingLoss(), + dataset=None, + optimizer=optimizer, + metrics=lambda output, target: accuracy(output, target, topk=(1, 5,)), + num_epochs=120, + log_frequency=10, + grad_reg_loss_type=args.grad_reg_loss_type, + grad_reg_loss_params=grad_reg_loss_params, + applied_hardware=args.applied_hardware, dummy_input=(1, 3, 224, 224), + ref_latency=args.reference_latency) + trainer.train() + trainer.export(args.arch_path) + +The complete example code can be found :githublink:`here `. + +Implementation +"""""""""""""" + +The implementation on NNI is based on the `offical implementation `__. The official implementation supports two training approaches: gradient descent and RL based. In our current implementation on NNI, gradient descent training approach is supported. The complete support of ProxylessNAS is ongoing. + +The official implementation supports different targeted hardware, including 'mobile', 'cpu', 'gpu8', 'flops'. In NNI repo, the hardware latency prediction is supported by `Microsoft nn-Meter `__. nn-Meter is an accurate inference latency predictor for DNN models on diverse edge devices. nn-Meter support four hardwares up to now, including ``cortexA76cpu_tflite21``, ``adreno640gpu_tflite21``, ``adreno630gpu_tflite21``, and ``myriadvpu_openvino2019r2``. Users can find more information about nn-Meter on its website. More hardware will be supported in the future. Users could find more details about applying ``nn-Meter`` :doc:`here
`. + +Below we will describe implementation details. Like other one-shot NAS algorithms on NNI, ProxylessNAS is composed of two parts: *search space* and *training approach*. For users to flexibly define their own search space and use built-in ProxylessNAS training approach, please refer to :githublink:`example code ` for a reference. + +.. image:: ../../../img/proxylessnas.png + :width: 450 + :align: center + +ProxylessNAS training approach is composed of ProxylessLayerChoice and ProxylessNasTrainer. ProxylessLayerChoice instantiates MixedOp for each mutable (i.e., LayerChoice), and manage architecture weights in MixedOp. **For DataParallel**, architecture weights should be included in user model. Specifically, in ProxylessNAS implementation, we add MixedOp to the corresponding mutable (i.e., LayerChoice) as a member variable. The ProxylessLayerChoice class also exposes two member functions, i.e., ``resample``, ``finalize_grad``, for the trainer to control the training of architecture weights. + +Reproduction Results +"""""""""""""""""""" + +To reproduce the result, we first run the search, we found that though it runs many epochs the chosen architecture converges at the first several epochs. This is probably induced by hyper-parameters or the implementation, we are working on it. + +Customization +------------- + +Multi-trial +^^^^^^^^^^^ + +.. autoclass:: nni.retiarii.Sampler + :noindex: + :members: + +.. autoclass:: nni.retiarii.strategy.BaseStrategy + :members: + +.. automodule:: nni.retiarii.execution + :members: + :imported-members: + :undoc-members: + +One-shot +^^^^^^^^ + +.. autoclass:: nni.retiarii.oneshot.BaseOneShotTrainer + :members: + +.. autofunction:: nni.retiarii.oneshot.pytorch.utils.replace_layer_choice + +.. autofunction:: nni.retiarii.oneshot.pytorch.utils.replace_input_choice diff --git a/docs/source/reference/nas/toctree.rst b/docs/source/reference/nas/toctree.rst new file mode 100644 index 0000000000000000000000000000000000000000..6dbd070145673602ef02bad4b56dc3fd819ee539 --- /dev/null +++ b/docs/source/reference/nas/toctree.rst @@ -0,0 +1,10 @@ +NAS API Reference +================= + +.. toctree:: + :maxdepth: 2 + + search_space + strategy + evaluator + Others diff --git a/docs/source/reference/nnictl.rst b/docs/source/reference/nnictl.rst index af313f8fa17eccc798d6542056ee634a1beb86a9..1452fa181f0e5f74fc6dfeb9f05741d7466cf8c9 100644 --- a/docs/source/reference/nnictl.rst +++ b/docs/source/reference/nnictl.rst @@ -1,5 +1,5 @@ -nnictl -====== +nnictl Commands +=============== .. argparse:: :module: nni.tools.nnictl.nnictl diff --git a/docs/source/reference/others.rst b/docs/source/reference/others.rst new file mode 100644 index 0000000000000000000000000000000000000000..a2b5d2a278c4eec2e707d342e5ee0ddc52ae7a5a --- /dev/null +++ b/docs/source/reference/others.rst @@ -0,0 +1,14 @@ +Uncategorized Modules +===================== + +nni.common.serializer +--------------------- + +.. automodule:: nni.common.serializer + :members: + +nni.typehint +------------ + +.. automodule:: nni.typehint + :members: diff --git a/docs/source/reference/python_api.rst b/docs/source/reference/python_api.rst new file mode 100644 index 0000000000000000000000000000000000000000..34959e3c16dd01007517b462f1376d5e4aae8ca0 --- /dev/null +++ b/docs/source/reference/python_api.rst @@ -0,0 +1,11 @@ +Python API Reference +==================== + +.. toctree:: + :maxdepth: 1 + + Hyperparameter Optimization + Neural Architecture Search + Model Compression + Experiment + Others diff --git a/docs/source/reference_zh.rst b/docs/source/reference_zh.rst deleted file mode 100644 index c8911b662c9db7d840312c758163ab1594cb9732..0000000000000000000000000000000000000000 --- a/docs/source/reference_zh.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. 19ce4f2ee1d3c4f1be277ab09ba40092 - -参考 -================== - -.. toctree:: - :maxdepth: 2 - - nnictl 命令 - Experiment 配置 - Experiment 配置(遗产) - 搜索空间 - NNI Annotation - SDK API 参考 - 支持的框架和库 - 从 Python 发起实验 - 共享存储 - Tensorboard diff --git a/docs/source/refs.bib b/docs/source/refs.bib index d6c642b27bcf623232dc8d13b4d2b4638db0cb75..7a70a4c58feaf4ecf878340ffec7b2bdb47a9cd0 100644 --- a/docs/source/refs.bib +++ b/docs/source/refs.bib @@ -1,3 +1,67 @@ +/* HPO */ + +@article{bergstra2011algorithms, + title={Algorithms for hyper-parameter optimization}, + author={Bergstra, James and Bardenet, R{\'e}mi and Bengio, Yoshua and K{\'e}gl, Bal{\'a}zs}, + journal={Advances in neural information processing systems}, + volume={24}, + year={2011} +} + +@inproceedings{li2018metis, + title={Metis: Robustly tuning tail latencies of cloud systems}, + author={Li, Zhao Lucis and Liang, Chieh-Jan Mike and He, Wenjia and Zhu, Lianjie and Dai, Wenjun and Jiang, Jin and Sun, Guangzhong}, + booktitle={2018 USENIX Annual Technical Conference (USENIX ATC 18)}, + pages={981--992}, + year={2018} +} + +@inproceedings{hutter2011sequential, + title={Sequential model-based optimization for general algorithm configuration}, + author={Hutter, Frank and Hoos, Holger H and Leyton-Brown, Kevin}, + booktitle={International conference on learning and intelligent optimization}, + pages={507--523}, + year={2011}, + organization={Springer} +} + +@article{li2017hyperband, + title={Hyperband: A novel bandit-based approach to hyperparameter optimization}, + author={Li, Lisha and Jamieson, Kevin and DeSalvo, Giulia and Rostamizadeh, Afshin and Talwalkar, Ameet}, + journal={The Journal of Machine Learning Research}, + volume={18}, + number={1}, + pages={6765--6816}, + year={2017}, + publisher={JMLR. org} +} + +@inproceedings{falkner2018bohb, + title={BOHB: Robust and efficient hyperparameter optimization at scale}, + author={Falkner, Stefan and Klein, Aaron and Hutter, Frank}, + booktitle={International Conference on Machine Learning}, + pages={1437--1446}, + year={2018}, + organization={PMLR} +} + +/* NAS */ + +@inproceedings{zoph2017neural, + title={Neural Architecture Search with Reinforcement Learning}, + author={Zoph, Barret and Le, Quoc V}, + booktitle={International Conference on Learning Representations}, + year={2017} +} + +@inproceedings{zoph2018learning, + title={Learning transferable architectures for scalable image recognition}, + author={Zoph, Barret and Vasudevan, Vijay and Shlens, Jonathon and Le, Quoc V}, + booktitle={Proceedings of the IEEE conference on computer vision and pattern recognition}, + pages={8697--8710}, + year={2018} +} + @inproceedings{liu2018darts, title={DARTS: Differentiable Architecture Search}, author={Liu, Hanxiao and Simonyan, Karen and Yang, Yiming}, @@ -27,3 +91,27 @@ year={2018}, organization={PMLR} } + +@inproceedings{radosavovic2019network, + title={On network design spaces for visual recognition}, + author={Radosavovic, Ilija and Johnson, Justin and Xie, Saining and Lo, Wan-Yen and Doll{\'a}r, Piotr}, + booktitle={Proceedings of the IEEE/CVF International Conference on Computer Vision}, + pages={1882--1890}, + year={2019} +} + +@inproceedings{ying2019bench, + title={Nas-bench-101: Towards reproducible neural architecture search}, + author={Ying, Chris and Klein, Aaron and Christiansen, Eric and Real, Esteban and Murphy, Kevin and Hutter, Frank}, + booktitle={International Conference on Machine Learning}, + pages={7105--7114}, + year={2019}, + organization={PMLR} +} + +@inproceedings{dong2019bench, + title={NAS-Bench-201: Extending the Scope of Reproducible Neural Architecture Search}, + author={Dong, Xuanyi and Yang, Yi}, + booktitle={International Conference on Learning Representations}, + year={2019} +} diff --git a/docs/source/Release.rst b/docs/source/release.rst similarity index 94% rename from docs/source/Release.rst rename to docs/source/release.rst index 1bb467f74522ef7a162cdb14911dde973396dbc0..1d7cb5395600d488e5ad490ad371268af57a9ee6 100644 --- a/docs/source/Release.rst +++ b/docs/source/release.rst @@ -5,6 +5,61 @@ Change Log ========== +Release 2.7 - 4/18/2022 +----------------------- + +Documentation +^^^^^^^^^^^^^ + +A full-size upgrade of the documentation, with the following significant improvements in the reading experience, practical tutorials, and examples: + +* Reorganized the document structure with a new document template. (`Upgraded doc entry `__) +* Add more friendly tutorials with jupyter notebook. (`New Quick Starts `__) +* New model pruning demo available. (`Youtube entry `__, `Bilibili entry `__) + +Hyper-Parameter Optimization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* [Improvement] TPE and random tuners will not generate duplicate hyperparameters anymore. +* [Improvement] Most Python APIs now have type annotations. + +Neural Architecture Search +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* Jointly search for architecture and hyper-parameters: ValueChoice in evaluator. (`doc `__) +* Support composition (transformation) of one or several value choices. (`doc `__) +* Enhanced Cell API (``merge_op``, preprocessor, postprocessor). (`doc `__) +* The argument ``depth`` in the ``Repeat`` API allows ValueChoice. (`doc `__) +* Support loading ``state_dict`` between sub-net and super-net. (`doc `__, `example in spos `__) +* Support BN fine-tuning and evaluation in SPOS example. (`doc `__) +* *Experimental* Model hyper-parameter choice. (`doc `__) +* *Preview* Lightning implementation for Retiarii including DARTS, ENAS, ProxylessNAS and RandomNAS. (`example usage `__) +* *Preview* A search space hub that contains 10 search spaces. (`code `__) + +Model Compression +^^^^^^^^^^^^^^^^^ + +* Pruning V2 is promoted as default pruning framework, old pruning is legacy and keeps for a few releases.(`doc `__) +* A new pruning mode ``balance`` is supported in ``LevelPruner``.(`doc `__) +* Support coarse-grained pruning in ``ADMMPruner``.(`doc `__) +* [Improvement] Support more operation types in pruning speedup. +* [Improvement] Optimize performance of some pruners. + +Experiment +^^^^^^^^^^ + +* [Improvement] Experiment.run() no longer stops web portal on return. + +Notable Bugfixes +^^^^^^^^^^^^^^^^ + +* Fixed: experiment list could not open experiment with prefix. +* Fixed: serializer for complex kinds of arguments. +* Fixed: some typos in code. (thanks @a1trl9 @mrshu) +* Fixed: dependency issue across layer in pruning speedup. +* Fixed: uncheck trial doesn't work bug in the detail table. +* Fixed: filter name | id bug in the experiment management page. + Release 2.6 - 1/19/2022 ----------------------- @@ -1506,7 +1561,7 @@ NNICTL new features and updates Before v0.3, NNI only supports running single experiment once a time. After this release, users are able to run multiple experiments simultaneously. Each experiment will require a unique port, the 1st experiment will be set to the default port as previous versions. You can specify a unique port for the rest experiments as below: - .. code-block:: bash + .. code-block:: text nnictl create --port 8081 --config diff --git a/docs/source/sdk_reference.rst b/docs/source/sdk_reference.rst deleted file mode 100644 index 4d5a64353194c2d77f8c4fe96da699b2db2b2803..0000000000000000000000000000000000000000 --- a/docs/source/sdk_reference.rst +++ /dev/null @@ -1,12 +0,0 @@ -#################### -Python API Reference -#################### - - -.. toctree:: - :maxdepth: 1 - - Auto Tune - NAS - Compression - Python API \ No newline at end of file diff --git a/docs/source/sdk_reference_zh.rst b/docs/source/sdk_reference_zh.rst deleted file mode 100644 index fbf85cad7af28755e3e13e3c36c283aa71db6330..0000000000000000000000000000000000000000 --- a/docs/source/sdk_reference_zh.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. 60cb924d0ec522b7709acf4f8cff3f16 - -#################### -Python API 参考 -#################### - - -.. toctree:: - :maxdepth: 1 - - 自动调优 - NAS - 模型压缩 - Python API \ No newline at end of file diff --git a/docs/source/sharings/automodel_toctree.rst b/docs/source/sharings/automodel_toctree.rst new file mode 100644 index 0000000000000000000000000000000000000000..b49cabc511b519ead6739da2db1f3dacc673b050 --- /dev/null +++ b/docs/source/sharings/automodel_toctree.rst @@ -0,0 +1,10 @@ +Automatic Model Tuning +====================== + +.. toctree:: + :maxdepth: 1 + + Tuning SVD automatically + EfficientNet on NNI + Automatic Model Architecture Search for Reading Comprehension + Parallelizing Optimization for TPE \ No newline at end of file diff --git a/docs/source/sharings/autosys_toctree.rst b/docs/source/sharings/autosys_toctree.rst new file mode 100644 index 0000000000000000000000000000000000000000..0f00d8beb5bdee121329157142431de9957b0d19 --- /dev/null +++ b/docs/source/sharings/autosys_toctree.rst @@ -0,0 +1,9 @@ +Automatic System Tuning +======================= + +.. toctree:: + :maxdepth: 1 + + Tuning SPTAG (Space Partition Tree And Graph) automatically + Tuning the performance of RocksDB + Tuning Tensor Operators automatically \ No newline at end of file diff --git a/docs/source/sharings/community_sharings.rst b/docs/source/sharings/community_sharings.rst new file mode 100644 index 0000000000000000000000000000000000000000..8de66dcb490c0556009ffe13bb12742c01c3da59 --- /dev/null +++ b/docs/source/sharings/community_sharings.rst @@ -0,0 +1,14 @@ +Use Cases and Solutions +======================= + +.. toctree:: + :maxdepth: 1 + + Overview + Automatic Model Tuning (HPO/NAS) + Automatic System Tuning (AutoSys) + Model Compression + Feature Engineering + Performance measurement, comparison and analysis + Use NNI on Google Colab + nnSpider Emoticons diff --git a/docs/source/TrialExample/EfficientNet.rst b/docs/source/sharings/efficientnet.rst similarity index 86% rename from docs/source/TrialExample/EfficientNet.rst rename to docs/source/sharings/efficientnet.rst index b544f88312c8add93eda0f090d0d01263cc6e8ba..0c010f6f0faef85a0e0e66ac7a88d0bad10f259d 100644 --- a/docs/source/TrialExample/EfficientNet.rst +++ b/docs/source/sharings/efficientnet.rst @@ -15,7 +15,7 @@ Instructions #. Run ``git clone https://github.com/ultmaster/EfficientNet-PyTorch`` to clone the `ultmaster modified version `__ of the original `EfficientNet-PyTorch `__. The modifications were done to adhere to the original `Tensorflow version `__ as close as possible (including EMA, label smoothing and etc.); also added are the part which gets parameters from tuner and reports intermediate/final results. Clone it into ``EfficientNet-PyTorch``\ ; the files like ``main.py``\ , ``train_imagenet.sh`` will appear inside, as specified in the configuration files. #. Run ``nnictl create --config config_local.yml`` (use ``config_pai.yml`` for OpenPAI) to find the best EfficientNet-B1. Adjust the training service (PAI/local/remote), batch size in the config files according to the environment. -For training on ImageNet, read ``EfficientNet-PyTorch/train_imagenet.sh``. Download ImageNet beforehand and extract it adhering to `PyTorch format `__ and then replace ``/mnt/data/imagenet`` in with the location of the ImageNet storage. This file should also be a good example to follow for mounting ImageNet into the container on OpenPAI. +For training on ImageNet, read ``EfficientNet-PyTorch/train_imagenet.sh``. Download ImageNet beforehand and extract it adhering to `PyTorch format `__ and then replace ``/mnt/data/imagenet`` in with the location of the ImageNet storage. This file should also be a good example to follow for mounting ImageNet into the container on OpenPAI. Results ------- diff --git a/docs/source/sharings/feature_engineering_toctree.rst b/docs/source/sharings/feature_engineering_toctree.rst new file mode 100644 index 0000000000000000000000000000000000000000..10a86cf9d7fd84c4f6eab053996a5ce958d2a471 --- /dev/null +++ b/docs/source/sharings/feature_engineering_toctree.rst @@ -0,0 +1,7 @@ +Feature Engineering +=================== + +.. toctree:: + :maxdepth: 1 + + NNI review article from Zhihu: - By Garvin Li diff --git a/docs/source/CommunitySharings/HpoComparison.rst b/docs/source/sharings/hpo_comparison.rst similarity index 92% rename from docs/source/CommunitySharings/HpoComparison.rst rename to docs/source/sharings/hpo_comparison.rst index 5a95e42f875c47577b4b0b625c4e11e7568a25a0..88f4622f1d2dbf83662641fd7238bf73070421bc 100644 --- a/docs/source/CommunitySharings/HpoComparison.rst +++ b/docs/source/sharings/hpo_comparison.rst @@ -5,24 +5,13 @@ Hyper Parameter Optimization Comparison Comparison of Hyperparameter Optimization (HPO) algorithms on several problems. -Hyperparameter Optimization algorithms are list below: - - -* `Random Search <../Tuner/BuiltinTuner.rst>`__ -* `Grid Search <../Tuner/BuiltinTuner.rst>`__ -* `Evolution <../Tuner/BuiltinTuner.rst>`__ -* `Anneal <../Tuner/BuiltinTuner.rst>`__ -* `Metis <../Tuner/BuiltinTuner.rst>`__ -* `TPE <../Tuner/BuiltinTuner.rst>`__ -* `SMAC <../Tuner/BuiltinTuner.rst>`__ -* `HyperBand <../Tuner/BuiltinTuner.rst>`__ -* `BOHB <../Tuner/BuiltinTuner.rst>`__ +Hyperparameter Optimization algorithms are listed in :doc:`/hpo/tuners`. All algorithms run in NNI local environment. -Machine Environment: +Machine Environment: -.. code-block:: bash +.. code-block:: text OS: Linux Ubuntu 16.04 LTS CPU: Intel(R) Xeon(R) CPU E5-2690 v3 @ 2.60GHz 2600 MHz @@ -39,7 +28,7 @@ AutoGBDT Example Problem Description ^^^^^^^^^^^^^^^^^^^ -Nonconvex problem on the hyper-parameter search of `AutoGBDT <../TrialExample/GbdtExample.rst>`__ example. +Nonconvex problem on the hyper-parameter search of :githublink:`AutoGBDT example `. Search Space ^^^^^^^^^^^^ @@ -215,7 +204,7 @@ The performance of ``DB_Bench`` is associated with the machine configuration and Machine configuration ^^^^^^^^^^^^^^^^^^^^^ -.. code-block:: bash +.. code-block:: text RocksDB: version 6.1 CPU: 6 * Intel(R) Xeon(R) CPU E5-2690 v4 @ 2.60GHz diff --git a/docs/img/emoicons/Comfort.png b/docs/source/sharings/images/nn_spider/comfort.png similarity index 100% rename from docs/img/emoicons/Comfort.png rename to docs/source/sharings/images/nn_spider/comfort.png diff --git a/docs/img/emoicons/Crying.png b/docs/source/sharings/images/nn_spider/crying.png similarity index 100% rename from docs/img/emoicons/Crying.png rename to docs/source/sharings/images/nn_spider/crying.png diff --git a/docs/img/emoicons/Cut.png b/docs/source/sharings/images/nn_spider/cut.png similarity index 100% rename from docs/img/emoicons/Cut.png rename to docs/source/sharings/images/nn_spider/cut.png diff --git a/docs/img/emoicons/Error.png b/docs/source/sharings/images/nn_spider/error.png similarity index 100% rename from docs/img/emoicons/Error.png rename to docs/source/sharings/images/nn_spider/error.png diff --git a/docs/img/emoicons/Holiday.png b/docs/source/sharings/images/nn_spider/holiday.png similarity index 100% rename from docs/img/emoicons/Holiday.png rename to docs/source/sharings/images/nn_spider/holiday.png diff --git a/docs/img/emoicons/home.svg b/docs/source/sharings/images/nn_spider/home.svg similarity index 100% rename from docs/img/emoicons/home.svg rename to docs/source/sharings/images/nn_spider/home.svg diff --git a/docs/img/emoicons/NoBug.png b/docs/source/sharings/images/nn_spider/nobug.png similarity index 100% rename from docs/img/emoicons/NoBug.png rename to docs/source/sharings/images/nn_spider/nobug.png diff --git a/docs/img/emoicons/Sign.png b/docs/source/sharings/images/nn_spider/sign.png similarity index 100% rename from docs/img/emoicons/Sign.png rename to docs/source/sharings/images/nn_spider/sign.png diff --git a/docs/img/emoicons/Sweat.png b/docs/source/sharings/images/nn_spider/sweat.png similarity index 100% rename from docs/img/emoicons/Sweat.png rename to docs/source/sharings/images/nn_spider/sweat.png diff --git a/docs/img/emoicons/Weaving.png b/docs/source/sharings/images/nn_spider/weaving.png similarity index 100% rename from docs/img/emoicons/Weaving.png rename to docs/source/sharings/images/nn_spider/weaving.png diff --git a/docs/img/emoicons/Working.png b/docs/source/sharings/images/nn_spider/working.png similarity index 100% rename from docs/img/emoicons/Working.png rename to docs/source/sharings/images/nn_spider/working.png diff --git a/docs/source/TrialExample/KDExample.rst b/docs/source/sharings/kd_example.rst similarity index 74% rename from docs/source/TrialExample/KDExample.rst rename to docs/source/sharings/kd_example.rst index 29a23ae02bdfcd7412f39b674b3b5ac91bf133bb..20d4e25eb65218219c76dc91ec86270ea283fe5c 100644 --- a/docs/source/TrialExample/KDExample.rst +++ b/docs/source/sharings/kd_example.rst @@ -35,12 +35,12 @@ PyTorch code loss.backward() -The complete code for fine-tuning the pruned model can be found :githublink:`here ` +The complete code for fine-tuning the pruned model can be found :githublink:`here ` -.. code-block:: python +.. code-block:: bash - python finetune_kd_torch.py --model [model name] --teacher-model-dir [pretrained checkpoint path] --student-model-dir [pruned checkpoint path] --mask-path [mask file path] + python finetune_kd_torch.py --model [model name] --teacher-model-dir [pretrained checkpoint path] --student-model-dir [pruned checkpoint path] --mask-path [mask file path] -Note that: for fine-tuning a pruned model, run :githublink:`basic_pruners_torch.py ` first to get the mask file, then pass the mask path as argument to the script. +Note that: for fine-tuning a pruned model, run :githublink:`basic_pruners_torch.py ` first to get the mask file, then pass the mask path as argument to the script. diff --git a/docs/source/CommunitySharings/ModelCompressionComparison.rst b/docs/source/sharings/model_compress_comp.rst similarity index 72% rename from docs/source/CommunitySharings/ModelCompressionComparison.rst rename to docs/source/sharings/model_compress_comp.rst index de22b8639028824c9bda6352f5b95396955ac7e8..ec610774d44824aa57c3a372a55723f500973e9e 100644 --- a/docs/source/CommunitySharings/ModelCompressionComparison.rst +++ b/docs/source/sharings/model_compress_comp.rst @@ -13,7 +13,7 @@ The experiments are performed with the following pruners/datasets/models: * - Models: :githublink:`VGG16, ResNet18, ResNet50 ` + Models: :githublink:`VGG16, ResNet18, ResNet50 ` * Datasets: CIFAR-10 @@ -35,7 +35,7 @@ The experiments are performed with the following pruners/datasets/models: For the pruners with scheduling, ``L1Filter Pruner`` is used as the base algorithm. That is to say, after the sparsities distribution is decided by the scheduling algorithm, ``L1Filter Pruner`` is used to performn real pruning. * - All the pruners listed above are implemented in :githublink:`nni `. + All the pruners listed above are implemented in :doc:`nni `. Experiment Result ----------------- @@ -50,24 +50,24 @@ The experiment result are shown in the following figures: CIFAR-10, VGG16: -.. image:: ../../../examples/model_compress/pruning/comparison_of_pruners/img/performance_comparison_vgg16.png - :target: ../../../examples/model_compress/pruning/comparison_of_pruners/img/performance_comparison_vgg16.png +.. image:: ../../../examples/model_compress/pruning/legacy/comparison_of_pruners/img/performance_comparison_vgg16.png + :target: ../../../examples/model_compress/pruning/legacy/comparison_of_pruners/img/performance_comparison_vgg16.png :alt: CIFAR-10, ResNet18: -.. image:: ../../../examples/model_compress/pruning/comparison_of_pruners/img/performance_comparison_resnet18.png - :target: ../../../examples/model_compress/pruning/comparison_of_pruners/img/performance_comparison_resnet18.png +.. image:: ../../../examples/model_compress/pruning/legacy/comparison_of_pruners/img/performance_comparison_resnet18.png + :target: ../../../examples/model_compress/pruning/legacy/comparison_of_pruners/img/performance_comparison_resnet18.png :alt: CIFAR-10, ResNet50: -.. image:: ../../../examples/model_compress/pruning/comparison_of_pruners/img/performance_comparison_resnet50.png - :target: ../../../examples/model_compress/pruning/comparison_of_pruners/img/performance_comparison_resnet50.png +.. image:: ../../../examples/model_compress/pruning/legacy/comparison_of_pruners/img/performance_comparison_resnet50.png + :target: ../../../examples/model_compress/pruning/legacy/comparison_of_pruners/img/performance_comparison_resnet50.png :alt: @@ -88,22 +88,19 @@ Implementation Details ^^^^^^^^^^^^^^^^^^^^^^ -* - The experiment results are all collected with the default configuration of the pruners in nni, which means that when we call a pruner class in nni, we don't change any default class arguments. +* The experiment results are all collected with the default configuration of the pruners in nni, which means that when we call a pruner class in nni, we don't change any default class arguments. -* - Both FLOPs and the number of parameters are counted with :githublink:`Model FLOPs/Parameters Counter ` after :githublink:`model speed up `. +* Both FLOPs and the number of parameters are counted with :ref:`Model FLOPs/Parameters Counter ` after :doc:`model speedup `. This avoids potential issues of counting them of masked models. -* - The experiment code can be found :githublink:`here `. +* The experiment code can be found :githublink:`here `. Experiment Result Rendering ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * - If you follow the practice in the :githublink:`example `\ , for every single pruning experiment, the experiment result will be saved in JSON format as follows: + If you follow the practice in the :githublink:`example `\ , for every single pruning experiment, the experiment result will be saved in JSON format as follows: .. code-block:: json @@ -114,8 +111,8 @@ Experiment Result Rendering } * - The experiment results are saved :githublink:`here `. - You can refer to :githublink:`analyze ` to plot new performance comparison figures. + The experiment results are saved :githublink:`here `. + You can refer to :githublink:`analyze ` to plot new performance comparison figures. Contribution ------------ diff --git a/docs/source/sharings/model_compression_toctree.rst b/docs/source/sharings/model_compression_toctree.rst new file mode 100644 index 0000000000000000000000000000000000000000..a678654aa66eae226eb7ed05596f675022296127 --- /dev/null +++ b/docs/source/sharings/model_compression_toctree.rst @@ -0,0 +1,7 @@ +Model Compression +================= + +.. toctree:: + :maxdepth: 1 + + Knowledge distillation with NNI model compression \ No newline at end of file diff --git a/docs/source/CommunitySharings/NasComparison.rst b/docs/source/sharings/nas_comparison.rst similarity index 100% rename from docs/source/CommunitySharings/NasComparison.rst rename to docs/source/sharings/nas_comparison.rst diff --git a/docs/source/sharings/nn_spider.rst b/docs/source/sharings/nn_spider.rst new file mode 100644 index 0000000000000000000000000000000000000000..9be0a2e52a02b1a09d4d085fdf84ed03cbe78362 --- /dev/null +++ b/docs/source/sharings/nn_spider.rst @@ -0,0 +1,52 @@ +nnSpider Emoticons +================== + +* Comfort + + .. image:: images/nn_spider/comfort.png + :width: 400 + +* Crying + + .. image:: images/nn_spider/crying.png + :width: 400 + +* Cut + + .. image:: images/nn_spider/cut.png + :width: 400 + +* Error + + .. image:: images/nn_spider/error.png + :width: 400 + +* Holiday + + .. image:: images/nn_spider/holiday.png + :width: 400 + +* No bug + + .. image:: images/nn_spider/nobug.png + :width: 400 + +* Sign + + .. image:: images/nn_spider/sign.png + :width: 400 + +* Sweat + + .. image:: images/nn_spider/sweat.png + :width: 400 + +* Weaving + + .. image:: images/nn_spider/weaving.png + :width: 400 + +* Working + + .. image:: images/nn_spider/working.png + :width: 400 diff --git a/docs/source/CommunitySharings/NNI_AutoFeatureEng.rst b/docs/source/sharings/nni_autofeatureeng.rst similarity index 100% rename from docs/source/CommunitySharings/NNI_AutoFeatureEng.rst rename to docs/source/sharings/nni_autofeatureeng.rst diff --git a/docs/source/CommunitySharings/NNI_colab_support.rst b/docs/source/sharings/nni_colab_support.rst similarity index 52% rename from docs/source/CommunitySharings/NNI_colab_support.rst rename to docs/source/sharings/nni_colab_support.rst index 438f66bb2684c2123d8eba67d6021727074e73fb..99ca87d6bb7afdf29a3cd3dce0d87597b2bc93f3 100644 --- a/docs/source/CommunitySharings/NNI_colab_support.rst +++ b/docs/source/sharings/nni_colab_support.rst @@ -6,40 +6,42 @@ NNI can easily run on Google Colab platform. However, Colab doesn't expose its p How to Open NNI's Web UI on Google Colab ---------------------------------------- - #. Install required packages and softwares. -.. code-block:: bash + .. code-block:: bash - ! pip install nni # install nni - ! wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip # download ngrok and unzip it - ! unzip ngrok-stable-linux-amd64.zip - ! mkdir -p nni_repo - ! git clone https://github.com/microsoft/nni.git nni_repo/nni # clone NNI's offical repo to get examples + ! pip install nni # install nni + ! wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip # download ngrok and unzip it + ! unzip ngrok-stable-linux-amd64.zip + ! mkdir -p nni_repo + ! git clone https://github.com/microsoft/nni.git nni_repo/nni # clone NNI's offical repo to get examples -#. Register a ngrok account `here `__\ , then connect to your account using your authtoken. +#. Register a ngrok account `here `__, then connect to your account using your authtoken. -.. code-block:: bash + .. code-block:: bash - ! ./ngrok authtoken + ! ./ngrok authtoken YOUR_AUTH_TOKEN #. Start an NNI example on a port bigger than 1024, then start ngrok with the same port. If you want to use gpu, make sure gpuNum >= 1 in config.yml. Use ``get_ipython()`` to start ngrok since it will be stuck if you use ``! ngrok http 5000 &``. -.. code-block:: bash + .. code-block:: bash + + ! nnictl create --config nni_repo/nni/examples/trials/mnist-pytorch/config.yml --port 5000 & + + .. code-block:: python - ! nnictl create --config nni_repo/nni/examples/trials/mnist-pytorch/config.yml --port 5000 & - get_ipython().system_raw('./ngrok http 5000 &') + get_ipython().system_raw('./ngrok http 5000 &') #. Check the public url. -.. code-block:: bash + .. code-block:: bash - ! curl -s http://localhost:4040/api/tunnels # don't change the port number 4040 + ! curl -s http://localhost:4040/api/tunnels # don't change the port number 4040 -You will see an url like http://xxxx.ngrok.io after step 4, open this url and you will find NNI's Web UI. Have fun :) + You will see an url like ``http://xxxx.ngrok.io`` after step 4, open this url and you will find NNI's Web UI. Have fun :) Access Web UI with frp ---------------------- diff --git a/docs/source/TrialExample/OpEvoExamples.rst b/docs/source/sharings/op_evo_examples.rst similarity index 99% rename from docs/source/TrialExample/OpEvoExamples.rst rename to docs/source/sharings/op_evo_examples.rst index 870bdd2123e814cdfd1ef27445671fedf659b35a..f4984728b5a697811814eccaf3162c24594f1896 100644 --- a/docs/source/TrialExample/OpEvoExamples.rst +++ b/docs/source/sharings/op_evo_examples.rst @@ -118,7 +118,7 @@ Citing OpEvo If you feel OpEvo is helpful, please consider citing the paper as follows: -.. code-block:: bash +.. code-block:: bib @misc{gao2020opevo, title={OpEvo: An Evolutionary Method for Tensor Operator Optimization}, diff --git a/docs/source/sharings/overview.rst b/docs/source/sharings/overview.rst new file mode 100644 index 0000000000000000000000000000000000000000..a4b7c93507e29b0dd5b4fcf284f1f7d2191de6ac --- /dev/null +++ b/docs/source/sharings/overview.rst @@ -0,0 +1,46 @@ +Use Cases and Solutions +======================= + +Different from the tutorials and examples in the rest of the document which show the usage of a feature, this part mainly introduces end-to-end scenarios and use cases to help users further understand how NNI can help them. NNI can be widely adopted in various scenarios. We also encourage community contributors to share their AutoML practices especially the NNI usage practices from their experience. + +Automatic Model Tuning +---------------------- + +NNI can be applied on various model tuning tasks. Some state-of-the-art model search algorithms, such as EfficientNet, can be easily built on NNI. Popular models, e.g., recommendation models, can be tuned with NNI. The following are some use cases to illustrate how to leverage NNI in your model tuning tasks and how to build your own pipeline with NNI. + +* :doc:`Tuning SVD automatically ` +* :doc:`EfficientNet on NNI ` +* :doc:`Automatic Model Architecture Search for Reading Comprehension ` +* :doc:`Parallelizing Optimization for TPE ` + +Automatic System Tuning +----------------------- + +The performance of systems, such as database, tensor operator implementaion, often need to be tuned to adapt to specific hardware configuration, targeted workload, etc. Manually tuning a system is complicated and often requires detailed understanding of hardware and workload. NNI can make such tasks much easier and help system owners find the best configuration to the system automatically. The detailed design philosophy of automatic system tuning can be found in this `paper `__ . The following are some typical cases that NNI can help. + +* :doc:`Tuning SPTAG (Space Partition Tree And Graph) automatically ` +* :doc:`Tuning the performance of RocksDB ` +* :doc:`Tuning Tensor Operators automatically ` + +Model Compression +----------------- + +The following one shows how to apply knowledge distillation on NNI model compression. More use cases and solutions will be added in the future. + +* :doc:`Knowledge distillation with NNI model compression ` + +Feature Engineering +------------------- + +The following is an article about how NNI helps in auto feature engineering shared by a community contributor. More use cases and solutions will be added in the future. + +* :doc:`NNI review article from Zhihu: - By Garvin Li ` + +Performance Measurement, Comparison and Analysis +------------------------------------------------ + +Performance comparison and analysis can help users decide a proper algorithm (e.g., tuner, NAS algorithm) for their scenario. The following are some measurement and comparison data for users' reference. + +* :doc:`Neural Architecture Search Comparison ` +* :doc:`Hyper-parameter Tuning Algorithm Comparsion ` +* :doc:`Model Compression Algorithm Comparsion ` diff --git a/docs/source/CommunitySharings/ParallelizingTpeSearch.rst b/docs/source/sharings/parallelizing_tpe_search.rst similarity index 100% rename from docs/source/CommunitySharings/ParallelizingTpeSearch.rst rename to docs/source/sharings/parallelizing_tpe_search.rst diff --git a/docs/source/sharings/perf_compare_toctree.rst b/docs/source/sharings/perf_compare_toctree.rst new file mode 100644 index 0000000000000000000000000000000000000000..e27714b7b97855b91e8f79e1930a82c1e4f7d906 --- /dev/null +++ b/docs/source/sharings/perf_compare_toctree.rst @@ -0,0 +1,9 @@ +Performance Measurement, Comparison and Analysis +================================================ + +.. toctree:: + :maxdepth: 1 + + Neural Architecture Search Comparison + Hyper-parameter Tuning Algorithm Comparsion + Model Compression Algorithm Comparsion \ No newline at end of file diff --git a/docs/source/CommunitySharings/RecommendersSvd.rst b/docs/source/sharings/recommenders_svd.rst similarity index 100% rename from docs/source/CommunitySharings/RecommendersSvd.rst rename to docs/source/sharings/recommenders_svd.rst diff --git a/docs/source/TrialExample/RocksdbExamples.rst b/docs/source/sharings/rocksdb_examples.rst similarity index 91% rename from docs/source/TrialExample/RocksdbExamples.rst rename to docs/source/sharings/rocksdb_examples.rst index b917194854a77be389f666340129f5e9144bfaff..aaeb877a5bab46b018d47bf233fe080fccd28afa 100644 --- a/docs/source/TrialExample/RocksdbExamples.rst +++ b/docs/source/sharings/rocksdb_examples.rst @@ -8,7 +8,7 @@ Overview The performance of RocksDB is highly contingent on its tuning. However, because of the complexity of its underlying technology and a large number of configurable parameters, a good configuration is sometimes hard to obtain. NNI can help to address this issue. NNI supports many kinds of tuning algorithms to search the best configuration of RocksDB, and support many kinds of environments like local machine, remote servers and cloud. -This example illustrates how to use NNI to search the best configuration of RocksDB for a ``fillrandom`` benchmark supported by a benchmark tool ``db_bench``\ , which is an official benchmark tool provided by RocksDB itself. Therefore, before running this example, please make sure NNI is installed and `db_bench `__ is in your ``PATH``. Please refer to `here <../Tutorial/QuickStart.rst>`__ for detailed information about installation and preparing of NNI environment, and `here `__ for compiling RocksDB as well as ``db_bench``. +This example illustrates how to use NNI to search the best configuration of RocksDB for a ``fillrandom`` benchmark supported by a benchmark tool ``db_bench``\ , which is an official benchmark tool provided by RocksDB itself. Therefore, before running this example, please make sure NNI is installed and `db_bench `__ is in your ``PATH``. Please refer to :doc:`here ` for detailed information about installation and preparing of NNI environment, and `here `__ for compiling RocksDB as well as ``db_bench``. We also provide a simple script :githublink:`db_bench_installation.sh ` helping to compile and install ``db_bench`` as well as its dependencies on Ubuntu. Installing RocksDB on other systems can follow the same procedure. @@ -24,7 +24,7 @@ Search Space For simplicity, this example tunes three parameters, ``write_buffer_size``\ , ``min_write_buffer_num`` and ``level0_file_num_compaction_trigger``\ , for writing 16M keys with 20 Bytes of key size and 100 Bytes of value size randomly, based on writing operations per second (OPS). ``write_buffer_size`` sets the size of a single memtable. Once memtable exceeds this size, it is marked immutable and a new one is created. ``min_write_buffer_num`` is the minimum number of memtables to be merged before flushing to storage. Once the number of files in level 0 reaches ``level0_file_num_compaction_trigger``\ , level 0 to level 1 compaction is triggered. -In this example, the search space is specified by a ``search_space.json`` file as shown below. Detailed explanation of search space could be found `here <../Tutorial/SearchSpaceSpec.rst>`__. +In this example, the search space is specified by a ``search_space.json`` file as shown below. Detailed explanation of search space could be found :doc:`here `. .. code-block:: json @@ -48,8 +48,7 @@ In this example, the search space is specified by a ``search_space.json`` file a Benchmark code ^^^^^^^^^^^^^^ -Benchmark code should receive a configuration from NNI manager, and report the corresponding benchmark result back. Following NNI APIs are designed for this purpose. In this example, writing operations per second (OPS) is used as a performance metric. Please refer to `here `__ for detailed information. - +Benchmark code should receive a configuration from NNI manager, and report the corresponding benchmark result back. Following NNI APIs are designed for this purpose. In this example, writing operations per second (OPS) is used as a performance metric. * Use ``nni.get_next_parameter()`` to get next system configuration. * Use ``nni.report_final_result(metric)`` to report the benchmark result. @@ -59,7 +58,7 @@ Benchmark code should receive a configuration from NNI manager, and report the c Config file ^^^^^^^^^^^ -One could start a NNI experiment with a config file. A config file for NNI is a ``yaml`` file usually including experiment settings (\ ``trialConcurrency``\ , ``trialGpuNumber``\ , etc.), platform settings (\ ``trainingService``\ ), path settings (\ ``searchSpaceFile``\ , ``trialCodeDirectory``\ , etc.) and tuner settings (\ ``tuner``\ , ``tuner optimize_mode``\ , etc.). Please refer to `here <../Tutorial/QuickStart.rst>`__ for more information. +One could start a NNI experiment with a config file. A config file for NNI is a ``yaml`` file usually including experiment settings (\ ``trialConcurrency``\ , ``trialGpuNumber``\ , etc.), platform settings (\ ``trainingService``\ ), path settings (\ ``searchSpaceFile``\ , ``trialCodeDirectory``\ , etc.) and tuner settings (\ ``tuner``\ , ``tuner optimize_mode``\ , etc.). Please refer to :doc:`/reference/experiment_config`. Here is an example of tuning RocksDB with SMAC algorithm: @@ -69,7 +68,7 @@ Here is an example of tuning RocksDB with TPE algorithm: :githublink:`code directory ` -Other tuners can be easily adopted in the same way. Please refer to `here <../Tuner/BuiltinTuner.rst>`__ for more information. +Other tuners can be easily adopted in the same way. Please refer to :doc:`here ` for more information. Finally, we could enter the example folder and start the experiment using following commands: diff --git a/docs/source/CommunitySharings/SptagAutoTune.rst b/docs/source/sharings/sptag_auto_tune.rst similarity index 100% rename from docs/source/CommunitySharings/SptagAutoTune.rst rename to docs/source/sharings/sptag_auto_tune.rst diff --git a/docs/source/TrialExample/SquadEvolutionExamples.rst b/docs/source/sharings/squad_evolution_examples.rst similarity index 99% rename from docs/source/TrialExample/SquadEvolutionExamples.rst rename to docs/source/sharings/squad_evolution_examples.rst index 69cc7e4742f32efcf6e22112311b05eaa1316b3a..49f1215985b094ff63ea7787d00d21b93069889a 100644 --- a/docs/source/TrialExample/SquadEvolutionExamples.rst +++ b/docs/source/sharings/squad_evolution_examples.rst @@ -146,9 +146,9 @@ Among those files, ``trial.py`` and ``graph_to_tf.py`` are special. if topo_i == '|': continue if graph.layers[topo_i].graph_type == LayerType.input.value: - # ...... + ... elif graph.layers[topo_i].graph_type == LayerType.attention.value: - # ...... + ... # More layers to handle As we can see, this function is actually a compiler, that converts the internal model DAG configuration (which will be introduced in the ``Model configuration format`` section) ``graph``\ , to a Tensorflow computation graph. @@ -162,6 +162,7 @@ performs topological sorting on the internal graph representation, and the code .. code-block:: python for _, topo_i in enumerate(topology): + ... performs actually conversion that maps each layer to a part in Tensorflow computation graph. diff --git a/docs/source/training_services_zh.rst b/docs/source/training_services_zh.rst deleted file mode 100644 index 761536b2472ec6674ba1a2b5fe9b186fdaccbc6c..0000000000000000000000000000000000000000 --- a/docs/source/training_services_zh.rst +++ /dev/null @@ -1,17 +0,0 @@ -.. 4e054d96c7d211dc514c99d673415d8e - -NNI 支持的训练平台介绍 -===================================== - -.. toctree:: - Overview <./TrainingService/Overview> - 本机<./TrainingService/LocalMode> - 远程<./TrainingService/RemoteMachineMode> - OpenPAI<./TrainingService/PaiMode> - Kubeflow<./TrainingService/KubeflowMode> - AdaptDL<./TrainingService/AdaptDLMode> - FrameworkController<./TrainingService/FrameworkControllerMode> - DLTS<./TrainingService/DLTSMode> - AML<./TrainingService/AMLMode> - PAI-DLC<./TrainingService/DLCMode> - 混合模式 <./TrainingService/HybridMode> diff --git a/docs/source/tutorials.rst b/docs/source/tutorials.rst deleted file mode 100644 index 9759089cfe971b4b0cac6ad4792ba343dc972978..0000000000000000000000000000000000000000 --- a/docs/source/tutorials.rst +++ /dev/null @@ -1,28 +0,0 @@ -Tutorials -========= - -.. TOC - -.. toctree:: - :maxdepth: 2 - :hidden: - - tutorials/nni_experiment - tutorials/nas_quick_start_mnist - -.. ---------------------- - -.. cardlinkitem:: - :header: Start and Manage a New Experiment - :description: Familiarize yourself with Pythonic API to manage a hyper-parameter tuning experiment - :link: tutorials/nni_experiment.html - :image: ../img/thumbnails/overview-31.png - :tags: Experiment/HPO - -.. cardlinkitem:: - :header: Get started with NAS on MNIST - :description: bla bla bla bla - :link: tutorials/nas_quick_start_mnist.html - :image: ../img/thumbnails/overview-30.png - :background: cyan - :tags: NAS diff --git a/docs/source/tutorials/hello_nas.ipynb b/docs/source/tutorials/hello_nas.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..d7e1f9f88540cc160afe4f225df9582f31a0589c --- /dev/null +++ b/docs/source/tutorials/hello_nas.ipynb @@ -0,0 +1,259 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# Hello, NAS!\n\nThis is the 101 tutorial of Neural Architecture Search (NAS) on NNI.\nIn this tutorial, we will search for a neural architecture on MNIST dataset with the help of NAS framework of NNI, i.e., *Retiarii*.\nWe use multi-trial NAS as an example to show how to construct and explore a model space.\n\nThere are mainly three crucial components for a neural architecture search task, namely,\n\n* Model search space that defines a set of models to explore.\n* A proper strategy as the method to explore this model space.\n* A model evaluator that reports the performance of every model in the space.\n\nCurrently, PyTorch is the only supported framework by Retiarii, and we have only tested **PyTorch 1.7 to 1.10**.\nThis tutorial assumes PyTorch context but it should also apply to other frameworks, which is in our future plan.\n\n## Define your Model Space\n\nModel space is defined by users to express a set of models that users want to explore, which contains potentially good-performing models.\nIn this framework, a model space is defined with two parts: a base model and possible mutations on the base model.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Define Base Model\n\nDefining a base model is almost the same as defining a PyTorch (or TensorFlow) model.\nUsually, you only need to replace the code ``import torch.nn as nn`` with\n``import nni.retiarii.nn.pytorch as nn`` to use our wrapped PyTorch modules.\n\nBelow is a very simple example of defining a base model.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import torch\nimport torch.nn.functional as F\nimport nni.retiarii.nn.pytorch as nn\nfrom nni.retiarii import model_wrapper\n\n\n@model_wrapper # this decorator should be put on the out most\nclass Net(nn.Module):\n def __init__(self):\n super().__init__()\n self.conv1 = nn.Conv2d(1, 32, 3, 1)\n self.conv2 = nn.Conv2d(32, 64, 3, 1)\n self.dropout1 = nn.Dropout(0.25)\n self.dropout2 = nn.Dropout(0.5)\n self.fc1 = nn.Linear(9216, 128)\n self.fc2 = nn.Linear(128, 10)\n\n def forward(self, x):\n x = F.relu(self.conv1(x))\n x = F.max_pool2d(self.conv2(x), 2)\n x = torch.flatten(self.dropout1(x), 1)\n x = self.fc2(self.dropout2(F.relu(self.fc1(x))))\n output = F.log_softmax(x, dim=1)\n return output" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + ".. tip:: Always keep in mind that you should use ``import nni.retiarii.nn.pytorch as nn`` and :meth:`nni.retiarii.model_wrapper`.\n Many mistakes are a result of forgetting one of those.\n Also, please use ``torch.nn`` for submodules of ``nn.init``, e.g., ``torch.nn.init`` instead of ``nn.init``.\n\n### Define Model Mutations\n\nA base model is only one concrete model not a model space. We provide :doc:`API and Primitives
`\nfor users to express how the base model can be mutated. That is, to build a model space which includes many models.\n\nBased on the above base model, we can define a model space as below.\n\n.. code-block:: diff\n\n @model_wrapper\n class Net(nn.Module):\n def __init__(self):\n super().__init__()\n self.conv1 = nn.Conv2d(1, 32, 3, 1)\n - self.conv2 = nn.Conv2d(32, 64, 3, 1)\n + self.conv2 = nn.LayerChoice([\n + nn.Conv2d(32, 64, 3, 1),\n + DepthwiseSeparableConv(32, 64)\n + ])\n - self.dropout1 = nn.Dropout(0.25)\n + self.dropout1 = nn.Dropout(nn.ValueChoice([0.25, 0.5, 0.75]))\n self.dropout2 = nn.Dropout(0.5)\n - self.fc1 = nn.Linear(9216, 128)\n - self.fc2 = nn.Linear(128, 10)\n + feature = nn.ValueChoice([64, 128, 256])\n + self.fc1 = nn.Linear(9216, feature)\n + self.fc2 = nn.Linear(feature, 10)\n\n def forward(self, x):\n x = F.relu(self.conv1(x))\n x = F.max_pool2d(self.conv2(x), 2)\n x = torch.flatten(self.dropout1(x), 1)\n x = self.fc2(self.dropout2(F.relu(self.fc1(x))))\n output = F.log_softmax(x, dim=1)\n return output\n\nThis results in the following code:\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "class DepthwiseSeparableConv(nn.Module):\n def __init__(self, in_ch, out_ch):\n super().__init__()\n self.depthwise = nn.Conv2d(in_ch, in_ch, kernel_size=3, groups=in_ch)\n self.pointwise = nn.Conv2d(in_ch, out_ch, kernel_size=1)\n\n def forward(self, x):\n return self.pointwise(self.depthwise(x))\n\n\n@model_wrapper\nclass ModelSpace(nn.Module):\n def __init__(self):\n super().__init__()\n self.conv1 = nn.Conv2d(1, 32, 3, 1)\n # LayerChoice is used to select a layer between Conv2d and DwConv.\n self.conv2 = nn.LayerChoice([\n nn.Conv2d(32, 64, 3, 1),\n DepthwiseSeparableConv(32, 64)\n ])\n # ValueChoice is used to select a dropout rate.\n # ValueChoice can be used as parameter of modules wrapped in `nni.retiarii.nn.pytorch`\n # or customized modules wrapped with `@basic_unit`.\n self.dropout1 = nn.Dropout(nn.ValueChoice([0.25, 0.5, 0.75])) # choose dropout rate from 0.25, 0.5 and 0.75\n self.dropout2 = nn.Dropout(0.5)\n feature = nn.ValueChoice([64, 128, 256])\n self.fc1 = nn.Linear(9216, feature)\n self.fc2 = nn.Linear(feature, 10)\n\n def forward(self, x):\n x = F.relu(self.conv1(x))\n x = F.max_pool2d(self.conv2(x), 2)\n x = torch.flatten(self.dropout1(x), 1)\n x = self.fc2(self.dropout2(F.relu(self.fc1(x))))\n output = F.log_softmax(x, dim=1)\n return output\n\n\nmodel_space = ModelSpace()\nmodel_space" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This example uses two mutation APIs,\n:class:`nn.LayerChoice ` and\n:class:`nn.InputChoice `.\n:class:`nn.LayerChoice `\ntakes a list of candidate modules (two in this example), one will be chosen for each sampled model.\nIt can be used like normal PyTorch module.\n:class:`nn.InputChoice ` takes a list of candidate values,\none will be chosen to take effect for each sampled model.\n\nMore detailed API description and usage can be found :doc:`here
`.\n\n

Note

We are actively enriching the mutation APIs, to facilitate easy construction of model space.\n If the currently supported mutation APIs cannot express your model space,\n please refer to :doc:`this doc ` for customizing mutators.

\n\n## Explore the Defined Model Space\n\nThere are basically two exploration approaches: (1) search by evaluating each sampled model independently,\nwhich is the search approach in `multi-trial NAS `\nand (2) one-shot weight-sharing based search, which is used in one-shot NAS.\nWe demonstrate the first approach in this tutorial. Users can refer to `here ` for the second approach.\n\nFirst, users need to pick a proper exploration strategy to explore the defined model space.\nSecond, users need to pick or customize a model evaluator to evaluate the performance of each explored model.\n\n### Pick an exploration strategy\n\nRetiarii supports many :doc:`exploration strategies
`.\n\nSimply choosing (i.e., instantiate) an exploration strategy as below.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import nni.retiarii.strategy as strategy\nsearch_strategy = strategy.Random(dedup=True) # dedup=False if deduplication is not wanted" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Pick or customize a model evaluator\n\nIn the exploration process, the exploration strategy repeatedly generates new models. A model evaluator is for training\nand validating each generated model to obtain the model's performance.\nThe performance is sent to the exploration strategy for the strategy to generate better models.\n\nRetiarii has provided :doc:`built-in model evaluators
`, but to start with,\nit is recommended to use :class:`FunctionalEvaluator `,\nthat is, to wrap your own training and evaluation code with one single function.\nThis function should receive one single model class and uses :func:`nni.report_final_result` to report the final score of this model.\n\nAn example here creates a simple evaluator that runs on MNIST dataset, trains for 2 epochs, and reports its validation accuracy.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import nni\n\nfrom torchvision import transforms\nfrom torchvision.datasets import MNIST\nfrom torch.utils.data import DataLoader\n\n\ndef train_epoch(model, device, train_loader, optimizer, epoch):\n loss_fn = torch.nn.CrossEntropyLoss()\n model.train()\n for batch_idx, (data, target) in enumerate(train_loader):\n data, target = data.to(device), target.to(device)\n optimizer.zero_grad()\n output = model(data)\n loss = loss_fn(output, target)\n loss.backward()\n optimizer.step()\n if batch_idx % 10 == 0:\n print('Train Epoch: {} [{}/{} ({:.0f}%)]\\tLoss: {:.6f}'.format(\n epoch, batch_idx * len(data), len(train_loader.dataset),\n 100. * batch_idx / len(train_loader), loss.item()))\n\n\ndef test_epoch(model, device, test_loader):\n model.eval()\n test_loss = 0\n correct = 0\n with torch.no_grad():\n for data, target in test_loader:\n data, target = data.to(device), target.to(device)\n output = model(data)\n pred = output.argmax(dim=1, keepdim=True)\n correct += pred.eq(target.view_as(pred)).sum().item()\n\n test_loss /= len(test_loader.dataset)\n accuracy = 100. * correct / len(test_loader.dataset)\n\n print('\\nTest set: Accuracy: {}/{} ({:.0f}%)\\n'.format(\n correct, len(test_loader.dataset), accuracy))\n\n return accuracy\n\n\ndef evaluate_model(model_cls):\n # \"model_cls\" is a class, need to instantiate\n model = model_cls()\n\n device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')\n model.to(device)\n\n optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)\n transf = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])\n train_loader = DataLoader(MNIST('data/mnist', download=True, transform=transf), batch_size=64, shuffle=True)\n test_loader = DataLoader(MNIST('data/mnist', download=True, train=False, transform=transf), batch_size=64)\n\n for epoch in range(3):\n # train the model for one epoch\n train_epoch(model, device, train_loader, optimizer, epoch)\n # test the model for one epoch\n accuracy = test_epoch(model, device, test_loader)\n # call report intermediate result. Result can be float or dict\n nni.report_intermediate_result(accuracy)\n\n # report final test result\n nni.report_final_result(accuracy)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create the evaluator\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from nni.retiarii.evaluator import FunctionalEvaluator\nevaluator = FunctionalEvaluator(evaluate_model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The ``train_epoch`` and ``test_epoch`` here can be any customized function,\nwhere users can write their own training recipe.\n\nIt is recommended that the ``evaluate_model`` here accepts no additional arguments other than ``model_cls``.\nHowever, in the :doc:`advanced tutorial
`, we will show how to use additional arguments in case you actually need those.\nIn future, we will support mutation on the arguments of evaluators, which is commonly called \"Hyper-parmeter tuning\".\n\n## Launch an Experiment\n\nAfter all the above are prepared, it is time to start an experiment to do the model search. An example is shown below.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from nni.retiarii.experiment.pytorch import RetiariiExperiment, RetiariiExeConfig\nexp = RetiariiExperiment(model_space, evaluator, [], search_strategy)\nexp_config = RetiariiExeConfig('local')\nexp_config.experiment_name = 'mnist_search'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following configurations are useful to control how many trials to run at most / at the same time.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "exp_config.max_trial_number = 4 # spawn 4 trials at most\nexp_config.trial_concurrency = 2 # will run two trials concurrently" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Remember to set the following config if you want to GPU.\n``use_active_gpu`` should be set true if you wish to use an occupied GPU (possibly running a GUI).\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "exp_config.trial_gpu_number = 1\nexp_config.training_service.use_active_gpu = True" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Launch the experiment. The experiment should take several minutes to finish on a workstation with 2 GPUs.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "exp.run(exp_config, 8081)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Users can also run Retiarii Experiment with :doc:`different training services `\nbesides ``local`` training service.\n\n## Visualize the Experiment\n\nUsers can visualize their experiment in the same way as visualizing a normal hyper-parameter tuning experiment.\nFor example, open ``localhost:8081`` in your browser, 8081 is the port that you set in ``exp.run``.\nPlease refer to :doc:`here ` for details.\n\nWe support visualizing models with 3rd-party visualization engines (like `Netron `__).\nThis can be used by clicking ``Visualization`` in detail panel for each trial.\nNote that current visualization is based on `onnx `__ ,\nthus visualization is not feasible if the model cannot be exported into onnx.\n\nBuilt-in evaluators (e.g., Classification) will automatically export the model into a file.\nFor your own evaluator, you need to save your file into ``$NNI_OUTPUT_DIR/model.onnx`` to make this work.\nFor instance,\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import os\nfrom pathlib import Path\n\n\ndef evaluate_model_with_visualization(model_cls):\n model = model_cls()\n # dump the model into an onnx\n if 'NNI_OUTPUT_DIR' in os.environ:\n dummy_input = torch.zeros(1, 3, 32, 32)\n torch.onnx.export(model, (dummy_input, ),\n Path(os.environ['NNI_OUTPUT_DIR']) / 'model.onnx')\n evaluate_model(model_cls)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Relaunch the experiment, and a button is shown on Web portal.\n\n\n\n## Export Top Models\n\nUsers can export top models after the exploration is done using ``export_top_models``.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "for model_dict in exp.export_top_models(formatter='dict'):\n print(model_dict)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The output is ``json`` object which records the mutation actions of the top model.\nIf users want to output source code of the top model,\nthey can use `graph-based execution engine ` for the experiment,\nby simply adding the following two lines.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "exp_config.execution_engine = 'base'\nexport_formatter = 'code'" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/docs/source/tutorials/hello_nas.py b/docs/source/tutorials/hello_nas.py new file mode 100644 index 0000000000000000000000000000000000000000..ca0b580aa82bf7f88e6af79b59d8167da3d82bf0 --- /dev/null +++ b/docs/source/tutorials/hello_nas.py @@ -0,0 +1,364 @@ +""" +Hello, NAS! +=========== + +This is the 101 tutorial of Neural Architecture Search (NAS) on NNI. +In this tutorial, we will search for a neural architecture on MNIST dataset with the help of NAS framework of NNI, i.e., *Retiarii*. +We use multi-trial NAS as an example to show how to construct and explore a model space. + +There are mainly three crucial components for a neural architecture search task, namely, + +* Model search space that defines a set of models to explore. +* A proper strategy as the method to explore this model space. +* A model evaluator that reports the performance of every model in the space. + +Currently, PyTorch is the only supported framework by Retiarii, and we have only tested **PyTorch 1.7 to 1.10**. +This tutorial assumes PyTorch context but it should also apply to other frameworks, which is in our future plan. + +Define your Model Space +----------------------- + +Model space is defined by users to express a set of models that users want to explore, which contains potentially good-performing models. +In this framework, a model space is defined with two parts: a base model and possible mutations on the base model. +""" + +# %% +# +# Define Base Model +# ^^^^^^^^^^^^^^^^^ +# +# Defining a base model is almost the same as defining a PyTorch (or TensorFlow) model. +# Usually, you only need to replace the code ``import torch.nn as nn`` with +# ``import nni.retiarii.nn.pytorch as nn`` to use our wrapped PyTorch modules. +# +# Below is a very simple example of defining a base model. + +import torch +import torch.nn.functional as F +import nni.retiarii.nn.pytorch as nn +from nni.retiarii import model_wrapper + + +@model_wrapper # this decorator should be put on the out most +class Net(nn.Module): + def __init__(self): + super().__init__() + self.conv1 = nn.Conv2d(1, 32, 3, 1) + self.conv2 = nn.Conv2d(32, 64, 3, 1) + self.dropout1 = nn.Dropout(0.25) + self.dropout2 = nn.Dropout(0.5) + self.fc1 = nn.Linear(9216, 128) + self.fc2 = nn.Linear(128, 10) + + def forward(self, x): + x = F.relu(self.conv1(x)) + x = F.max_pool2d(self.conv2(x), 2) + x = torch.flatten(self.dropout1(x), 1) + x = self.fc2(self.dropout2(F.relu(self.fc1(x)))) + output = F.log_softmax(x, dim=1) + return output + +# %% +# .. tip:: Always keep in mind that you should use ``import nni.retiarii.nn.pytorch as nn`` and :meth:`nni.retiarii.model_wrapper`. +# Many mistakes are a result of forgetting one of those. +# Also, please use ``torch.nn`` for submodules of ``nn.init``, e.g., ``torch.nn.init`` instead of ``nn.init``. +# +# Define Model Mutations +# ^^^^^^^^^^^^^^^^^^^^^^ +# +# A base model is only one concrete model not a model space. We provide :doc:`API and Primitives
` +# for users to express how the base model can be mutated. That is, to build a model space which includes many models. +# +# Based on the above base model, we can define a model space as below. +# +# .. code-block:: diff +# +# @model_wrapper +# class Net(nn.Module): +# def __init__(self): +# super().__init__() +# self.conv1 = nn.Conv2d(1, 32, 3, 1) +# - self.conv2 = nn.Conv2d(32, 64, 3, 1) +# + self.conv2 = nn.LayerChoice([ +# + nn.Conv2d(32, 64, 3, 1), +# + DepthwiseSeparableConv(32, 64) +# + ]) +# - self.dropout1 = nn.Dropout(0.25) +# + self.dropout1 = nn.Dropout(nn.ValueChoice([0.25, 0.5, 0.75])) +# self.dropout2 = nn.Dropout(0.5) +# - self.fc1 = nn.Linear(9216, 128) +# - self.fc2 = nn.Linear(128, 10) +# + feature = nn.ValueChoice([64, 128, 256]) +# + self.fc1 = nn.Linear(9216, feature) +# + self.fc2 = nn.Linear(feature, 10) +# +# def forward(self, x): +# x = F.relu(self.conv1(x)) +# x = F.max_pool2d(self.conv2(x), 2) +# x = torch.flatten(self.dropout1(x), 1) +# x = self.fc2(self.dropout2(F.relu(self.fc1(x)))) +# output = F.log_softmax(x, dim=1) +# return output +# +# This results in the following code: + + +class DepthwiseSeparableConv(nn.Module): + def __init__(self, in_ch, out_ch): + super().__init__() + self.depthwise = nn.Conv2d(in_ch, in_ch, kernel_size=3, groups=in_ch) + self.pointwise = nn.Conv2d(in_ch, out_ch, kernel_size=1) + + def forward(self, x): + return self.pointwise(self.depthwise(x)) + + +@model_wrapper +class ModelSpace(nn.Module): + def __init__(self): + super().__init__() + self.conv1 = nn.Conv2d(1, 32, 3, 1) + # LayerChoice is used to select a layer between Conv2d and DwConv. + self.conv2 = nn.LayerChoice([ + nn.Conv2d(32, 64, 3, 1), + DepthwiseSeparableConv(32, 64) + ]) + # ValueChoice is used to select a dropout rate. + # ValueChoice can be used as parameter of modules wrapped in `nni.retiarii.nn.pytorch` + # or customized modules wrapped with `@basic_unit`. + self.dropout1 = nn.Dropout(nn.ValueChoice([0.25, 0.5, 0.75])) # choose dropout rate from 0.25, 0.5 and 0.75 + self.dropout2 = nn.Dropout(0.5) + feature = nn.ValueChoice([64, 128, 256]) + self.fc1 = nn.Linear(9216, feature) + self.fc2 = nn.Linear(feature, 10) + + def forward(self, x): + x = F.relu(self.conv1(x)) + x = F.max_pool2d(self.conv2(x), 2) + x = torch.flatten(self.dropout1(x), 1) + x = self.fc2(self.dropout2(F.relu(self.fc1(x)))) + output = F.log_softmax(x, dim=1) + return output + + +model_space = ModelSpace() +model_space + +# %% +# This example uses two mutation APIs, +# :class:`nn.LayerChoice ` and +# :class:`nn.InputChoice `. +# :class:`nn.LayerChoice ` +# takes a list of candidate modules (two in this example), one will be chosen for each sampled model. +# It can be used like normal PyTorch module. +# :class:`nn.InputChoice ` takes a list of candidate values, +# one will be chosen to take effect for each sampled model. +# +# More detailed API description and usage can be found :doc:`here
`. +# +# .. note:: +# +# We are actively enriching the mutation APIs, to facilitate easy construction of model space. +# If the currently supported mutation APIs cannot express your model space, +# please refer to :doc:`this doc
` for customizing mutators. +# +# Explore the Defined Model Space +# ------------------------------- +# +# There are basically two exploration approaches: (1) search by evaluating each sampled model independently, +# which is the search approach in :ref:`multi-trial NAS ` +# and (2) one-shot weight-sharing based search, which is used in one-shot NAS. +# We demonstrate the first approach in this tutorial. Users can refer to :ref:`here ` for the second approach. +# +# First, users need to pick a proper exploration strategy to explore the defined model space. +# Second, users need to pick or customize a model evaluator to evaluate the performance of each explored model. +# +# Pick an exploration strategy +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# +# Retiarii supports many :doc:`exploration strategies
`. +# +# Simply choosing (i.e., instantiate) an exploration strategy as below. + +import nni.retiarii.strategy as strategy +search_strategy = strategy.Random(dedup=True) # dedup=False if deduplication is not wanted + +# %% +# Pick or customize a model evaluator +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# +# In the exploration process, the exploration strategy repeatedly generates new models. A model evaluator is for training +# and validating each generated model to obtain the model's performance. +# The performance is sent to the exploration strategy for the strategy to generate better models. +# +# Retiarii has provided :doc:`built-in model evaluators
`, but to start with, +# it is recommended to use :class:`FunctionalEvaluator `, +# that is, to wrap your own training and evaluation code with one single function. +# This function should receive one single model class and uses :func:`nni.report_final_result` to report the final score of this model. +# +# An example here creates a simple evaluator that runs on MNIST dataset, trains for 2 epochs, and reports its validation accuracy. + +import nni + +from torchvision import transforms +from torchvision.datasets import MNIST +from torch.utils.data import DataLoader + + +def train_epoch(model, device, train_loader, optimizer, epoch): + loss_fn = torch.nn.CrossEntropyLoss() + model.train() + for batch_idx, (data, target) in enumerate(train_loader): + data, target = data.to(device), target.to(device) + optimizer.zero_grad() + output = model(data) + loss = loss_fn(output, target) + loss.backward() + optimizer.step() + if batch_idx % 10 == 0: + print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format( + epoch, batch_idx * len(data), len(train_loader.dataset), + 100. * batch_idx / len(train_loader), loss.item())) + + +def test_epoch(model, device, test_loader): + model.eval() + test_loss = 0 + correct = 0 + with torch.no_grad(): + for data, target in test_loader: + data, target = data.to(device), target.to(device) + output = model(data) + pred = output.argmax(dim=1, keepdim=True) + correct += pred.eq(target.view_as(pred)).sum().item() + + test_loss /= len(test_loader.dataset) + accuracy = 100. * correct / len(test_loader.dataset) + + print('\nTest set: Accuracy: {}/{} ({:.0f}%)\n'.format( + correct, len(test_loader.dataset), accuracy)) + + return accuracy + + +def evaluate_model(model_cls): + # "model_cls" is a class, need to instantiate + model = model_cls() + + device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu') + model.to(device) + + optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) + transf = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))]) + train_loader = DataLoader(MNIST('data/mnist', download=True, transform=transf), batch_size=64, shuffle=True) + test_loader = DataLoader(MNIST('data/mnist', download=True, train=False, transform=transf), batch_size=64) + + for epoch in range(3): + # train the model for one epoch + train_epoch(model, device, train_loader, optimizer, epoch) + # test the model for one epoch + accuracy = test_epoch(model, device, test_loader) + # call report intermediate result. Result can be float or dict + nni.report_intermediate_result(accuracy) + + # report final test result + nni.report_final_result(accuracy) + + +# %% +# Create the evaluator + +from nni.retiarii.evaluator import FunctionalEvaluator +evaluator = FunctionalEvaluator(evaluate_model) + +# %% +# +# The ``train_epoch`` and ``test_epoch`` here can be any customized function, +# where users can write their own training recipe. +# +# It is recommended that the ``evaluate_model`` here accepts no additional arguments other than ``model_cls``. +# However, in the :doc:`advanced tutorial
`, we will show how to use additional arguments in case you actually need those. +# In future, we will support mutation on the arguments of evaluators, which is commonly called "Hyper-parmeter tuning". +# +# Launch an Experiment +# -------------------- +# +# After all the above are prepared, it is time to start an experiment to do the model search. An example is shown below. + +from nni.retiarii.experiment.pytorch import RetiariiExperiment, RetiariiExeConfig +exp = RetiariiExperiment(model_space, evaluator, [], search_strategy) +exp_config = RetiariiExeConfig('local') +exp_config.experiment_name = 'mnist_search' + +# %% +# The following configurations are useful to control how many trials to run at most / at the same time. + +exp_config.max_trial_number = 4 # spawn 4 trials at most +exp_config.trial_concurrency = 2 # will run two trials concurrently + +# %% +# Remember to set the following config if you want to GPU. +# ``use_active_gpu`` should be set true if you wish to use an occupied GPU (possibly running a GUI). + +exp_config.trial_gpu_number = 1 +exp_config.training_service.use_active_gpu = True + +# %% +# Launch the experiment. The experiment should take several minutes to finish on a workstation with 2 GPUs. + +exp.run(exp_config, 8081) + +# %% +# Users can also run Retiarii Experiment with :doc:`different training services ` +# besides ``local`` training service. +# +# Visualize the Experiment +# ------------------------ +# +# Users can visualize their experiment in the same way as visualizing a normal hyper-parameter tuning experiment. +# For example, open ``localhost:8081`` in your browser, 8081 is the port that you set in ``exp.run``. +# Please refer to :doc:`here ` for details. +# +# We support visualizing models with 3rd-party visualization engines (like `Netron `__). +# This can be used by clicking ``Visualization`` in detail panel for each trial. +# Note that current visualization is based on `onnx `__ , +# thus visualization is not feasible if the model cannot be exported into onnx. +# +# Built-in evaluators (e.g., Classification) will automatically export the model into a file. +# For your own evaluator, you need to save your file into ``$NNI_OUTPUT_DIR/model.onnx`` to make this work. +# For instance, + +import os +from pathlib import Path + + +def evaluate_model_with_visualization(model_cls): + model = model_cls() + # dump the model into an onnx + if 'NNI_OUTPUT_DIR' in os.environ: + dummy_input = torch.zeros(1, 3, 32, 32) + torch.onnx.export(model, (dummy_input, ), + Path(os.environ['NNI_OUTPUT_DIR']) / 'model.onnx') + evaluate_model(model_cls) + +# %% +# Relaunch the experiment, and a button is shown on Web portal. +# +# .. image:: ../../img/netron_entrance_webui.png +# +# Export Top Models +# ----------------- +# +# Users can export top models after the exploration is done using ``export_top_models``. + +for model_dict in exp.export_top_models(formatter='dict'): + print(model_dict) + +# %% +# The output is ``json`` object which records the mutation actions of the top model. +# If users want to output source code of the top model, +# they can use :ref:`graph-based execution engine ` for the experiment, +# by simply adding the following two lines. + +exp_config.execution_engine = 'base' +export_formatter = 'code' diff --git a/docs/source/tutorials/hello_nas.py.md5 b/docs/source/tutorials/hello_nas.py.md5 new file mode 100644 index 0000000000000000000000000000000000000000..7612888d2b874d677776cbff1ea86f60d9ea805e --- /dev/null +++ b/docs/source/tutorials/hello_nas.py.md5 @@ -0,0 +1 @@ +0e49e3aef98633744807b814786f6b31 \ No newline at end of file diff --git a/docs/source/tutorials/hello_nas.rst b/docs/source/tutorials/hello_nas.rst new file mode 100644 index 0000000000000000000000000000000000000000..fd0e9590c9c7df9851d60a7576dbd91b1e739932 --- /dev/null +++ b/docs/source/tutorials/hello_nas.rst @@ -0,0 +1,625 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "tutorials/hello_nas.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_tutorials_hello_nas.py: + + +Hello, NAS! +=========== + +This is the 101 tutorial of Neural Architecture Search (NAS) on NNI. +In this tutorial, we will search for a neural architecture on MNIST dataset with the help of NAS framework of NNI, i.e., *Retiarii*. +We use multi-trial NAS as an example to show how to construct and explore a model space. + +There are mainly three crucial components for a neural architecture search task, namely, + +* Model search space that defines a set of models to explore. +* A proper strategy as the method to explore this model space. +* A model evaluator that reports the performance of every model in the space. + +Currently, PyTorch is the only supported framework by Retiarii, and we have only tested **PyTorch 1.7 to 1.10**. +This tutorial assumes PyTorch context but it should also apply to other frameworks, which is in our future plan. + +Define your Model Space +----------------------- + +Model space is defined by users to express a set of models that users want to explore, which contains potentially good-performing models. +In this framework, a model space is defined with two parts: a base model and possible mutations on the base model. + +.. GENERATED FROM PYTHON SOURCE LINES 26-34 + +Define Base Model +^^^^^^^^^^^^^^^^^ + +Defining a base model is almost the same as defining a PyTorch (or TensorFlow) model. +Usually, you only need to replace the code ``import torch.nn as nn`` with +``import nni.retiarii.nn.pytorch as nn`` to use our wrapped PyTorch modules. + +Below is a very simple example of defining a base model. + +.. GENERATED FROM PYTHON SOURCE LINES 35-61 + +.. code-block:: default + + + import torch + import torch.nn.functional as F + import nni.retiarii.nn.pytorch as nn + from nni.retiarii import model_wrapper + + + @model_wrapper # this decorator should be put on the out most + class Net(nn.Module): + def __init__(self): + super().__init__() + self.conv1 = nn.Conv2d(1, 32, 3, 1) + self.conv2 = nn.Conv2d(32, 64, 3, 1) + self.dropout1 = nn.Dropout(0.25) + self.dropout2 = nn.Dropout(0.5) + self.fc1 = nn.Linear(9216, 128) + self.fc2 = nn.Linear(128, 10) + + def forward(self, x): + x = F.relu(self.conv1(x)) + x = F.max_pool2d(self.conv2(x), 2) + x = torch.flatten(self.dropout1(x), 1) + x = self.fc2(self.dropout2(F.relu(self.fc1(x)))) + output = F.log_softmax(x, dim=1) + return output + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 62-104 + +.. tip:: Always keep in mind that you should use ``import nni.retiarii.nn.pytorch as nn`` and :meth:`nni.retiarii.model_wrapper`. + Many mistakes are a result of forgetting one of those. + Also, please use ``torch.nn`` for submodules of ``nn.init``, e.g., ``torch.nn.init`` instead of ``nn.init``. + +Define Model Mutations +^^^^^^^^^^^^^^^^^^^^^^ + +A base model is only one concrete model not a model space. We provide :doc:`API and Primitives
` +for users to express how the base model can be mutated. That is, to build a model space which includes many models. + +Based on the above base model, we can define a model space as below. + +.. code-block:: diff + + @model_wrapper + class Net(nn.Module): + def __init__(self): + super().__init__() + self.conv1 = nn.Conv2d(1, 32, 3, 1) + - self.conv2 = nn.Conv2d(32, 64, 3, 1) + + self.conv2 = nn.LayerChoice([ + + nn.Conv2d(32, 64, 3, 1), + + DepthwiseSeparableConv(32, 64) + + ]) + - self.dropout1 = nn.Dropout(0.25) + + self.dropout1 = nn.Dropout(nn.ValueChoice([0.25, 0.5, 0.75])) + self.dropout2 = nn.Dropout(0.5) + - self.fc1 = nn.Linear(9216, 128) + - self.fc2 = nn.Linear(128, 10) + + feature = nn.ValueChoice([64, 128, 256]) + + self.fc1 = nn.Linear(9216, feature) + + self.fc2 = nn.Linear(feature, 10) + + def forward(self, x): + x = F.relu(self.conv1(x)) + x = F.max_pool2d(self.conv2(x), 2) + x = torch.flatten(self.dropout1(x), 1) + x = self.fc2(self.dropout2(F.relu(self.fc1(x)))) + output = F.log_softmax(x, dim=1) + return output + +This results in the following code: + +.. GENERATED FROM PYTHON SOURCE LINES 104-147 + +.. code-block:: default + + + + class DepthwiseSeparableConv(nn.Module): + def __init__(self, in_ch, out_ch): + super().__init__() + self.depthwise = nn.Conv2d(in_ch, in_ch, kernel_size=3, groups=in_ch) + self.pointwise = nn.Conv2d(in_ch, out_ch, kernel_size=1) + + def forward(self, x): + return self.pointwise(self.depthwise(x)) + + + @model_wrapper + class ModelSpace(nn.Module): + def __init__(self): + super().__init__() + self.conv1 = nn.Conv2d(1, 32, 3, 1) + # LayerChoice is used to select a layer between Conv2d and DwConv. + self.conv2 = nn.LayerChoice([ + nn.Conv2d(32, 64, 3, 1), + DepthwiseSeparableConv(32, 64) + ]) + # ValueChoice is used to select a dropout rate. + # ValueChoice can be used as parameter of modules wrapped in `nni.retiarii.nn.pytorch` + # or customized modules wrapped with `@basic_unit`. + self.dropout1 = nn.Dropout(nn.ValueChoice([0.25, 0.5, 0.75])) # choose dropout rate from 0.25, 0.5 and 0.75 + self.dropout2 = nn.Dropout(0.5) + feature = nn.ValueChoice([64, 128, 256]) + self.fc1 = nn.Linear(9216, feature) + self.fc2 = nn.Linear(feature, 10) + + def forward(self, x): + x = F.relu(self.conv1(x)) + x = F.max_pool2d(self.conv2(x), 2) + x = torch.flatten(self.dropout1(x), 1) + x = self.fc2(self.dropout2(F.relu(self.fc1(x)))) + output = F.log_softmax(x, dim=1) + return output + + + model_space = ModelSpace() + model_space + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + + ModelSpace( + (conv1): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1)) + (conv2): LayerChoice([Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1)), DepthwiseSeparableConv( + (depthwise): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), groups=32) + (pointwise): Conv2d(32, 64, kernel_size=(1, 1), stride=(1, 1)) + )], label='model_1') + (dropout1): Dropout(p=0.25, inplace=False) + (dropout2): Dropout(p=0.5, inplace=False) + (fc1): Linear(in_features=9216, out_features=64, bias=True) + (fc2): Linear(in_features=64, out_features=10, bias=True) + ) + + + +.. GENERATED FROM PYTHON SOURCE LINES 148-182 + +This example uses two mutation APIs, +:class:`nn.LayerChoice ` and +:class:`nn.InputChoice `. +:class:`nn.LayerChoice ` +takes a list of candidate modules (two in this example), one will be chosen for each sampled model. +It can be used like normal PyTorch module. +:class:`nn.InputChoice ` takes a list of candidate values, +one will be chosen to take effect for each sampled model. + +More detailed API description and usage can be found :doc:`here
`. + +.. note:: + + We are actively enriching the mutation APIs, to facilitate easy construction of model space. + If the currently supported mutation APIs cannot express your model space, + please refer to :doc:`this doc ` for customizing mutators. + +Explore the Defined Model Space +------------------------------- + +There are basically two exploration approaches: (1) search by evaluating each sampled model independently, +which is the search approach in :ref:`multi-trial NAS ` +and (2) one-shot weight-sharing based search, which is used in one-shot NAS. +We demonstrate the first approach in this tutorial. Users can refer to :ref:`here ` for the second approach. + +First, users need to pick a proper exploration strategy to explore the defined model space. +Second, users need to pick or customize a model evaluator to evaluate the performance of each explored model. + +Pick an exploration strategy +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Retiarii supports many :doc:`exploration strategies `. + +Simply choosing (i.e., instantiate) an exploration strategy as below. + +.. GENERATED FROM PYTHON SOURCE LINES 182-186 + +.. code-block:: default + + + import nni.retiarii.strategy as strategy + search_strategy = strategy.Random(dedup=True) # dedup=False if deduplication is not wanted + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + + /home/yugzhan/miniconda3/envs/cu102/lib/python3.8/site-packages/ray/autoscaler/_private/cli_logger.py:57: FutureWarning: Not all Ray CLI dependencies were found. In Ray 1.4+, the Ray CLI, autoscaler, and dashboard will only be usable via `pip install 'ray[default]'`. Please update your install command. + warnings.warn( + + + + +.. GENERATED FROM PYTHON SOURCE LINES 187-200 + +Pick or customize a model evaluator +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In the exploration process, the exploration strategy repeatedly generates new models. A model evaluator is for training +and validating each generated model to obtain the model's performance. +The performance is sent to the exploration strategy for the strategy to generate better models. + +Retiarii has provided :doc:`built-in model evaluators `, but to start with, +it is recommended to use :class:`FunctionalEvaluator `, +that is, to wrap your own training and evaluation code with one single function. +This function should receive one single model class and uses :func:`nni.report_final_result` to report the final score of this model. + +An example here creates a simple evaluator that runs on MNIST dataset, trains for 2 epochs, and reports its validation accuracy. + +.. GENERATED FROM PYTHON SOURCE LINES 200-268 + +.. code-block:: default + + + import nni + + from torchvision import transforms + from torchvision.datasets import MNIST + from torch.utils.data import DataLoader + + + def train_epoch(model, device, train_loader, optimizer, epoch): + loss_fn = torch.nn.CrossEntropyLoss() + model.train() + for batch_idx, (data, target) in enumerate(train_loader): + data, target = data.to(device), target.to(device) + optimizer.zero_grad() + output = model(data) + loss = loss_fn(output, target) + loss.backward() + optimizer.step() + if batch_idx % 10 == 0: + print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format( + epoch, batch_idx * len(data), len(train_loader.dataset), + 100. * batch_idx / len(train_loader), loss.item())) + + + def test_epoch(model, device, test_loader): + model.eval() + test_loss = 0 + correct = 0 + with torch.no_grad(): + for data, target in test_loader: + data, target = data.to(device), target.to(device) + output = model(data) + pred = output.argmax(dim=1, keepdim=True) + correct += pred.eq(target.view_as(pred)).sum().item() + + test_loss /= len(test_loader.dataset) + accuracy = 100. * correct / len(test_loader.dataset) + + print('\nTest set: Accuracy: {}/{} ({:.0f}%)\n'.format( + correct, len(test_loader.dataset), accuracy)) + + return accuracy + + + def evaluate_model(model_cls): + # "model_cls" is a class, need to instantiate + model = model_cls() + + device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu') + model.to(device) + + optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) + transf = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))]) + train_loader = DataLoader(MNIST('data/mnist', download=True, transform=transf), batch_size=64, shuffle=True) + test_loader = DataLoader(MNIST('data/mnist', download=True, train=False, transform=transf), batch_size=64) + + for epoch in range(3): + # train the model for one epoch + train_epoch(model, device, train_loader, optimizer, epoch) + # test the model for one epoch + accuracy = test_epoch(model, device, test_loader) + # call report intermediate result. Result can be float or dict + nni.report_intermediate_result(accuracy) + + # report final test result + nni.report_final_result(accuracy) + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 269-270 + +Create the evaluator + +.. GENERATED FROM PYTHON SOURCE LINES 270-274 + +.. code-block:: default + + + from nni.retiarii.evaluator import FunctionalEvaluator + evaluator = FunctionalEvaluator(evaluate_model) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 275-286 + +The ``train_epoch`` and ``test_epoch`` here can be any customized function, +where users can write their own training recipe. + +It is recommended that the ``evaluate_model`` here accepts no additional arguments other than ``model_cls``. +However, in the :doc:`advanced tutorial `, we will show how to use additional arguments in case you actually need those. +In future, we will support mutation on the arguments of evaluators, which is commonly called "Hyper-parmeter tuning". + +Launch an Experiment +-------------------- + +After all the above are prepared, it is time to start an experiment to do the model search. An example is shown below. + +.. GENERATED FROM PYTHON SOURCE LINES 287-293 + +.. code-block:: default + + + from nni.retiarii.experiment.pytorch import RetiariiExperiment, RetiariiExeConfig + exp = RetiariiExperiment(model_space, evaluator, [], search_strategy) + exp_config = RetiariiExeConfig('local') + exp_config.experiment_name = 'mnist_search' + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 294-295 + +The following configurations are useful to control how many trials to run at most / at the same time. + +.. GENERATED FROM PYTHON SOURCE LINES 295-299 + +.. code-block:: default + + + exp_config.max_trial_number = 4 # spawn 4 trials at most + exp_config.trial_concurrency = 2 # will run two trials concurrently + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 300-302 + +Remember to set the following config if you want to GPU. +``use_active_gpu`` should be set true if you wish to use an occupied GPU (possibly running a GUI). + +.. GENERATED FROM PYTHON SOURCE LINES 302-306 + +.. code-block:: default + + + exp_config.trial_gpu_number = 1 + exp_config.training_service.use_active_gpu = True + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 307-308 + +Launch the experiment. The experiment should take several minutes to finish on a workstation with 2 GPUs. + +.. GENERATED FROM PYTHON SOURCE LINES 308-311 + +.. code-block:: default + + + exp.run(exp_config, 8081) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + INFO:nni.experiment:Creating experiment, Experiment ID: z8ns5fv7 + INFO:nni.experiment:Connecting IPC pipe... + INFO:nni.experiment:Starting web server... + INFO:nni.experiment:Setting up... + INFO:nni.runtime.msg_dispatcher_base:Dispatcher started + INFO:nni.retiarii.experiment.pytorch:Web UI URLs: http://127.0.0.1:8081 http://10.190.172.35:8081 http://192.168.49.1:8081 http://172.17.0.1:8081 + INFO:nni.retiarii.experiment.pytorch:Start strategy... + INFO:root:Successfully update searchSpace. + INFO:nni.retiarii.strategy.bruteforce:Random search running in fixed size mode. Dedup: on. + INFO:nni.retiarii.experiment.pytorch:Stopping experiment, please wait... + INFO:nni.retiarii.experiment.pytorch:Strategy exit + INFO:nni.retiarii.experiment.pytorch:Waiting for experiment to become DONE (you can ctrl+c if there is no running trial jobs)... + INFO:nni.runtime.msg_dispatcher_base:Dispatcher exiting... + INFO:nni.retiarii.experiment.pytorch:Experiment stopped + + + + +.. GENERATED FROM PYTHON SOURCE LINES 312-330 + +Users can also run Retiarii Experiment with :doc:`different training services ` +besides ``local`` training service. + +Visualize the Experiment +------------------------ + +Users can visualize their experiment in the same way as visualizing a normal hyper-parameter tuning experiment. +For example, open ``localhost:8081`` in your browser, 8081 is the port that you set in ``exp.run``. +Please refer to :doc:`here ` for details. + +We support visualizing models with 3rd-party visualization engines (like `Netron `__). +This can be used by clicking ``Visualization`` in detail panel for each trial. +Note that current visualization is based on `onnx `__ , +thus visualization is not feasible if the model cannot be exported into onnx. + +Built-in evaluators (e.g., Classification) will automatically export the model into a file. +For your own evaluator, you need to save your file into ``$NNI_OUTPUT_DIR/model.onnx`` to make this work. +For instance, + +.. GENERATED FROM PYTHON SOURCE LINES 330-344 + +.. code-block:: default + + + import os + from pathlib import Path + + + def evaluate_model_with_visualization(model_cls): + model = model_cls() + # dump the model into an onnx + if 'NNI_OUTPUT_DIR' in os.environ: + dummy_input = torch.zeros(1, 3, 32, 32) + torch.onnx.export(model, (dummy_input, ), + Path(os.environ['NNI_OUTPUT_DIR']) / 'model.onnx') + evaluate_model(model_cls) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 345-353 + +Relaunch the experiment, and a button is shown on Web portal. + +.. image:: ../../img/netron_entrance_webui.png + +Export Top Models +----------------- + +Users can export top models after the exploration is done using ``export_top_models``. + +.. GENERATED FROM PYTHON SOURCE LINES 353-357 + +.. code-block:: default + + + for model_dict in exp.export_top_models(formatter='dict'): + print(model_dict) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + {'model_1': '0', 'model_2': 0.25, 'model_3': 64} + + + + +.. GENERATED FROM PYTHON SOURCE LINES 358-362 + +The output is ``json`` object which records the mutation actions of the top model. +If users want to output source code of the top model, +they can use :ref:`graph-based execution engine ` for the experiment, +by simply adding the following two lines. + +.. GENERATED FROM PYTHON SOURCE LINES 362-365 + +.. code-block:: default + + + exp_config.execution_engine = 'base' + export_formatter = 'code' + + + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 2 minutes 4.499 seconds) + + +.. _sphx_glr_download_tutorials_hello_nas.py: + + +.. only :: html + + .. container:: sphx-glr-footer + :class: sphx-glr-footer-example + + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: hello_nas.py ` + + + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: hello_nas.ipynb ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/hello_nas_codeobj.pickle b/docs/source/tutorials/hello_nas_codeobj.pickle new file mode 100644 index 0000000000000000000000000000000000000000..a25313e349ff2eeeaefe272e41c5bf8f31615b64 Binary files /dev/null and b/docs/source/tutorials/hello_nas_codeobj.pickle differ diff --git a/docs/source/tutorials/hello_nas_zh.rst b/docs/source/tutorials/hello_nas_zh.rst new file mode 100644 index 0000000000000000000000000000000000000000..aa325fddf19066ee5d60b3ce714145930240fc90 --- /dev/null +++ b/docs/source/tutorials/hello_nas_zh.rst @@ -0,0 +1,617 @@ +.. 8a873f2c9cb0e8e3ed2d66b9d16c330f + + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "tutorials/hello_nas.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_tutorials_hello_nas.py: + + +架构搜索入门教程 +================ + +这是 NNI 上的神经架构搜索(NAS)的入门教程。 +在本教程中,我们将借助 NNI 的 NAS 框架,即 *Retiarii*,在 MNIST 数据集上实现网络结构搜索。 +我们以多尝试的架构搜索为例来展示如何构建和探索模型空间。 + +神经架构搜索任务主要有三个关键组成部分,即 + +* 模型搜索空间,定义了一个要探索的模型的集合。 +* 一个合适的策略作为探索这个模型空间的方法。 +* 一个模型评估器,用于为搜索空间中每个模型评估性能。 + +目前,Retiarii 只支持 PyTorch,并对 **PyTorch 1.7 到 1.10** 进行了测试。 +所以本教程假定您使用 PyTorch 作为深度学习框架。未来我们会支持更多框架。 + +定义您的模型空间 +---------------------- + +模型空间是由用户定义的,用来表达用户想要探索的一组模型,其中包含有潜力的好模型。 +在 NNI 的框架中,模型空间由两部分定义:基本模型和基本模型上可能的变化。 + +.. GENERATED FROM PYTHON SOURCE LINES 26-34 + +定义基本模型 +^^^^^^^^^^^^^^^^^ + +定义基本模型与定义 PyTorch(或 TensorFlow)模型几乎相同。 +通常,您只需将代码 ``import torch.nn as nn`` 替换为 +``import nni.retiarii.nn.pytorch as nn`` 以使用我们打包的 PyTorch 模块。 + +下面是定义基本模型的一个非常简单的示例。 + +.. GENERATED FROM PYTHON SOURCE LINES 35-61 + +.. code-block:: default + + + import torch + import torch.nn.functional as F + import nni.retiarii.nn.pytorch as nn + from nni.retiarii import model_wrapper + + + @model_wrapper # this decorator should be put on the out most + class Net(nn.Module): + def __init__(self): + super().__init__() + self.conv1 = nn.Conv2d(1, 32, 3, 1) + self.conv2 = nn.Conv2d(32, 64, 3, 1) + self.dropout1 = nn.Dropout(0.25) + self.dropout2 = nn.Dropout(0.5) + self.fc1 = nn.Linear(9216, 128) + self.fc2 = nn.Linear(128, 10) + + def forward(self, x): + x = F.relu(self.conv1(x)) + x = F.max_pool2d(self.conv2(x), 2) + x = torch.flatten(self.dropout1(x), 1) + x = self.fc2(self.dropout2(F.relu(self.fc1(x)))) + output = F.log_softmax(x, dim=1) + return output + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 62-104 + +.. tip:: 记住,您应该使用 ``import nni.retiarii.nn.pytorch as nn`` 和 :meth:`nni.retiarii.model_wrapper`。 + 许多错误都是因为忘记使用某一个。 + 另外,要使用 ``nn.init`` 的子模块,可以使用 ``torch.nn``,例如, ``torch.nn.init`` 而不是 ``nn.init``。 + +定义模型变化 +^^^^^^^^^^^^^^^^^^^^^^ + +基本模型只是一个具体模型,而不是模型空间。 我们提供 :doc:`模型变化的 API ` +让用户表达如何改变基本模型。 即构建一个包含许多模型的搜索空间。 + +基于上述基本模型,我们可以定义如下模型空间。 + +.. code-block:: diff + + @model_wrapper + class Net(nn.Module): + def __init__(self): + super().__init__() + self.conv1 = nn.Conv2d(1, 32, 3, 1) + - self.conv2 = nn.Conv2d(32, 64, 3, 1) + + self.conv2 = nn.LayerChoice([ + + nn.Conv2d(32, 64, 3, 1), + + DepthwiseSeparableConv(32, 64) + + ]) + - self.dropout1 = nn.Dropout(0.25) + + self.dropout1 = nn.Dropout(nn.ValueChoice([0.25, 0.5, 0.75])) + self.dropout2 = nn.Dropout(0.5) + - self.fc1 = nn.Linear(9216, 128) + - self.fc2 = nn.Linear(128, 10) + + feature = nn.ValueChoice([64, 128, 256]) + + self.fc1 = nn.Linear(9216, feature) + + self.fc2 = nn.Linear(feature, 10) + + def forward(self, x): + x = F.relu(self.conv1(x)) + x = F.max_pool2d(self.conv2(x), 2) + x = torch.flatten(self.dropout1(x), 1) + x = self.fc2(self.dropout2(F.relu(self.fc1(x)))) + output = F.log_softmax(x, dim=1) + return output + +结果是以下代码: + +.. GENERATED FROM PYTHON SOURCE LINES 104-147 + +.. code-block:: default + + + + class DepthwiseSeparableConv(nn.Module): + def __init__(self, in_ch, out_ch): + super().__init__() + self.depthwise = nn.Conv2d(in_ch, in_ch, kernel_size=3, groups=in_ch) + self.pointwise = nn.Conv2d(in_ch, out_ch, kernel_size=1) + + def forward(self, x): + return self.pointwise(self.depthwise(x)) + + + @model_wrapper + class ModelSpace(nn.Module): + def __init__(self): + super().__init__() + self.conv1 = nn.Conv2d(1, 32, 3, 1) + # LayerChoice is used to select a layer between Conv2d and DwConv. + self.conv2 = nn.LayerChoice([ + nn.Conv2d(32, 64, 3, 1), + DepthwiseSeparableConv(32, 64) + ]) + # ValueChoice is used to select a dropout rate. + # ValueChoice can be used as parameter of modules wrapped in `nni.retiarii.nn.pytorch` + # or customized modules wrapped with `@basic_unit`. + self.dropout1 = nn.Dropout(nn.ValueChoice([0.25, 0.5, 0.75])) # choose dropout rate from 0.25, 0.5 and 0.75 + self.dropout2 = nn.Dropout(0.5) + feature = nn.ValueChoice([64, 128, 256]) + self.fc1 = nn.Linear(9216, feature) + self.fc2 = nn.Linear(feature, 10) + + def forward(self, x): + x = F.relu(self.conv1(x)) + x = F.max_pool2d(self.conv2(x), 2) + x = torch.flatten(self.dropout1(x), 1) + x = self.fc2(self.dropout2(F.relu(self.fc1(x)))) + output = F.log_softmax(x, dim=1) + return output + + + model_space = ModelSpace() + model_space + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + + ModelSpace( + (conv1): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1)) + (conv2): LayerChoice([Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1)), DepthwiseSeparableConv( + (depthwise): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), groups=32) + (pointwise): Conv2d(32, 64, kernel_size=(1, 1), stride=(1, 1)) + )], label='model_1') + (dropout1): Dropout(p=0.25, inplace=False) + (dropout2): Dropout(p=0.5, inplace=False) + (fc1): Linear(in_features=9216, out_features=64, bias=True) + (fc2): Linear(in_features=64, out_features=10, bias=True) + ) + + + +.. GENERATED FROM PYTHON SOURCE LINES 148-182 + +这个例子使用了两个模型变化的 API, :class:`nn.LayerChoice ` 和 :class:`nn.InputChoice `。 +:class:`nn.LayerChoice ` 可以从一系列的候选子模块中(在本例中为两个),为每个采样模型选择一个。 +它可以像原来的 PyTorch 子模块一样使用。 +:class:`nn.InputChoice ` 的参数是一个候选值列表,语义是为每个采样模型选择一个值。 + +更详细的 API 描述和用法可以在 :doc:`这里 ` 找到。 + +.. note:: + + 我们正在积极丰富模型变化的 API,使得您可以轻松构建模型空间。 + 如果当前支持的模型变化的 API 不能表达您的模型空间, + 请参考 :doc:`这篇文档 ` 来自定义突变。 + +探索定义的模型空间 +------------------------------------------- + +简单来讲,有两种探索方法: +(1) 独立评估每个采样到的模型,这是 :ref:`多尝试 NAS ` 中的搜索方法。 +(2) 单尝试共享权重型的搜索,简称单尝试 NAS。 +我们在本教程中演示了第一种方法。第二种方法用户可以参考 :ref:`这里 `。 + +首先,用户需要选择合适的探索策略来探索定义好的模型空间。 +其次,用户需要选择或自定义模型性能评估来评估每个探索模型的性能。 + +选择探索策略 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Retiarii 支持许多 :doc:`探索策略`。 + +只需选择(即实例化)探索策略,就如下面的代码演示的一样: + +.. GENERATED FROM PYTHON SOURCE LINES 182-186 + +.. code-block:: default + + + import nni.retiarii.strategy as strategy + search_strategy = strategy.Random(dedup=True) # dedup=False if deduplication is not wanted + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + + /home/yugzhan/miniconda3/envs/cu102/lib/python3.8/site-packages/ray/autoscaler/_private/cli_logger.py:57: FutureWarning: Not all Ray CLI dependencies were found. In Ray 1.4+, the Ray CLI, autoscaler, and dashboard will only be usable via `pip install 'ray[default]'`. Please update your install command. + warnings.warn( + + + + +.. GENERATED FROM PYTHON SOURCE LINES 187-200 + +挑选或自定义模型评估器 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +在探索过程中,探索策略反复生成新模型。模型评估器负责训练并验证每个生成的模型以获得模型的性能。 +该性能作为模型的得分被发送到探索策略以帮助其生成更好的模型。 + +Retiarii 提供了 :doc:`内置模型评估器 `,但在此之前, +我们建议使用 :class:`FunctionalEvaluator `,即用一个函数包装您自己的训练和评估代码。 +这个函数应该接收一个单一的模型类并使用 :func:`nni.report_final_result` 报告这个模型的最终分数。 + +此处的示例创建了一个简单的评估器,该评估器在 MNIST 数据集上运行,训练 2 个 epoch,并报告其在验证集上的准确率。 + +.. GENERATED FROM PYTHON SOURCE LINES 200-268 + +.. code-block:: default + + + import nni + + from torchvision import transforms + from torchvision.datasets import MNIST + from torch.utils.data import DataLoader + + + def train_epoch(model, device, train_loader, optimizer, epoch): + loss_fn = torch.nn.CrossEntropyLoss() + model.train() + for batch_idx, (data, target) in enumerate(train_loader): + data, target = data.to(device), target.to(device) + optimizer.zero_grad() + output = model(data) + loss = loss_fn(output, target) + loss.backward() + optimizer.step() + if batch_idx % 10 == 0: + print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format( + epoch, batch_idx * len(data), len(train_loader.dataset), + 100. * batch_idx / len(train_loader), loss.item())) + + + def test_epoch(model, device, test_loader): + model.eval() + test_loss = 0 + correct = 0 + with torch.no_grad(): + for data, target in test_loader: + data, target = data.to(device), target.to(device) + output = model(data) + pred = output.argmax(dim=1, keepdim=True) + correct += pred.eq(target.view_as(pred)).sum().item() + + test_loss /= len(test_loader.dataset) + accuracy = 100. * correct / len(test_loader.dataset) + + print('\nTest set: Accuracy: {}/{} ({:.0f}%)\n'.format( + correct, len(test_loader.dataset), accuracy)) + + return accuracy + + + def evaluate_model(model_cls): + # "model_cls" is a class, need to instantiate + model = model_cls() + + device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu') + model.to(device) + + optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) + transf = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))]) + train_loader = DataLoader(MNIST('data/mnist', download=True, transform=transf), batch_size=64, shuffle=True) + test_loader = DataLoader(MNIST('data/mnist', download=True, train=False, transform=transf), batch_size=64) + + for epoch in range(3): + # train the model for one epoch + train_epoch(model, device, train_loader, optimizer, epoch) + # test the model for one epoch + accuracy = test_epoch(model, device, test_loader) + # call report intermediate result. Result can be float or dict + nni.report_intermediate_result(accuracy) + + # report final test result + nni.report_final_result(accuracy) + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 269-270 + +创建评估器 + +.. GENERATED FROM PYTHON SOURCE LINES 270-274 + +.. code-block:: default + + + from nni.retiarii.evaluator import FunctionalEvaluator + evaluator = FunctionalEvaluator(evaluate_model) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 275-286 + +这里的 ``train_epoch`` 和 ``test_epoch`` 可以是任何自定义函数,用户可以在其中编写自己的训练逻辑。 + +建议这里的 ``evaluate_model`` 不接受除 ``model_cls`` 之外的其他参数。 +但是,在 `高级教程 ` 中,我们将展示如何使用其他参数,以免您确实需要这些参数。 +未来,我们将支持对评估器的参数进行变化(通常称为“超参数调优”)。 + +启动实验 +-------------------- + +一切都已准备就绪,现在就可以开始做模型搜索的实验了。如下所示。 + +.. GENERATED FROM PYTHON SOURCE LINES 287-293 + +.. code-block:: default + + + from nni.retiarii.experiment.pytorch import RetiariiExperiment, RetiariiExeConfig + exp = RetiariiExperiment(model_space, evaluator, [], search_strategy) + exp_config = RetiariiExeConfig('local') + exp_config.experiment_name = 'mnist_search' + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 294-295 + +以下配置可以用于控制最多/同时运行多少试验。 + +.. GENERATED FROM PYTHON SOURCE LINES 295-299 + +.. code-block:: default + + + exp_config.max_trial_number = 4 # 最多运行 4 个实验 + exp_config.trial_concurrency = 2 # 最多同时运行 2 个试验 + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 300-302 + +如果要使用 GPU,请设置以下配置。 +如果您希望使用被占用了的 GPU(比如 GPU 上可能正在运行 GUI),则 ``use_active_gpu`` 应设置为 true。 + +.. GENERATED FROM PYTHON SOURCE LINES 302-306 + +.. code-block:: default + + + exp_config.trial_gpu_number = 1 + exp_config.training_service.use_active_gpu = True + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 307-308 + +启动实验。 在一个有两块 GPU 的工作站上完成整个实验大约需要几分钟时间。 + +.. GENERATED FROM PYTHON SOURCE LINES 308-311 + +.. code-block:: default + + + exp.run(exp_config, 8081) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + INFO:nni.experiment:Creating experiment, Experiment ID: z8ns5fv7 + INFO:nni.experiment:Connecting IPC pipe... + INFO:nni.experiment:Starting web server... + INFO:nni.experiment:Setting up... + INFO:nni.runtime.msg_dispatcher_base:Dispatcher started + INFO:nni.retiarii.experiment.pytorch:Web UI URLs: http://127.0.0.1:8081 http://10.190.172.35:8081 http://192.168.49.1:8081 http://172.17.0.1:8081 + INFO:nni.retiarii.experiment.pytorch:Start strategy... + INFO:root:Successfully update searchSpace. + INFO:nni.retiarii.strategy.bruteforce:Random search running in fixed size mode. Dedup: on. + INFO:nni.retiarii.experiment.pytorch:Stopping experiment, please wait... + INFO:nni.retiarii.experiment.pytorch:Strategy exit + INFO:nni.retiarii.experiment.pytorch:Waiting for experiment to become DONE (you can ctrl+c if there is no running trial jobs)... + INFO:nni.runtime.msg_dispatcher_base:Dispatcher exiting... + INFO:nni.retiarii.experiment.pytorch:Experiment stopped + + + + +.. GENERATED FROM PYTHON SOURCE LINES 312-330 + +除了 ``local`` 训练平台,用户还可以使用 :doc:`不同的训练平台 ` 来运行 Retiarii 试验。 + +可视化实验 +---------------------- + +用户可以可视化他们的架构搜索实验,就像可视化超参调优实验一样。 +例如,在浏览器中打开 ``localhost:8081``,8081 是您在 ``exp.run`` 中设置的端口。 +详情请参考 :doc:`这里`。 + +我们支持使用第三方可视化引擎(如 `Netron `__)对模型进行可视化。 +这可以通过单击每个试验的详细面板中的“可视化”来使用。 +请注意,当前的可视化是基于 `onnx `__, +因此,如果模型不能导出为 onnx,可视化是不可行的。 + +内置评估器(例如 Classification)会将模型自动导出到文件中。 +对于您自己的评估器,您需要将文件保存到 ``$NNI_OUTPUT_DIR/model.onnx``。 +例如, + +.. GENERATED FROM PYTHON SOURCE LINES 330-344 + +.. code-block:: default + + + import os + from pathlib import Path + + + def evaluate_model_with_visualization(model_cls): + model = model_cls() + # dump the model into an onnx + if 'NNI_OUTPUT_DIR' in os.environ: + dummy_input = torch.zeros(1, 3, 32, 32) + torch.onnx.export(model, (dummy_input, ), + Path(os.environ['NNI_OUTPUT_DIR']) / 'model.onnx') + evaluate_model(model_cls) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 345-353 + +重新启动实验,Web 界面上会显示一个按钮。 + +.. image:: ../../img/netron_entrance_webui.png + +导出最优模型 +----------------- + +搜索完成后,用户可以使用 ``export_top_models`` 导出最优模型。 + +.. GENERATED FROM PYTHON SOURCE LINES 353-357 + +.. code-block:: default + + + for model_dict in exp.export_top_models(formatter='dict'): + print(model_dict) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + {'model_1': '0', 'model_2': 0.25, 'model_3': 64} + + + + +.. GENERATED FROM PYTHON SOURCE LINES 358-362 + +输出是一个 JSON 对象,记录了最好的模型的每一个选择都选了什么。 +如果用户想要搜出来的模型的源代码,他们可以使用 :ref:`基于图的引擎 `,只需增加如下两行。 + +.. GENERATED FROM PYTHON SOURCE LINES 362-365 + +.. code-block:: default + + + exp_config.execution_engine = 'base' + export_formatter = 'code' + + + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 2 minutes 4.499 seconds) + + +.. _sphx_glr_download_tutorials_hello_nas.py: + + +.. only :: html + + .. container:: sphx-glr-footer + :class: sphx-glr-footer-example + + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: hello_nas.py ` + + + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: hello_nas.ipynb ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/hpo_nnictl/model.ipynb b/docs/source/tutorials/hpo_nnictl/model.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..f1acdfc84cfa733f50d01bde413b0b8813162302 --- /dev/null +++ b/docs/source/tutorials/hpo_nnictl/model.ipynb @@ -0,0 +1,162 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# Port PyTorch Quickstart to NNI\nThis is a modified version of `PyTorch quickstart`_.\n\nIt can be run directly and will have the exact same result as original version.\n\nFurthermore, it enables the ability of auto tuning with an NNI *experiment*, which will be detailed later.\n\nIt is recommended to run this script directly first to verify the environment.\n\nThere are 2 key differences from the original version:\n\n1. In `Get optimized hyperparameters`_ part, it receives generated hyperparameters.\n2. In `Train model and report accuracy`_ part, it reports accuracy metrics to NNI.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import nni\nimport torch\nfrom torch import nn\nfrom torch.utils.data import DataLoader\nfrom torchvision import datasets\nfrom torchvision.transforms import ToTensor" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Hyperparameters to be tuned\nThese are the hyperparameters that will be tuned.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "params = {\n 'features': 512,\n 'lr': 0.001,\n 'momentum': 0,\n}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Get optimized hyperparameters\nIf run directly, :func:`nni.get_next_parameter` is a no-op and returns an empty dict.\nBut with an NNI *experiment*, it will receive optimized hyperparameters from tuning algorithm.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "optimized_params = nni.get_next_parameter()\nparams.update(optimized_params)\nprint(params)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load dataset\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "training_data = datasets.FashionMNIST(root=\"data\", train=True, download=True, transform=ToTensor())\ntest_data = datasets.FashionMNIST(root=\"data\", train=False, download=True, transform=ToTensor())\n\nbatch_size = 64\n\ntrain_dataloader = DataLoader(training_data, batch_size=batch_size)\ntest_dataloader = DataLoader(test_data, batch_size=batch_size)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Build model with hyperparameters\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\nprint(f\"Using {device} device\")\n\nclass NeuralNetwork(nn.Module):\n def __init__(self):\n super(NeuralNetwork, self).__init__()\n self.flatten = nn.Flatten()\n self.linear_relu_stack = nn.Sequential(\n nn.Linear(28*28, params['features']),\n nn.ReLU(),\n nn.Linear(params['features'], params['features']),\n nn.ReLU(),\n nn.Linear(params['features'], 10)\n )\n\n def forward(self, x):\n x = self.flatten(x)\n logits = self.linear_relu_stack(x)\n return logits\n\nmodel = NeuralNetwork().to(device)\n\nloss_fn = nn.CrossEntropyLoss()\noptimizer = torch.optim.SGD(model.parameters(), lr=params['lr'], momentum=params['momentum'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define train and test\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def train(dataloader, model, loss_fn, optimizer):\n size = len(dataloader.dataset)\n model.train()\n for batch, (X, y) in enumerate(dataloader):\n X, y = X.to(device), y.to(device)\n pred = model(X)\n loss = loss_fn(pred, y)\n optimizer.zero_grad()\n loss.backward()\n optimizer.step()\n\ndef test(dataloader, model, loss_fn):\n size = len(dataloader.dataset)\n num_batches = len(dataloader)\n model.eval()\n test_loss, correct = 0, 0\n with torch.no_grad():\n for X, y in dataloader:\n X, y = X.to(device), y.to(device)\n pred = model(X)\n test_loss += loss_fn(pred, y).item()\n correct += (pred.argmax(1) == y).type(torch.float).sum().item()\n test_loss /= num_batches\n correct /= size\n return correct" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Train model and report accuracy\nReport accuracy metrics to NNI so the tuning algorithm can suggest better hyperparameters.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "epochs = 5\nfor t in range(epochs):\n print(f\"Epoch {t+1}\\n-------------------------------\")\n train(train_dataloader, model, loss_fn, optimizer)\n accuracy = test(test_dataloader, model, loss_fn)\n nni.report_intermediate_result(accuracy)\nnni.report_final_result(accuracy)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.3" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/docs/source/tutorials/hpo_nnictl/model.py b/docs/source/tutorials/hpo_nnictl/model.py new file mode 100644 index 0000000000000000000000000000000000000000..1bb07bf148e712d0450f8a93a29e9e7d3a9f0814 --- /dev/null +++ b/docs/source/tutorials/hpo_nnictl/model.py @@ -0,0 +1,125 @@ +""" +Port PyTorch Quickstart to NNI +============================== +This is a modified version of `PyTorch quickstart`_. + +It can be run directly and will have the exact same result as original version. + +Furthermore, it enables the ability of auto tuning with an NNI *experiment*, which will be detailed later. + +It is recommended to run this script directly first to verify the environment. + +There are 2 key differences from the original version: + +1. In `Get optimized hyperparameters`_ part, it receives generated hyperparameters. +2. In `Train model and report accuracy`_ part, it reports accuracy metrics to NNI. + +.. _PyTorch quickstart: https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html +""" + +# %% +import nni +import torch +from torch import nn +from torch.utils.data import DataLoader +from torchvision import datasets +from torchvision.transforms import ToTensor + +# %% +# Hyperparameters to be tuned +# --------------------------- +# These are the hyperparameters that will be tuned. +params = { + 'features': 512, + 'lr': 0.001, + 'momentum': 0, +} + +# %% +# Get optimized hyperparameters +# ----------------------------- +# If run directly, :func:`nni.get_next_parameter` is a no-op and returns an empty dict. +# But with an NNI *experiment*, it will receive optimized hyperparameters from tuning algorithm. +optimized_params = nni.get_next_parameter() +params.update(optimized_params) +print(params) + +# %% +# Load dataset +# ------------ +training_data = datasets.FashionMNIST(root="data", train=True, download=True, transform=ToTensor()) +test_data = datasets.FashionMNIST(root="data", train=False, download=True, transform=ToTensor()) + +batch_size = 64 + +train_dataloader = DataLoader(training_data, batch_size=batch_size) +test_dataloader = DataLoader(test_data, batch_size=batch_size) + +# %% +# Build model with hyperparameters +# -------------------------------- +device = "cuda" if torch.cuda.is_available() else "cpu" +print(f"Using {device} device") + +class NeuralNetwork(nn.Module): + def __init__(self): + super(NeuralNetwork, self).__init__() + self.flatten = nn.Flatten() + self.linear_relu_stack = nn.Sequential( + nn.Linear(28*28, params['features']), + nn.ReLU(), + nn.Linear(params['features'], params['features']), + nn.ReLU(), + nn.Linear(params['features'], 10) + ) + + def forward(self, x): + x = self.flatten(x) + logits = self.linear_relu_stack(x) + return logits + +model = NeuralNetwork().to(device) + +loss_fn = nn.CrossEntropyLoss() +optimizer = torch.optim.SGD(model.parameters(), lr=params['lr'], momentum=params['momentum']) + +# %% +# Define train and test +# --------------------- +def train(dataloader, model, loss_fn, optimizer): + size = len(dataloader.dataset) + model.train() + for batch, (X, y) in enumerate(dataloader): + X, y = X.to(device), y.to(device) + pred = model(X) + loss = loss_fn(pred, y) + optimizer.zero_grad() + loss.backward() + optimizer.step() + +def test(dataloader, model, loss_fn): + size = len(dataloader.dataset) + num_batches = len(dataloader) + model.eval() + test_loss, correct = 0, 0 + with torch.no_grad(): + for X, y in dataloader: + X, y = X.to(device), y.to(device) + pred = model(X) + test_loss += loss_fn(pred, y).item() + correct += (pred.argmax(1) == y).type(torch.float).sum().item() + test_loss /= num_batches + correct /= size + return correct + +# %% +# Train model and report accuracy +# ------------------------------- +# Report accuracy metrics to NNI so the tuning algorithm can suggest better hyperparameters. +epochs = 5 +for t in range(epochs): + print(f"Epoch {t+1}\n-------------------------------") + train(train_dataloader, model, loss_fn, optimizer) + accuracy = test(test_dataloader, model, loss_fn) + nni.report_intermediate_result(accuracy) +nni.report_final_result(accuracy) diff --git a/docs/source/tutorials/hpo_nnictl/model.py.md5 b/docs/source/tutorials/hpo_nnictl/model.py.md5 new file mode 100644 index 0000000000000000000000000000000000000000..4559246a46ee2117cab8a12000e5d39683b0e633 --- /dev/null +++ b/docs/source/tutorials/hpo_nnictl/model.py.md5 @@ -0,0 +1 @@ +ed8bfc27e3d555d842fc4eec2635e619 \ No newline at end of file diff --git a/docs/source/tutorials/hpo_nnictl/model.rst b/docs/source/tutorials/hpo_nnictl/model.rst new file mode 100644 index 0000000000000000000000000000000000000000..9c978807ef48b0a61e7c52076b7c7a2fe6545aee --- /dev/null +++ b/docs/source/tutorials/hpo_nnictl/model.rst @@ -0,0 +1,303 @@ +:orphan: + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "tutorials/hpo_nnictl/model.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_tutorials_hpo_nnictl_model.py: + + +Port PyTorch Quickstart to NNI +============================== +This is a modified version of `PyTorch quickstart`_. + +It can be run directly and will have the exact same result as original version. + +Furthermore, it enables the ability of auto tuning with an NNI *experiment*, which will be detailed later. + +It is recommended to run this script directly first to verify the environment. + +There are 2 key differences from the original version: + +1. In `Get optimized hyperparameters`_ part, it receives generated hyperparameters. +2. In `Train model and report accuracy`_ part, it reports accuracy metrics to NNI. + +.. _PyTorch quickstart: https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html + +.. GENERATED FROM PYTHON SOURCE LINES 21-28 + +.. code-block:: default + + import nni + import torch + from torch import nn + from torch.utils.data import DataLoader + from torchvision import datasets + from torchvision.transforms import ToTensor + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 29-32 + +Hyperparameters to be tuned +--------------------------- +These are the hyperparameters that will be tuned. + +.. GENERATED FROM PYTHON SOURCE LINES 32-38 + +.. code-block:: default + + params = { + 'features': 512, + 'lr': 0.001, + 'momentum': 0, + } + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 39-43 + +Get optimized hyperparameters +----------------------------- +If run directly, :func:`nni.get_next_parameter` is a no-op and returns an empty dict. +But with an NNI *experiment*, it will receive optimized hyperparameters from tuning algorithm. + +.. GENERATED FROM PYTHON SOURCE LINES 43-47 + +.. code-block:: default + + optimized_params = nni.get_next_parameter() + params.update(optimized_params) + print(params) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + {'features': 512, 'lr': 0.001, 'momentum': 0} + + + + +.. GENERATED FROM PYTHON SOURCE LINES 48-50 + +Load dataset +------------ + +.. GENERATED FROM PYTHON SOURCE LINES 50-58 + +.. code-block:: default + + training_data = datasets.FashionMNIST(root="data", train=True, download=True, transform=ToTensor()) + test_data = datasets.FashionMNIST(root="data", train=False, download=True, transform=ToTensor()) + + batch_size = 64 + + train_dataloader = DataLoader(training_data, batch_size=batch_size) + test_dataloader = DataLoader(test_data, batch_size=batch_size) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 59-61 + +Build model with hyperparameters +-------------------------------- + +.. GENERATED FROM PYTHON SOURCE LINES 61-86 + +.. code-block:: default + + device = "cuda" if torch.cuda.is_available() else "cpu" + print(f"Using {device} device") + + class NeuralNetwork(nn.Module): + def __init__(self): + super(NeuralNetwork, self).__init__() + self.flatten = nn.Flatten() + self.linear_relu_stack = nn.Sequential( + nn.Linear(28*28, params['features']), + nn.ReLU(), + nn.Linear(params['features'], params['features']), + nn.ReLU(), + nn.Linear(params['features'], 10) + ) + + def forward(self, x): + x = self.flatten(x) + logits = self.linear_relu_stack(x) + return logits + + model = NeuralNetwork().to(device) + + loss_fn = nn.CrossEntropyLoss() + optimizer = torch.optim.SGD(model.parameters(), lr=params['lr'], momentum=params['momentum']) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + Using cpu device + + + + +.. GENERATED FROM PYTHON SOURCE LINES 87-89 + +Define train and test +--------------------- + +.. GENERATED FROM PYTHON SOURCE LINES 89-115 + +.. code-block:: default + + def train(dataloader, model, loss_fn, optimizer): + size = len(dataloader.dataset) + model.train() + for batch, (X, y) in enumerate(dataloader): + X, y = X.to(device), y.to(device) + pred = model(X) + loss = loss_fn(pred, y) + optimizer.zero_grad() + loss.backward() + optimizer.step() + + def test(dataloader, model, loss_fn): + size = len(dataloader.dataset) + num_batches = len(dataloader) + model.eval() + test_loss, correct = 0, 0 + with torch.no_grad(): + for X, y in dataloader: + X, y = X.to(device), y.to(device) + pred = model(X) + test_loss += loss_fn(pred, y).item() + correct += (pred.argmax(1) == y).type(torch.float).sum().item() + test_loss /= num_batches + correct /= size + return correct + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 116-119 + +Train model and report accuracy +------------------------------- +Report accuracy metrics to NNI so the tuning algorithm can suggest better hyperparameters. + +.. GENERATED FROM PYTHON SOURCE LINES 119-126 + +.. code-block:: default + + epochs = 5 + for t in range(epochs): + print(f"Epoch {t+1}\n-------------------------------") + train(train_dataloader, model, loss_fn, optimizer) + accuracy = test(test_dataloader, model, loss_fn) + nni.report_intermediate_result(accuracy) + nni.report_final_result(accuracy) + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + Epoch 1 + ------------------------------- + [2022-03-21 01:09:37] INFO (nni/MainThread) Intermediate result: 0.461 (Index 0) + Epoch 2 + ------------------------------- + [2022-03-21 01:09:42] INFO (nni/MainThread) Intermediate result: 0.5529 (Index 1) + Epoch 3 + ------------------------------- + [2022-03-21 01:09:47] INFO (nni/MainThread) Intermediate result: 0.6155 (Index 2) + Epoch 4 + ------------------------------- + [2022-03-21 01:09:52] INFO (nni/MainThread) Intermediate result: 0.6345 (Index 3) + Epoch 5 + ------------------------------- + [2022-03-21 01:09:56] INFO (nni/MainThread) Intermediate result: 0.6505 (Index 4) + [2022-03-21 01:09:56] INFO (nni/MainThread) Final result: 0.6505 + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 24.441 seconds) + + +.. _sphx_glr_download_tutorials_hpo_nnictl_model.py: + + +.. only :: html + + .. container:: sphx-glr-footer + :class: sphx-glr-footer-example + + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: model.py ` + + + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: model.ipynb ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/hpo_nnictl/model_codeobj.pickle b/docs/source/tutorials/hpo_nnictl/model_codeobj.pickle new file mode 100644 index 0000000000000000000000000000000000000000..a3c2703b82cc3d598535e1496393fb9933b3e58c Binary files /dev/null and b/docs/source/tutorials/hpo_nnictl/model_codeobj.pickle differ diff --git a/docs/source/tutorials/hpo_nnictl/nnictl.rst b/docs/source/tutorials/hpo_nnictl/nnictl.rst new file mode 100644 index 0000000000000000000000000000000000000000..c5032207204e35dc4ea6a74db767f9fcbc4ca7f0 --- /dev/null +++ b/docs/source/tutorials/hpo_nnictl/nnictl.rst @@ -0,0 +1,207 @@ +Run HPO Experiment with nnictl +============================== + +This tutorial has exactly the same effect as :doc:`../hpo_quickstart_pytorch/main`. + +Both tutorials optimize the model in `official PyTorch quickstart +`__ with auto-tuning, +while this one manages the experiment with command line tool and YAML config file, instead of pure Python code. + +The tutorial consists of 4 steps: + +1. Modify the model for auto-tuning. +2. Define hyperparameters' search space. +3. Create config file. +4. Run the experiment. + +The first two steps are identical to quickstart. + +Step 1: Prepare the model +------------------------- +In first step, we need to prepare the model to be tuned. + +The model should be put in a separate script. +It will be evaluated many times concurrently, +and possibly will be trained on distributed platforms. + +In this tutorial, the model is defined in :doc:`model.py `. + +In short, it is a PyTorch model with 3 additional API calls: + +1. Use :func:`nni.get_next_parameter` to fetch the hyperparameters to be evalutated. +2. Use :func:`nni.report_intermediate_result` to report per-epoch accuracy metrics. +3. Use :func:`nni.report_final_result` to report final accuracy. + +Please understand the model code before continue to next step. + +Step 2: Define search space +--------------------------- +In model code, we have prepared 3 hyperparameters to be tuned: +*features*, *lr*, and *momentum*. + +Here we need to define their *search space* so the tuning algorithm can sample them in desired range. + +Assuming we have following prior knowledge for these hyperparameters: + +1. *features* should be one of 128, 256, 512, 1024. +2. *lr* should be a float between 0.0001 and 0.1, and it follows exponential distribution. +3. *momentum* should be a float between 0 and 1. + +In NNI, the space of *features* is called ``choice``; +the space of *lr* is called ``loguniform``; +and the space of *momentum* is called ``uniform``. +You may have noticed, these names are derived from ``numpy.random``. + +For full specification of search space, check :doc:`the reference `. + +Now we can define the search space as follow: + +.. code-block:: yaml + + search_space: + features: + _type: choice + _value: [ 128, 256, 512, 1024 ] + lr: + _type: loguniform + _value: [ 0.0001, 0.1 ] + momentum: + _type: uniform + _value: [ 0, 1 ] + +Step 3: Configure the experiment +-------------------------------- +NNI uses an *experiment* to manage the HPO process. +The *experiment config* defines how to train the models and how to explore the search space. + +In this tutorial we use a YAML file ``config.yaml`` to define the experiment. + +Configure trial code +^^^^^^^^^^^^^^^^^^^^ +In NNI evaluation of each hyperparameter set is called a *trial*. +So the model script is called *trial code*. + +.. code-block:: yaml + + trial_command: python model.py + trial_code_directory: . + +When ``trial_code_directory`` is a relative path, it relates to the config file. +So in this case we need to put ``config.yaml`` and ``model.py`` in the same directory. + +.. attention:: + + The rules for resolving relative path are different in YAML config file and :doc:`Python experiment API `. + In Python experiment API relative paths are relative to current working directory. + +Configure how many trials to run +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Here we evaluate 10 sets of hyperparameters in total, and concurrently evaluate 2 sets at a time. + +.. code-block:: yaml + + max_trial_number: 10 + trial_concurrency: 2 + +You may also set ``max_experiment_duration = '1h'`` to limit running time. + +If neither ``max_trial_number`` nor ``max_experiment_duration`` are set, +the experiment will run forever until you stop it. + +.. note:: + + ``max_trial_number`` is set to 10 here for a fast example. + In real world it should be set to a larger number. + With default config TPE tuner requires 20 trials to warm up. + + +Configure tuning algorithm +^^^^^^^^^^^^^^^^^^^^^^^^^^ +Here we use :doc:`TPE tuner `. + +.. code-block:: yaml + + name: TPE + class_args: + optimize_mode: maximize + +Configure training service +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In this tutorial we use *local* mode, +which means models will be trained on local machine, without using any special training platform. + +.. code-block:: yaml + + training_service: + platform: local + +Wrap up +^^^^^^^ + +The full content of ``config.yaml`` is as follow: + +.. code-block:: yaml + + search_space: + features: + _type: choice + _value: [ 128, 256, 512, 1024 ] + lr: + _type: loguniform + _value: [ 0.0001, 0.1 ] + momentum: + _type: uniform + _value: [ 0, 1 ] + + trial_command: python model.py + trial_code_directory: . + + trial_concurrency: 2 + max_trial_number: 10 + + tuner: + name: TPE + class_args: + optimize_mode: maximize + + training_service: + platform: local + +Step 4: Run the experiment +-------------------------- +Now the experiment is ready. Launch it with ``nnictl create`` command: + +.. code-block:: bash + + $ nnictl create --config config.yaml --port 8080 + +You can use the web portal to view experiment status: http://localhost:8080. + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + [2022-04-01 12:00:00] Creating experiment, Experiment ID: p43ny6ew + [2022-04-01 12:00:00] Starting web server... + [2022-04-01 12:00:01] Setting up... + [2022-04-01 12:00:01] Web portal URLs: http://127.0.0.1:8080 http://192.168.1.1:8080 + [2022-04-01 12:00:01] To stop experiment run "nnictl stop p43ny6ew" or "nnictl stop --all" + [2022-04-01 12:00:01] Reference: https://nni.readthedocs.io/en/stable/reference/nnictl.html + +When the experiment is done, use ``nnictl stop`` command to stop it. + +.. code-block:: bash + + $ nnictl stop p43ny6ew + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + INFO: Stopping experiment 7u8yg9zw + INFO: Stop experiment success. diff --git a/docs/source/tutorials/hpo_quickstart_pytorch/images/thumb/sphx_glr_main_thumb.png b/docs/source/tutorials/hpo_quickstart_pytorch/images/thumb/sphx_glr_main_thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..b06c4e6a17748efb9e7d009eb1e161759cfa2b74 Binary files /dev/null and b/docs/source/tutorials/hpo_quickstart_pytorch/images/thumb/sphx_glr_main_thumb.png differ diff --git a/docs/source/tutorials/hpo_quickstart_pytorch/images/thumb/sphx_glr_model_thumb.png b/docs/source/tutorials/hpo_quickstart_pytorch/images/thumb/sphx_glr_model_thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..b06c4e6a17748efb9e7d009eb1e161759cfa2b74 Binary files /dev/null and b/docs/source/tutorials/hpo_quickstart_pytorch/images/thumb/sphx_glr_model_thumb.png differ diff --git a/docs/source/tutorials/hpo_quickstart_pytorch/main.ipynb b/docs/source/tutorials/hpo_quickstart_pytorch/main.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..a464395de8f0f0ebea1bbf2597cfe8f427703b94 --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_pytorch/main.ipynb @@ -0,0 +1,215 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# HPO Quickstart with PyTorch\nThis tutorial optimizes the model in `official PyTorch quickstart`_ with auto-tuning.\n\nThe tutorial consists of 4 steps: \n\n1. Modify the model for auto-tuning.\n2. Define hyperparameters' search space.\n3. Configure the experiment.\n4. Run the experiment.\n\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 1: Prepare the model\nIn first step, we need to prepare the model to be tuned.\n\nThe model should be put in a separate script.\nIt will be evaluated many times concurrently,\nand possibly will be trained on distributed platforms.\n\nIn this tutorial, the model is defined in :doc:`model.py `.\n\nIn short, it is a PyTorch model with 3 additional API calls:\n\n1. Use :func:`nni.get_next_parameter` to fetch the hyperparameters to be evalutated.\n2. Use :func:`nni.report_intermediate_result` to report per-epoch accuracy metrics.\n3. Use :func:`nni.report_final_result` to report final accuracy.\n\nPlease understand the model code before continue to next step.\n\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 2: Define search space\nIn model code, we have prepared 3 hyperparameters to be tuned:\n*features*, *lr*, and *momentum*.\n\nHere we need to define their *search space* so the tuning algorithm can sample them in desired range.\n\nAssuming we have following prior knowledge for these hyperparameters:\n\n1. *features* should be one of 128, 256, 512, 1024.\n2. *lr* should be a float between 0.0001 and 0.1, and it follows exponential distribution.\n3. *momentum* should be a float between 0 and 1.\n\nIn NNI, the space of *features* is called ``choice``;\nthe space of *lr* is called ``loguniform``;\nand the space of *momentum* is called ``uniform``.\nYou may have noticed, these names are derived from ``numpy.random``.\n\nFor full specification of search space, check :doc:`the reference `.\n\nNow we can define the search space as follow:\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "search_space = {\n 'features': {'_type': 'choice', '_value': [128, 256, 512, 1024]},\n 'lr': {'_type': 'loguniform', '_value': [0.0001, 0.1]},\n 'momentum': {'_type': 'uniform', '_value': [0, 1]},\n}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 3: Configure the experiment\nNNI uses an *experiment* to manage the HPO process.\nThe *experiment config* defines how to train the models and how to explore the search space.\n\nIn this tutorial we use a *local* mode experiment,\nwhich means models will be trained on local machine, without using any special training platform.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from nni.experiment import Experiment\nexperiment = Experiment('local')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we start to configure the experiment.\n\n### Configure trial code\nIn NNI evaluation of each hyperparameter set is called a *trial*.\nSo the model script is called *trial code*.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "experiment.config.trial_command = 'python model.py'\nexperiment.config.trial_code_directory = '.'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When ``trial_code_directory`` is a relative path, it relates to current working directory.\nTo run ``main.py`` in a different path, you can set trial code directory to ``Path(__file__).parent``.\n(`__file__ `__\nis only available in standard Python, not in Jupyter Notebook.)\n\n.. attention::\n\n If you are using Linux system without Conda,\n you may need to change ``\"python model.py\"`` to ``\"python3 model.py\"``.\n\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Configure search space\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "experiment.config.search_space = search_space" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Configure tuning algorithm\nHere we use :doc:`TPE tuner `.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "experiment.config.tuner.name = 'TPE'\nexperiment.config.tuner.class_args['optimize_mode'] = 'maximize'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Configure how many trials to run\nHere we evaluate 10 sets of hyperparameters in total, and concurrently evaluate 2 sets at a time.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "experiment.config.max_trial_number = 10\nexperiment.config.trial_concurrency = 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You may also set ``max_experiment_duration = '1h'`` to limit running time.\n\nIf neither ``max_trial_number`` nor ``max_experiment_duration`` are set,\nthe experiment will run forever until you press Ctrl-C.\n\n

Note

``max_trial_number`` is set to 10 here for a fast example.\n In real world it should be set to a larger number.\n With default config TPE tuner requires 20 trials to warm up.

\n\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 4: Run the experiment\nNow the experiment is ready. Choose a port and launch it. (Here we use port 8080.)\n\nYou can use the web portal to view experiment status: http://localhost:8080.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "experiment.run(8080)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## After the experiment is done\nEverything is done and it is safe to exit now. The following are optional.\n\nIf you are using standard Python instead of Jupyter Notebook,\nyou can add ``input()`` or ``signal.pause()`` to prevent Python from exiting,\nallowing you to view the web portal after the experiment is done.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# input('Press enter to quit')\nexperiment.stop()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + ":meth:`nni.experiment.Experiment.stop` is automatically invoked when Python exits,\nso it can be omitted in your code.\n\nAfter the experiment is stopped, you can run :meth:`nni.experiment.Experiment.view` to restart web portal.\n\n.. tip::\n\n This example uses :doc:`Python API ` to create experiment.\n\n You can also create and manage experiments with :doc:`command line tool <../hpo_nnictl/nnictl>`.\n\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/docs/source/tutorials/hpo_quickstart_pytorch/main.py b/docs/source/tutorials/hpo_quickstart_pytorch/main.py new file mode 100644 index 0000000000000000000000000000000000000000..648e03be85bba7aa000f523c0b1ae84579546e9f --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_pytorch/main.py @@ -0,0 +1,155 @@ +""" +HPO Quickstart with PyTorch +=========================== +This tutorial optimizes the model in `official PyTorch quickstart`_ with auto-tuning. + +The tutorial consists of 4 steps: + +1. Modify the model for auto-tuning. +2. Define hyperparameters' search space. +3. Configure the experiment. +4. Run the experiment. + +.. _official PyTorch quickstart: https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html +""" + +# %% +# Step 1: Prepare the model +# ------------------------- +# In first step, we need to prepare the model to be tuned. +# +# The model should be put in a separate script. +# It will be evaluated many times concurrently, +# and possibly will be trained on distributed platforms. +# +# In this tutorial, the model is defined in :doc:`model.py `. +# +# In short, it is a PyTorch model with 3 additional API calls: +# +# 1. Use :func:`nni.get_next_parameter` to fetch the hyperparameters to be evalutated. +# 2. Use :func:`nni.report_intermediate_result` to report per-epoch accuracy metrics. +# 3. Use :func:`nni.report_final_result` to report final accuracy. +# +# Please understand the model code before continue to next step. + +# %% +# Step 2: Define search space +# --------------------------- +# In model code, we have prepared 3 hyperparameters to be tuned: +# *features*, *lr*, and *momentum*. +# +# Here we need to define their *search space* so the tuning algorithm can sample them in desired range. +# +# Assuming we have following prior knowledge for these hyperparameters: +# +# 1. *features* should be one of 128, 256, 512, 1024. +# 2. *lr* should be a float between 0.0001 and 0.1, and it follows exponential distribution. +# 3. *momentum* should be a float between 0 and 1. +# +# In NNI, the space of *features* is called ``choice``; +# the space of *lr* is called ``loguniform``; +# and the space of *momentum* is called ``uniform``. +# You may have noticed, these names are derived from ``numpy.random``. +# +# For full specification of search space, check :doc:`the reference `. +# +# Now we can define the search space as follow: + +search_space = { + 'features': {'_type': 'choice', '_value': [128, 256, 512, 1024]}, + 'lr': {'_type': 'loguniform', '_value': [0.0001, 0.1]}, + 'momentum': {'_type': 'uniform', '_value': [0, 1]}, +} + +# %% +# Step 3: Configure the experiment +# -------------------------------- +# NNI uses an *experiment* to manage the HPO process. +# The *experiment config* defines how to train the models and how to explore the search space. +# +# In this tutorial we use a *local* mode experiment, +# which means models will be trained on local machine, without using any special training platform. +from nni.experiment import Experiment +experiment = Experiment('local') + +# %% +# Now we start to configure the experiment. +# +# Configure trial code +# ^^^^^^^^^^^^^^^^^^^^ +# In NNI evaluation of each hyperparameter set is called a *trial*. +# So the model script is called *trial code*. +experiment.config.trial_command = 'python model.py' +experiment.config.trial_code_directory = '.' +# %% +# When ``trial_code_directory`` is a relative path, it relates to current working directory. +# To run ``main.py`` in a different path, you can set trial code directory to ``Path(__file__).parent``. +# (`__file__ `__ +# is only available in standard Python, not in Jupyter Notebook.) +# +# .. attention:: +# +# If you are using Linux system without Conda, +# you may need to change ``"python model.py"`` to ``"python3 model.py"``. + +# %% +# Configure search space +# ^^^^^^^^^^^^^^^^^^^^^^ +experiment.config.search_space = search_space + +# %% +# Configure tuning algorithm +# ^^^^^^^^^^^^^^^^^^^^^^^^^^ +# Here we use :doc:`TPE tuner `. +experiment.config.tuner.name = 'TPE' +experiment.config.tuner.class_args['optimize_mode'] = 'maximize' + +# %% +# Configure how many trials to run +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# Here we evaluate 10 sets of hyperparameters in total, and concurrently evaluate 2 sets at a time. +experiment.config.max_trial_number = 10 +experiment.config.trial_concurrency = 2 +# %% +# You may also set ``max_experiment_duration = '1h'`` to limit running time. +# +# If neither ``max_trial_number`` nor ``max_experiment_duration`` are set, +# the experiment will run forever until you press Ctrl-C. +# +# .. note:: +# +# ``max_trial_number`` is set to 10 here for a fast example. +# In real world it should be set to a larger number. +# With default config TPE tuner requires 20 trials to warm up. + +# %% +# Step 4: Run the experiment +# -------------------------- +# Now the experiment is ready. Choose a port and launch it. (Here we use port 8080.) +# +# You can use the web portal to view experiment status: http://localhost:8080. +experiment.run(8080) + +# %% +# After the experiment is done +# ---------------------------- +# Everything is done and it is safe to exit now. The following are optional. +# +# If you are using standard Python instead of Jupyter Notebook, +# you can add ``input()`` or ``signal.pause()`` to prevent Python from exiting, +# allowing you to view the web portal after the experiment is done. + +# input('Press enter to quit') +experiment.stop() + +# %% +# :meth:`nni.experiment.Experiment.stop` is automatically invoked when Python exits, +# so it can be omitted in your code. +# +# After the experiment is stopped, you can run :meth:`nni.experiment.Experiment.view` to restart web portal. +# +# .. tip:: +# +# This example uses :doc:`Python API ` to create experiment. +# +# You can also create and manage experiments with :doc:`command line tool <../hpo_nnictl/nnictl>`. diff --git a/docs/source/tutorials/hpo_quickstart_pytorch/main.py.md5 b/docs/source/tutorials/hpo_quickstart_pytorch/main.py.md5 new file mode 100644 index 0000000000000000000000000000000000000000..1dc17777f25181cc410619d4c7bcf4d783fd3dfe --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_pytorch/main.py.md5 @@ -0,0 +1 @@ +e732cee426a4629b71f5fa28ce16fad7 \ No newline at end of file diff --git a/docs/source/tutorials/hpo_quickstart_pytorch/main.rst b/docs/source/tutorials/hpo_quickstart_pytorch/main.rst new file mode 100644 index 0000000000000000000000000000000000000000..00abe19c0c56c87d1887e636472586317d23a211 --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_pytorch/main.rst @@ -0,0 +1,335 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "tutorials/hpo_quickstart_pytorch/main.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_tutorials_hpo_quickstart_pytorch_main.py: + + +HPO Quickstart with PyTorch +=========================== +This tutorial optimizes the model in `official PyTorch quickstart`_ with auto-tuning. + +The tutorial consists of 4 steps: + +1. Modify the model for auto-tuning. +2. Define hyperparameters' search space. +3. Configure the experiment. +4. Run the experiment. + +.. _official PyTorch quickstart: https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html + +.. GENERATED FROM PYTHON SOURCE LINES 17-34 + +Step 1: Prepare the model +------------------------- +In first step, we need to prepare the model to be tuned. + +The model should be put in a separate script. +It will be evaluated many times concurrently, +and possibly will be trained on distributed platforms. + +In this tutorial, the model is defined in :doc:`model.py `. + +In short, it is a PyTorch model with 3 additional API calls: + +1. Use :func:`nni.get_next_parameter` to fetch the hyperparameters to be evalutated. +2. Use :func:`nni.report_intermediate_result` to report per-epoch accuracy metrics. +3. Use :func:`nni.report_final_result` to report final accuracy. + +Please understand the model code before continue to next step. + +.. GENERATED FROM PYTHON SOURCE LINES 36-57 + +Step 2: Define search space +--------------------------- +In model code, we have prepared 3 hyperparameters to be tuned: +*features*, *lr*, and *momentum*. + +Here we need to define their *search space* so the tuning algorithm can sample them in desired range. + +Assuming we have following prior knowledge for these hyperparameters: + +1. *features* should be one of 128, 256, 512, 1024. +2. *lr* should be a float between 0.0001 and 0.1, and it follows exponential distribution. +3. *momentum* should be a float between 0 and 1. + +In NNI, the space of *features* is called ``choice``; +the space of *lr* is called ``loguniform``; +and the space of *momentum* is called ``uniform``. +You may have noticed, these names are derived from ``numpy.random``. + +For full specification of search space, check :doc:`the reference `. + +Now we can define the search space as follow: + +.. GENERATED FROM PYTHON SOURCE LINES 57-64 + +.. code-block:: default + + + search_space = { + 'features': {'_type': 'choice', '_value': [128, 256, 512, 1024]}, + 'lr': {'_type': 'loguniform', '_value': [0.0001, 0.1]}, + 'momentum': {'_type': 'uniform', '_value': [0, 1]}, + } + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 65-72 + +Step 3: Configure the experiment +-------------------------------- +NNI uses an *experiment* to manage the HPO process. +The *experiment config* defines how to train the models and how to explore the search space. + +In this tutorial we use a *local* mode experiment, +which means models will be trained on local machine, without using any special training platform. + +.. GENERATED FROM PYTHON SOURCE LINES 72-75 + +.. code-block:: default + + from nni.experiment import Experiment + experiment = Experiment('local') + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 76-82 + +Now we start to configure the experiment. + +Configure trial code +^^^^^^^^^^^^^^^^^^^^ +In NNI evaluation of each hyperparameter set is called a *trial*. +So the model script is called *trial code*. + +.. GENERATED FROM PYTHON SOURCE LINES 82-84 + +.. code-block:: default + + experiment.config.trial_command = 'python model.py' + experiment.config.trial_code_directory = '.' + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 85-94 + +When ``trial_code_directory`` is a relative path, it relates to current working directory. +To run ``main.py`` in a different path, you can set trial code directory to ``Path(__file__).parent``. +(`__file__ `__ +is only available in standard Python, not in Jupyter Notebook.) + +.. attention:: + + If you are using Linux system without Conda, + you may need to change ``"python model.py"`` to ``"python3 model.py"``. + +.. GENERATED FROM PYTHON SOURCE LINES 96-98 + +Configure search space +^^^^^^^^^^^^^^^^^^^^^^ + +.. GENERATED FROM PYTHON SOURCE LINES 98-100 + +.. code-block:: default + + experiment.config.search_space = search_space + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 101-104 + +Configure tuning algorithm +^^^^^^^^^^^^^^^^^^^^^^^^^^ +Here we use :doc:`TPE tuner `. + +.. GENERATED FROM PYTHON SOURCE LINES 104-107 + +.. code-block:: default + + experiment.config.tuner.name = 'TPE' + experiment.config.tuner.class_args['optimize_mode'] = 'maximize' + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 108-111 + +Configure how many trials to run +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Here we evaluate 10 sets of hyperparameters in total, and concurrently evaluate 2 sets at a time. + +.. GENERATED FROM PYTHON SOURCE LINES 111-113 + +.. code-block:: default + + experiment.config.max_trial_number = 10 + experiment.config.trial_concurrency = 2 + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 114-124 + +You may also set ``max_experiment_duration = '1h'`` to limit running time. + +If neither ``max_trial_number`` nor ``max_experiment_duration`` are set, +the experiment will run forever until you press Ctrl-C. + +.. note:: + + ``max_trial_number`` is set to 10 here for a fast example. + In real world it should be set to a larger number. + With default config TPE tuner requires 20 trials to warm up. + +.. GENERATED FROM PYTHON SOURCE LINES 126-131 + +Step 4: Run the experiment +-------------------------- +Now the experiment is ready. Choose a port and launch it. (Here we use port 8080.) + +You can use the web portal to view experiment status: http://localhost:8080. + +.. GENERATED FROM PYTHON SOURCE LINES 131-133 + +.. code-block:: default + + experiment.run(8080) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + [2022-04-13 12:07:29] Creating experiment, Experiment ID: hgkju3iq + [2022-04-13 12:07:29] Starting web server... + [2022-04-13 12:07:30] Setting up... + [2022-04-13 12:07:30] Web portal URLs: http://127.0.0.1:8080 http://192.168.100.103:8080 + + True + + + +.. GENERATED FROM PYTHON SOURCE LINES 134-141 + +After the experiment is done +---------------------------- +Everything is done and it is safe to exit now. The following are optional. + +If you are using standard Python instead of Jupyter Notebook, +you can add ``input()`` or ``signal.pause()`` to prevent Python from exiting, +allowing you to view the web portal after the experiment is done. + +.. GENERATED FROM PYTHON SOURCE LINES 141-145 + +.. code-block:: default + + + # input('Press enter to quit') + experiment.stop() + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + [2022-04-13 12:08:50] Stopping experiment, please wait... + [2022-04-13 12:08:53] Experiment stopped + + + + +.. GENERATED FROM PYTHON SOURCE LINES 146-156 + +:meth:`nni.experiment.Experiment.stop` is automatically invoked when Python exits, +so it can be omitted in your code. + +After the experiment is stopped, you can run :meth:`nni.experiment.Experiment.view` to restart web portal. + +.. tip:: + + This example uses :doc:`Python API ` to create experiment. + + You can also create and manage experiments with :doc:`command line tool <../hpo_nnictl/nnictl>`. + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 1 minutes 24.367 seconds) + + +.. _sphx_glr_download_tutorials_hpo_quickstart_pytorch_main.py: + + +.. only :: html + + .. container:: sphx-glr-footer + :class: sphx-glr-footer-example + + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: main.py ` + + + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: main.ipynb ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/hpo_quickstart_pytorch/main_codeobj.pickle b/docs/source/tutorials/hpo_quickstart_pytorch/main_codeobj.pickle new file mode 100644 index 0000000000000000000000000000000000000000..b1cf18cbaeeaeca0f986d313be610ed25f91deb0 Binary files /dev/null and b/docs/source/tutorials/hpo_quickstart_pytorch/main_codeobj.pickle differ diff --git a/docs/source/tutorials/hpo_quickstart_pytorch/main_zh.rst b/docs/source/tutorials/hpo_quickstart_pytorch/main_zh.rst new file mode 100644 index 0000000000000000000000000000000000000000..0ca5d91067d947f56955fd3c18c9cb96b9f37f46 --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_pytorch/main_zh.rst @@ -0,0 +1,327 @@ +.. a395c59bf5359c3583b7a0a3ab66d705 + + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "tutorials/hpo_quickstart_pytorch/main.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_tutorials_hpo_quickstart_pytorch_main.py: + + +HPO 教程(PyTorch 版本) +======================== +本教程对 `PyTorch 官方教程 `__ 进行超参调优。 + +教程分为四步: + +1. 修改调优的模型代码; +2. 定义超参的搜索空间; +3. 配置实验; +4. 运行实验。 + +.. GENERATED FROM PYTHON SOURCE LINES 17-34 + +步骤一:准备模型 +---------------- +首先,我们需要准备待调优的模型。 + +由于被调优的模型会被独立地运行多次, +并且使用特定训练平台时还可能会被上传到云端执行, +我们需要将代码写在另一个 py 文件中。 + +本教程使用的模型的代码是 :doc:`model.py `。 + +模型代码在一个普通的 PyTorch 模型基础之上,增加了3个 API 调用: + +1. 使用 :func:`nni.get_next_parameter` 获取需要评估的超参; +2. 使用 :func:`nni.report_intermediate_result` 报告每个 epoch 产生的中间训练结果; +3. 使用 :func:`nni.report_final_result` 报告最终准确率。 + +请先理解模型代码,然后再继续下一步。 + +.. GENERATED FROM PYTHON SOURCE LINES 36-57 + +步骤二:定义搜索空间 +-------------------- +在模型代码中,我们准备了三个需要调优的超参:features、lr、momentum。 + +现在,我们需要定义的它们的“搜索空间”,指定它们的取值范围和分布规律。 + +假设我们对三个超参有以下先验知识: + +1. features 的取值可以为128、256、512、1024; +2. lr 的取值在0.0001到0.1之间,其取值符合指数分布; +3. momentum 的取值在0到1之间。 + +在 NNI 中,features 的取值范围称为 ``choice`` , +lr 的取值范围称为 ``loguniform`` , +momentum 的取值范围称为 ``uniform`` 。 +您可能已经注意到了,这些名称和 ``numpy.random`` 中的函数名一致。 + +完整的搜索空间文档: :doc:`/hpo/search_space`. + +我们的搜索空间定义如下: + +.. GENERATED FROM PYTHON SOURCE LINES 57-64 + +.. code-block:: default + + + search_space = { + 'features': {'_type': 'choice', '_value': [128, 256, 512, 1024]}, + 'lr': {'_type': 'loguniform', '_value': [0.0001, 0.1]}, + 'momentum': {'_type': 'uniform', '_value': [0, 1]}, + } + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 65-72 + +步骤三:配置实验 +---------------- +NNI 使用“实验”来管理超参调优,“实验配置”定义了如何训练模型、如何遍历搜索空间。 + +在本教程中我们使用 local 模式的实验,这意味着实验只在本机运行,不使用任何特别的训练平台。 + +.. GENERATED FROM PYTHON SOURCE LINES 72-75 + +.. code-block:: default + + from nni.experiment import Experiment + experiment = Experiment('local') + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 76-82 + +现在我们开始配置实验。 + +配置 trial +^^^^^^^^^^ +在 NNI 中评估一组超参的过程被称为一个“trial”(试验),上面的模型代码被称为“trial 代码”。 + +.. GENERATED FROM PYTHON SOURCE LINES 82-84 + +.. code-block:: default + + experiment.config.trial_command = 'python model.py' + experiment.config.trial_code_directory = '.' + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 85-94 + +如果 ``trial_code_directory`` 是一个相对路径,它被认为相对于当前的工作目录。 +如果您想在其他路径下运行本文件 ``main.py`` ,您可以将代码目录设置为 ``Path(__file__).parent`` 。 +(`__file__ `__ +只能在 py 文件中使用,不能在 Jupyter Notebook 中使用) + +.. attention:: + + 如果您使用 Linux 系统,并且没有使用 Conda, + 您可能需要将 ``"python model.py"`` 改为 ``"python3 model.py"`` 。 + +.. GENERATED FROM PYTHON SOURCE LINES 96-98 + +配置搜索空间 +^^^^^^^^^^^^ + +.. GENERATED FROM PYTHON SOURCE LINES 98-100 + +.. code-block:: default + + experiment.config.search_space = search_space + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 101-104 + +配置调优算法 +^^^^^^^^^^^^ +此处我们使用 :doc:`TPE 算法` 。 + +.. GENERATED FROM PYTHON SOURCE LINES 104-107 + +.. code-block:: default + + experiment.config.tuner.name = 'TPE' + experiment.config.tuner.class_args['optimize_mode'] = 'maximize' + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 108-111 + +配置运行多少 trial +^^^^^^^^^^^^^^^^^^ +本教程中我们总共尝试10组超参,并且每次并行地评估2组超参。 + +.. GENERATED FROM PYTHON SOURCE LINES 111-113 + +.. code-block:: default + + experiment.config.max_trial_number = 10 + experiment.config.trial_concurrency = 2 + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 114-124 + +您也可以设置 ``max_experiment_duration = '1h'`` 来限制运行时间。 + +如果 ``max_trial_number`` 和 ``max_experiment_duration`` 都没有设置,实验将会一直运行,直到您按下 Ctrl-C。 + +.. note:: + + 此处将 ``max_trial_number`` 设置为10是为了让教程能够较快地运行结束, + 在实际使用中应该设为更大的数值,TPE 算法在默认参数下需要评估20组超参才会完成初始化。 + +.. GENERATED FROM PYTHON SOURCE LINES 126-131 + +步骤四:运行实验 +---------------- +现在实验已经配置完成了,您可以指定一个端口来运行它,教程中我们使用8080端口。 + +您可以通过网页控制台查看实验状态: http://localhost:8080. + +.. GENERATED FROM PYTHON SOURCE LINES 131-133 + +.. code-block:: default + + experiment.run(8080) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + [2022-04-13 12:07:29] Creating experiment, Experiment ID: hgkju3iq + [2022-04-13 12:07:29] Starting web server... + [2022-04-13 12:07:30] Setting up... + [2022-04-13 12:07:30] Web portal URLs: http://127.0.0.1:8080 http://192.168.100.103:8080 + + True + + + +.. GENERATED FROM PYTHON SOURCE LINES 134-141 + +实验结束之后 +------------ +您只需要等待函数返回就可以正常结束实验,以下内容为可选项。 + +如果您使用的是普通 Python 而不是 Jupyter Notebook, +您可以在代码末尾加上一行 ``input()`` 或者 ``signal.pause()`` 来避免 Python 解释器自动退出, +这样您就能继续使用网页控制台。 + +.. GENERATED FROM PYTHON SOURCE LINES 141-145 + +.. code-block:: default + + + # input('Press enter to quit') + experiment.stop() + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + [2022-04-13 12:08:50] Stopping experiment, please wait... + [2022-04-13 12:08:53] Experiment stopped + + + + +.. GENERATED FROM PYTHON SOURCE LINES 146-156 + +:meth:`nni.experiment.Experiment.stop` 会在 Python 退出前自动调用,所以您可以将其省略,不写在自己的代码中。 + +实验完全停止之后,您可以使用 :meth:`nni.experiment.Experiment.view` 重新启动网页控制台。 + +.. tip:: + + 本教程使用 :doc:`Python API ` 创建实验, + 除此之外您也可以选择使用 :doc:`命令行工具 <../hpo_nnictl/nnictl>` 。 + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 1 minutes 24.367 seconds) + + +.. _sphx_glr_download_tutorials_hpo_quickstart_pytorch_main.py: + + +.. only :: html + + .. container:: sphx-glr-footer + :class: sphx-glr-footer-example + + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: main.py ` + + + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: main.ipynb ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/hpo_quickstart_pytorch/model.ipynb b/docs/source/tutorials/hpo_quickstart_pytorch/model.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..f1acdfc84cfa733f50d01bde413b0b8813162302 --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_pytorch/model.ipynb @@ -0,0 +1,162 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# Port PyTorch Quickstart to NNI\nThis is a modified version of `PyTorch quickstart`_.\n\nIt can be run directly and will have the exact same result as original version.\n\nFurthermore, it enables the ability of auto tuning with an NNI *experiment*, which will be detailed later.\n\nIt is recommended to run this script directly first to verify the environment.\n\nThere are 2 key differences from the original version:\n\n1. In `Get optimized hyperparameters`_ part, it receives generated hyperparameters.\n2. In `Train model and report accuracy`_ part, it reports accuracy metrics to NNI.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import nni\nimport torch\nfrom torch import nn\nfrom torch.utils.data import DataLoader\nfrom torchvision import datasets\nfrom torchvision.transforms import ToTensor" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Hyperparameters to be tuned\nThese are the hyperparameters that will be tuned.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "params = {\n 'features': 512,\n 'lr': 0.001,\n 'momentum': 0,\n}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Get optimized hyperparameters\nIf run directly, :func:`nni.get_next_parameter` is a no-op and returns an empty dict.\nBut with an NNI *experiment*, it will receive optimized hyperparameters from tuning algorithm.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "optimized_params = nni.get_next_parameter()\nparams.update(optimized_params)\nprint(params)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load dataset\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "training_data = datasets.FashionMNIST(root=\"data\", train=True, download=True, transform=ToTensor())\ntest_data = datasets.FashionMNIST(root=\"data\", train=False, download=True, transform=ToTensor())\n\nbatch_size = 64\n\ntrain_dataloader = DataLoader(training_data, batch_size=batch_size)\ntest_dataloader = DataLoader(test_data, batch_size=batch_size)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Build model with hyperparameters\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\nprint(f\"Using {device} device\")\n\nclass NeuralNetwork(nn.Module):\n def __init__(self):\n super(NeuralNetwork, self).__init__()\n self.flatten = nn.Flatten()\n self.linear_relu_stack = nn.Sequential(\n nn.Linear(28*28, params['features']),\n nn.ReLU(),\n nn.Linear(params['features'], params['features']),\n nn.ReLU(),\n nn.Linear(params['features'], 10)\n )\n\n def forward(self, x):\n x = self.flatten(x)\n logits = self.linear_relu_stack(x)\n return logits\n\nmodel = NeuralNetwork().to(device)\n\nloss_fn = nn.CrossEntropyLoss()\noptimizer = torch.optim.SGD(model.parameters(), lr=params['lr'], momentum=params['momentum'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define train and test\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def train(dataloader, model, loss_fn, optimizer):\n size = len(dataloader.dataset)\n model.train()\n for batch, (X, y) in enumerate(dataloader):\n X, y = X.to(device), y.to(device)\n pred = model(X)\n loss = loss_fn(pred, y)\n optimizer.zero_grad()\n loss.backward()\n optimizer.step()\n\ndef test(dataloader, model, loss_fn):\n size = len(dataloader.dataset)\n num_batches = len(dataloader)\n model.eval()\n test_loss, correct = 0, 0\n with torch.no_grad():\n for X, y in dataloader:\n X, y = X.to(device), y.to(device)\n pred = model(X)\n test_loss += loss_fn(pred, y).item()\n correct += (pred.argmax(1) == y).type(torch.float).sum().item()\n test_loss /= num_batches\n correct /= size\n return correct" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Train model and report accuracy\nReport accuracy metrics to NNI so the tuning algorithm can suggest better hyperparameters.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "epochs = 5\nfor t in range(epochs):\n print(f\"Epoch {t+1}\\n-------------------------------\")\n train(train_dataloader, model, loss_fn, optimizer)\n accuracy = test(test_dataloader, model, loss_fn)\n nni.report_intermediate_result(accuracy)\nnni.report_final_result(accuracy)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.3" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/docs/source/tutorials/hpo_quickstart_pytorch/model.py b/docs/source/tutorials/hpo_quickstart_pytorch/model.py new file mode 100644 index 0000000000000000000000000000000000000000..1bb07bf148e712d0450f8a93a29e9e7d3a9f0814 --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_pytorch/model.py @@ -0,0 +1,125 @@ +""" +Port PyTorch Quickstart to NNI +============================== +This is a modified version of `PyTorch quickstart`_. + +It can be run directly and will have the exact same result as original version. + +Furthermore, it enables the ability of auto tuning with an NNI *experiment*, which will be detailed later. + +It is recommended to run this script directly first to verify the environment. + +There are 2 key differences from the original version: + +1. In `Get optimized hyperparameters`_ part, it receives generated hyperparameters. +2. In `Train model and report accuracy`_ part, it reports accuracy metrics to NNI. + +.. _PyTorch quickstart: https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html +""" + +# %% +import nni +import torch +from torch import nn +from torch.utils.data import DataLoader +from torchvision import datasets +from torchvision.transforms import ToTensor + +# %% +# Hyperparameters to be tuned +# --------------------------- +# These are the hyperparameters that will be tuned. +params = { + 'features': 512, + 'lr': 0.001, + 'momentum': 0, +} + +# %% +# Get optimized hyperparameters +# ----------------------------- +# If run directly, :func:`nni.get_next_parameter` is a no-op and returns an empty dict. +# But with an NNI *experiment*, it will receive optimized hyperparameters from tuning algorithm. +optimized_params = nni.get_next_parameter() +params.update(optimized_params) +print(params) + +# %% +# Load dataset +# ------------ +training_data = datasets.FashionMNIST(root="data", train=True, download=True, transform=ToTensor()) +test_data = datasets.FashionMNIST(root="data", train=False, download=True, transform=ToTensor()) + +batch_size = 64 + +train_dataloader = DataLoader(training_data, batch_size=batch_size) +test_dataloader = DataLoader(test_data, batch_size=batch_size) + +# %% +# Build model with hyperparameters +# -------------------------------- +device = "cuda" if torch.cuda.is_available() else "cpu" +print(f"Using {device} device") + +class NeuralNetwork(nn.Module): + def __init__(self): + super(NeuralNetwork, self).__init__() + self.flatten = nn.Flatten() + self.linear_relu_stack = nn.Sequential( + nn.Linear(28*28, params['features']), + nn.ReLU(), + nn.Linear(params['features'], params['features']), + nn.ReLU(), + nn.Linear(params['features'], 10) + ) + + def forward(self, x): + x = self.flatten(x) + logits = self.linear_relu_stack(x) + return logits + +model = NeuralNetwork().to(device) + +loss_fn = nn.CrossEntropyLoss() +optimizer = torch.optim.SGD(model.parameters(), lr=params['lr'], momentum=params['momentum']) + +# %% +# Define train and test +# --------------------- +def train(dataloader, model, loss_fn, optimizer): + size = len(dataloader.dataset) + model.train() + for batch, (X, y) in enumerate(dataloader): + X, y = X.to(device), y.to(device) + pred = model(X) + loss = loss_fn(pred, y) + optimizer.zero_grad() + loss.backward() + optimizer.step() + +def test(dataloader, model, loss_fn): + size = len(dataloader.dataset) + num_batches = len(dataloader) + model.eval() + test_loss, correct = 0, 0 + with torch.no_grad(): + for X, y in dataloader: + X, y = X.to(device), y.to(device) + pred = model(X) + test_loss += loss_fn(pred, y).item() + correct += (pred.argmax(1) == y).type(torch.float).sum().item() + test_loss /= num_batches + correct /= size + return correct + +# %% +# Train model and report accuracy +# ------------------------------- +# Report accuracy metrics to NNI so the tuning algorithm can suggest better hyperparameters. +epochs = 5 +for t in range(epochs): + print(f"Epoch {t+1}\n-------------------------------") + train(train_dataloader, model, loss_fn, optimizer) + accuracy = test(test_dataloader, model, loss_fn) + nni.report_intermediate_result(accuracy) +nni.report_final_result(accuracy) diff --git a/docs/source/tutorials/hpo_quickstart_pytorch/model.py.md5 b/docs/source/tutorials/hpo_quickstart_pytorch/model.py.md5 new file mode 100644 index 0000000000000000000000000000000000000000..4559246a46ee2117cab8a12000e5d39683b0e633 --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_pytorch/model.py.md5 @@ -0,0 +1 @@ +ed8bfc27e3d555d842fc4eec2635e619 \ No newline at end of file diff --git a/docs/source/tutorials/hpo_quickstart_pytorch/model.rst b/docs/source/tutorials/hpo_quickstart_pytorch/model.rst new file mode 100644 index 0000000000000000000000000000000000000000..fde392d32846e05bb9bce746f967ac5dd0a61860 --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_pytorch/model.rst @@ -0,0 +1,303 @@ +:orphan: + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "tutorials/hpo_quickstart_pytorch/model.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_tutorials_hpo_quickstart_pytorch_model.py: + + +Port PyTorch Quickstart to NNI +============================== +This is a modified version of `PyTorch quickstart`_. + +It can be run directly and will have the exact same result as original version. + +Furthermore, it enables the ability of auto tuning with an NNI *experiment*, which will be detailed later. + +It is recommended to run this script directly first to verify the environment. + +There are 2 key differences from the original version: + +1. In `Get optimized hyperparameters`_ part, it receives generated hyperparameters. +2. In `Train model and report accuracy`_ part, it reports accuracy metrics to NNI. + +.. _PyTorch quickstart: https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html + +.. GENERATED FROM PYTHON SOURCE LINES 21-28 + +.. code-block:: default + + import nni + import torch + from torch import nn + from torch.utils.data import DataLoader + from torchvision import datasets + from torchvision.transforms import ToTensor + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 29-32 + +Hyperparameters to be tuned +--------------------------- +These are the hyperparameters that will be tuned. + +.. GENERATED FROM PYTHON SOURCE LINES 32-38 + +.. code-block:: default + + params = { + 'features': 512, + 'lr': 0.001, + 'momentum': 0, + } + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 39-43 + +Get optimized hyperparameters +----------------------------- +If run directly, :func:`nni.get_next_parameter` is a no-op and returns an empty dict. +But with an NNI *experiment*, it will receive optimized hyperparameters from tuning algorithm. + +.. GENERATED FROM PYTHON SOURCE LINES 43-47 + +.. code-block:: default + + optimized_params = nni.get_next_parameter() + params.update(optimized_params) + print(params) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + {'features': 512, 'lr': 0.001, 'momentum': 0} + + + + +.. GENERATED FROM PYTHON SOURCE LINES 48-50 + +Load dataset +------------ + +.. GENERATED FROM PYTHON SOURCE LINES 50-58 + +.. code-block:: default + + training_data = datasets.FashionMNIST(root="data", train=True, download=True, transform=ToTensor()) + test_data = datasets.FashionMNIST(root="data", train=False, download=True, transform=ToTensor()) + + batch_size = 64 + + train_dataloader = DataLoader(training_data, batch_size=batch_size) + test_dataloader = DataLoader(test_data, batch_size=batch_size) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 59-61 + +Build model with hyperparameters +-------------------------------- + +.. GENERATED FROM PYTHON SOURCE LINES 61-86 + +.. code-block:: default + + device = "cuda" if torch.cuda.is_available() else "cpu" + print(f"Using {device} device") + + class NeuralNetwork(nn.Module): + def __init__(self): + super(NeuralNetwork, self).__init__() + self.flatten = nn.Flatten() + self.linear_relu_stack = nn.Sequential( + nn.Linear(28*28, params['features']), + nn.ReLU(), + nn.Linear(params['features'], params['features']), + nn.ReLU(), + nn.Linear(params['features'], 10) + ) + + def forward(self, x): + x = self.flatten(x) + logits = self.linear_relu_stack(x) + return logits + + model = NeuralNetwork().to(device) + + loss_fn = nn.CrossEntropyLoss() + optimizer = torch.optim.SGD(model.parameters(), lr=params['lr'], momentum=params['momentum']) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + Using cpu device + + + + +.. GENERATED FROM PYTHON SOURCE LINES 87-89 + +Define train and test +--------------------- + +.. GENERATED FROM PYTHON SOURCE LINES 89-115 + +.. code-block:: default + + def train(dataloader, model, loss_fn, optimizer): + size = len(dataloader.dataset) + model.train() + for batch, (X, y) in enumerate(dataloader): + X, y = X.to(device), y.to(device) + pred = model(X) + loss = loss_fn(pred, y) + optimizer.zero_grad() + loss.backward() + optimizer.step() + + def test(dataloader, model, loss_fn): + size = len(dataloader.dataset) + num_batches = len(dataloader) + model.eval() + test_loss, correct = 0, 0 + with torch.no_grad(): + for X, y in dataloader: + X, y = X.to(device), y.to(device) + pred = model(X) + test_loss += loss_fn(pred, y).item() + correct += (pred.argmax(1) == y).type(torch.float).sum().item() + test_loss /= num_batches + correct /= size + return correct + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 116-119 + +Train model and report accuracy +------------------------------- +Report accuracy metrics to NNI so the tuning algorithm can suggest better hyperparameters. + +.. GENERATED FROM PYTHON SOURCE LINES 119-126 + +.. code-block:: default + + epochs = 5 + for t in range(epochs): + print(f"Epoch {t+1}\n-------------------------------") + train(train_dataloader, model, loss_fn, optimizer) + accuracy = test(test_dataloader, model, loss_fn) + nni.report_intermediate_result(accuracy) + nni.report_final_result(accuracy) + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + Epoch 1 + ------------------------------- + [2022-03-21 01:09:37] INFO (nni/MainThread) Intermediate result: 0.461 (Index 0) + Epoch 2 + ------------------------------- + [2022-03-21 01:09:42] INFO (nni/MainThread) Intermediate result: 0.5529 (Index 1) + Epoch 3 + ------------------------------- + [2022-03-21 01:09:47] INFO (nni/MainThread) Intermediate result: 0.6155 (Index 2) + Epoch 4 + ------------------------------- + [2022-03-21 01:09:52] INFO (nni/MainThread) Intermediate result: 0.6345 (Index 3) + Epoch 5 + ------------------------------- + [2022-03-21 01:09:56] INFO (nni/MainThread) Intermediate result: 0.6505 (Index 4) + [2022-03-21 01:09:56] INFO (nni/MainThread) Final result: 0.6505 + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 24.441 seconds) + + +.. _sphx_glr_download_tutorials_hpo_quickstart_pytorch_model.py: + + +.. only :: html + + .. container:: sphx-glr-footer + :class: sphx-glr-footer-example + + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: model.py ` + + + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: model.ipynb ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/hpo_quickstart_pytorch/model_codeobj.pickle b/docs/source/tutorials/hpo_quickstart_pytorch/model_codeobj.pickle new file mode 100644 index 0000000000000000000000000000000000000000..a3c2703b82cc3d598535e1496393fb9933b3e58c Binary files /dev/null and b/docs/source/tutorials/hpo_quickstart_pytorch/model_codeobj.pickle differ diff --git a/docs/source/tutorials/hpo_quickstart_pytorch/model_zh.rst b/docs/source/tutorials/hpo_quickstart_pytorch/model_zh.rst new file mode 100644 index 0000000000000000000000000000000000000000..5ec045658b7c5cdc8f0941d684023408e8c04ae1 --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_pytorch/model_zh.rst @@ -0,0 +1,300 @@ +.. e083b4dc8e350428ddf680e97b47cc8e + +:orphan: + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "tutorials/hpo_quickstart_pytorch/model.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_tutorials_hpo_quickstart_pytorch_model.py: + +将 PyTorch 官方教程移植到NNI +============================ +本文件是 `PyTorch 官方教程 `__ 的修改版。 + +您可以直接运行本文件,其结果和原版完全一致。同时,您也可以在 NNI 实验中使用本文件,进行超参调优。 + +我们建议您先直接运行一次本文件,在熟悉代码的同时检查运行环境。 + +和原版相比,我们做了两处修改: + +1. 在 `获取调优后的参数`_ 部分,我们使用调优算法生成的参数替换默认参数; +2. 在 `训练模型并上传结果`_ 部分,我们将准确率数据报告给 NNI。 + +.. GENERATED FROM PYTHON SOURCE LINES 21-28 + +.. code-block:: default + + import nni + import torch + from torch import nn + from torch.utils.data import DataLoader + from torchvision import datasets + from torchvision.transforms import ToTensor + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 29-32 + +准备调优的超参 +-------------- +以下超参将被调优: + +.. GENERATED FROM PYTHON SOURCE LINES 32-38 + +.. code-block:: default + + params = { + 'features': 512, + 'lr': 0.001, + 'momentum': 0, + } + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 39-43 + +获取调优后的参数 +---------------- +直接运行时 :func:`nni.get_next_parameter` 会返回空 dict, +而在 NNI 实验中使用时,它会返回调优算法生成的超参组合。 + +.. GENERATED FROM PYTHON SOURCE LINES 43-47 + +.. code-block:: default + + optimized_params = nni.get_next_parameter() + params.update(optimized_params) + print(params) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + {'features': 512, 'lr': 0.001, 'momentum': 0} + + + + +.. GENERATED FROM PYTHON SOURCE LINES 48-50 + +加载数据集 +---------- + +.. GENERATED FROM PYTHON SOURCE LINES 50-58 + +.. code-block:: default + + training_data = datasets.FashionMNIST(root="data", train=True, download=True, transform=ToTensor()) + test_data = datasets.FashionMNIST(root="data", train=False, download=True, transform=ToTensor()) + + batch_size = 64 + + train_dataloader = DataLoader(training_data, batch_size=batch_size) + test_dataloader = DataLoader(test_data, batch_size=batch_size) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 59-61 + +使用超参构建模型 +---------------- + +.. GENERATED FROM PYTHON SOURCE LINES 61-86 + +.. code-block:: default + + device = "cuda" if torch.cuda.is_available() else "cpu" + print(f"Using {device} device") + + class NeuralNetwork(nn.Module): + def __init__(self): + super(NeuralNetwork, self).__init__() + self.flatten = nn.Flatten() + self.linear_relu_stack = nn.Sequential( + nn.Linear(28*28, params['features']), + nn.ReLU(), + nn.Linear(params['features'], params['features']), + nn.ReLU(), + nn.Linear(params['features'], 10) + ) + + def forward(self, x): + x = self.flatten(x) + logits = self.linear_relu_stack(x) + return logits + + model = NeuralNetwork().to(device) + + loss_fn = nn.CrossEntropyLoss() + optimizer = torch.optim.SGD(model.parameters(), lr=params['lr'], momentum=params['momentum']) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + Using cpu device + + + + +.. GENERATED FROM PYTHON SOURCE LINES 87-89 + +定义训练和测试函数 +------------------ + +.. GENERATED FROM PYTHON SOURCE LINES 89-115 + +.. code-block:: default + + def train(dataloader, model, loss_fn, optimizer): + size = len(dataloader.dataset) + model.train() + for batch, (X, y) in enumerate(dataloader): + X, y = X.to(device), y.to(device) + pred = model(X) + loss = loss_fn(pred, y) + optimizer.zero_grad() + loss.backward() + optimizer.step() + + def test(dataloader, model, loss_fn): + size = len(dataloader.dataset) + num_batches = len(dataloader) + model.eval() + test_loss, correct = 0, 0 + with torch.no_grad(): + for X, y in dataloader: + X, y = X.to(device), y.to(device) + pred = model(X) + test_loss += loss_fn(pred, y).item() + correct += (pred.argmax(1) == y).type(torch.float).sum().item() + test_loss /= num_batches + correct /= size + return correct + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 116-119 + +训练模型并上传结果 +------------------ +将准确率数据报告给 NNI 的调参算法,以使其能够预测更优的超参组合。 + +.. GENERATED FROM PYTHON SOURCE LINES 119-126 + +.. code-block:: default + + epochs = 5 + for t in range(epochs): + print(f"Epoch {t+1}\n-------------------------------") + train(train_dataloader, model, loss_fn, optimizer) + accuracy = test(test_dataloader, model, loss_fn) + nni.report_intermediate_result(accuracy) + nni.report_final_result(accuracy) + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + Epoch 1 + ------------------------------- + [2022-03-21 01:09:37] INFO (nni/MainThread) Intermediate result: 0.461 (Index 0) + Epoch 2 + ------------------------------- + [2022-03-21 01:09:42] INFO (nni/MainThread) Intermediate result: 0.5529 (Index 1) + Epoch 3 + ------------------------------- + [2022-03-21 01:09:47] INFO (nni/MainThread) Intermediate result: 0.6155 (Index 2) + Epoch 4 + ------------------------------- + [2022-03-21 01:09:52] INFO (nni/MainThread) Intermediate result: 0.6345 (Index 3) + Epoch 5 + ------------------------------- + [2022-03-21 01:09:56] INFO (nni/MainThread) Intermediate result: 0.6505 (Index 4) + [2022-03-21 01:09:56] INFO (nni/MainThread) Final result: 0.6505 + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 24.441 seconds) + + +.. _sphx_glr_download_tutorials_hpo_quickstart_pytorch_model.py: + + +.. only :: html + + .. container:: sphx-glr-footer + :class: sphx-glr-footer-example + + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: model.py ` + + + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: model.ipynb ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/hpo_quickstart_pytorch/sg_execution_times.rst b/docs/source/tutorials/hpo_quickstart_pytorch/sg_execution_times.rst new file mode 100644 index 0000000000000000000000000000000000000000..95fbbb04684618cea64e44ba33ae5babd0eb7b6c --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_pytorch/sg_execution_times.rst @@ -0,0 +1,14 @@ + +:orphan: + +.. _sphx_glr_tutorials_hpo_quickstart_pytorch_sg_execution_times: + +Computation times +================= +**01:24.367** total execution time for **tutorials_hpo_quickstart_pytorch** files: + ++--------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_tutorials_hpo_quickstart_pytorch_main.py` (``main.py``) | 01:24.367 | 0.0 MB | ++--------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_tutorials_hpo_quickstart_pytorch_model.py` (``model.py``) | 00:00.000 | 0.0 MB | ++--------------------------------------------------------------------------+-----------+--------+ diff --git a/docs/source/tutorials/hpo_quickstart_tensorflow/images/thumb/sphx_glr_main_thumb.png b/docs/source/tutorials/hpo_quickstart_tensorflow/images/thumb/sphx_glr_main_thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..b06c4e6a17748efb9e7d009eb1e161759cfa2b74 Binary files /dev/null and b/docs/source/tutorials/hpo_quickstart_tensorflow/images/thumb/sphx_glr_main_thumb.png differ diff --git a/docs/source/tutorials/hpo_quickstart_tensorflow/images/thumb/sphx_glr_model_thumb.png b/docs/source/tutorials/hpo_quickstart_tensorflow/images/thumb/sphx_glr_model_thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..b06c4e6a17748efb9e7d009eb1e161759cfa2b74 Binary files /dev/null and b/docs/source/tutorials/hpo_quickstart_tensorflow/images/thumb/sphx_glr_model_thumb.png differ diff --git a/docs/source/tutorials/hpo_quickstart_tensorflow/main.ipynb b/docs/source/tutorials/hpo_quickstart_tensorflow/main.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..98982659f0c40b35763dd077e032d807f2b414e0 --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_tensorflow/main.ipynb @@ -0,0 +1,215 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# HPO Quickstart with TensorFlow\nThis tutorial optimizes the model in `official TensorFlow quickstart`_ with auto-tuning.\n\nThe tutorial consists of 4 steps: \n\n1. Modify the model for auto-tuning.\n2. Define hyperparameters' search space.\n3. Configure the experiment.\n4. Run the experiment.\n\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 1: Prepare the model\nIn first step, we need to prepare the model to be tuned.\n\nThe model should be put in a separate script.\nIt will be evaluated many times concurrently,\nand possibly will be trained on distributed platforms.\n\nIn this tutorial, the model is defined in :doc:`model.py `.\n\nIn short, it is a TensorFlow model with 3 additional API calls:\n\n1. Use :func:`nni.get_next_parameter` to fetch the hyperparameters to be evalutated.\n2. Use :func:`nni.report_intermediate_result` to report per-epoch accuracy metrics.\n3. Use :func:`nni.report_final_result` to report final accuracy.\n\nPlease understand the model code before continue to next step.\n\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 2: Define search space\nIn model code, we have prepared 4 hyperparameters to be tuned:\n*dense_units*, *activation_type*, *dropout_rate*, and *learning_rate*.\n\nHere we need to define their *search space* so the tuning algorithm can sample them in desired range.\n\nAssuming we have following prior knowledge for these hyperparameters:\n\n1. *dense_units* should be one of 64, 128, 256.\n2. *activation_type* should be one of 'relu', 'tanh', 'swish', or None.\n3. *dropout_rate* should be a float between 0.5 and 0.9.\n4. *learning_rate* should be a float between 0.0001 and 0.1, and it follows exponential distribution.\n\nIn NNI, the space of *dense_units* and *activation_type* is called ``choice``;\nthe space of *dropout_rate* is called ``uniform``;\nand the space of *learning_rate* is called ``loguniform``.\nYou may have noticed, these names are derived from ``numpy.random``.\n\nFor full specification of search space, check :doc:`the reference `.\n\nNow we can define the search space as follow:\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "search_space = {\n 'dense_units': {'_type': 'choice', '_value': [64, 128, 256]},\n 'activation_type': {'_type': 'choice', '_value': ['relu', 'tanh', 'swish', None]},\n 'dropout_rate': {'_type': 'uniform', '_value': [0.5, 0.9]},\n 'learning_rate': {'_type': 'loguniform', '_value': [0.0001, 0.1]},\n}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 3: Configure the experiment\nNNI uses an *experiment* to manage the HPO process.\nThe *experiment config* defines how to train the models and how to explore the search space.\n\nIn this tutorial we use a *local* mode experiment,\nwhich means models will be trained on local machine, without using any special training platform.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from nni.experiment import Experiment\nexperiment = Experiment('local')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we start to configure the experiment.\n\n### Configure trial code\nIn NNI evaluation of each hyperparameter set is called a *trial*.\nSo the model script is called *trial code*.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "experiment.config.trial_command = 'python model.py'\nexperiment.config.trial_code_directory = '.'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When ``trial_code_directory`` is a relative path, it relates to current working directory.\nTo run ``main.py`` in a different path, you can set trial code directory to ``Path(__file__).parent``.\n(`__file__ `__\nis only available in standard Python, not in Jupyter Notebook.)\n\n.. attention::\n\n If you are using Linux system without Conda,\n you may need to change ``\"python model.py\"`` to ``\"python3 model.py\"``.\n\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Configure search space\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "experiment.config.search_space = search_space" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Configure tuning algorithm\nHere we use :doc:`TPE tuner `.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "experiment.config.tuner.name = 'TPE'\nexperiment.config.tuner.class_args['optimize_mode'] = 'maximize'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Configure how many trials to run\nHere we evaluate 10 sets of hyperparameters in total, and concurrently evaluate 2 sets at a time.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "experiment.config.max_trial_number = 10\nexperiment.config.trial_concurrency = 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You may also set ``max_experiment_duration = '1h'`` to limit running time.\n\nIf neither ``max_trial_number`` nor ``max_experiment_duration`` are set,\nthe experiment will run forever until you press Ctrl-C.\n\n

Note

``max_trial_number`` is set to 10 here for a fast example.\n In real world it should be set to a larger number.\n With default config TPE tuner requires 20 trials to warm up.

\n\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 4: Run the experiment\nNow the experiment is ready. Choose a port and launch it. (Here we use port 8080.)\n\nYou can use the web portal to view experiment status: http://localhost:8080.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "experiment.run(8080)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## After the experiment is done\nEverything is done and it is safe to exit now. The following are optional.\n\nIf you are using standard Python instead of Jupyter Notebook,\nyou can add ``input()`` or ``signal.pause()`` to prevent Python from exiting,\nallowing you to view the web portal after the experiment is done.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# input('Press enter to quit')\nexperiment.stop()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + ":meth:`nni.experiment.Experiment.stop` is automatically invoked when Python exits,\nso it can be omitted in your code.\n\nAfter the experiment is stopped, you can run :meth:`nni.experiment.Experiment.view` to restart web portal.\n\n.. tip::\n\n This example uses :doc:`Python API ` to create experiment.\n\n You can also create and manage experiments with :doc:`command line tool <../hpo_nnictl/nnictl>`.\n\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/docs/source/tutorials/hpo_quickstart_tensorflow/main.py b/docs/source/tutorials/hpo_quickstart_tensorflow/main.py new file mode 100644 index 0000000000000000000000000000000000000000..9413ba5e312d0967a6a3c6b1bebf72c2fb90aa1d --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_tensorflow/main.py @@ -0,0 +1,157 @@ +""" +HPO Quickstart with TensorFlow +============================== +This tutorial optimizes the model in `official TensorFlow quickstart`_ with auto-tuning. + +The tutorial consists of 4 steps: + +1. Modify the model for auto-tuning. +2. Define hyperparameters' search space. +3. Configure the experiment. +4. Run the experiment. + +.. _official TensorFlow quickstart: https://www.tensorflow.org/tutorials/quickstart/beginner +""" + +# %% +# Step 1: Prepare the model +# ------------------------- +# In first step, we need to prepare the model to be tuned. +# +# The model should be put in a separate script. +# It will be evaluated many times concurrently, +# and possibly will be trained on distributed platforms. +# +# In this tutorial, the model is defined in :doc:`model.py `. +# +# In short, it is a TensorFlow model with 3 additional API calls: +# +# 1. Use :func:`nni.get_next_parameter` to fetch the hyperparameters to be evalutated. +# 2. Use :func:`nni.report_intermediate_result` to report per-epoch accuracy metrics. +# 3. Use :func:`nni.report_final_result` to report final accuracy. +# +# Please understand the model code before continue to next step. + +# %% +# Step 2: Define search space +# --------------------------- +# In model code, we have prepared 4 hyperparameters to be tuned: +# *dense_units*, *activation_type*, *dropout_rate*, and *learning_rate*. +# +# Here we need to define their *search space* so the tuning algorithm can sample them in desired range. +# +# Assuming we have following prior knowledge for these hyperparameters: +# +# 1. *dense_units* should be one of 64, 128, 256. +# 2. *activation_type* should be one of 'relu', 'tanh', 'swish', or None. +# 3. *dropout_rate* should be a float between 0.5 and 0.9. +# 4. *learning_rate* should be a float between 0.0001 and 0.1, and it follows exponential distribution. +# +# In NNI, the space of *dense_units* and *activation_type* is called ``choice``; +# the space of *dropout_rate* is called ``uniform``; +# and the space of *learning_rate* is called ``loguniform``. +# You may have noticed, these names are derived from ``numpy.random``. +# +# For full specification of search space, check :doc:`the reference `. +# +# Now we can define the search space as follow: + +search_space = { + 'dense_units': {'_type': 'choice', '_value': [64, 128, 256]}, + 'activation_type': {'_type': 'choice', '_value': ['relu', 'tanh', 'swish', None]}, + 'dropout_rate': {'_type': 'uniform', '_value': [0.5, 0.9]}, + 'learning_rate': {'_type': 'loguniform', '_value': [0.0001, 0.1]}, +} + +# %% +# Step 3: Configure the experiment +# -------------------------------- +# NNI uses an *experiment* to manage the HPO process. +# The *experiment config* defines how to train the models and how to explore the search space. +# +# In this tutorial we use a *local* mode experiment, +# which means models will be trained on local machine, without using any special training platform. +from nni.experiment import Experiment +experiment = Experiment('local') + +# %% +# Now we start to configure the experiment. +# +# Configure trial code +# ^^^^^^^^^^^^^^^^^^^^ +# In NNI evaluation of each hyperparameter set is called a *trial*. +# So the model script is called *trial code*. +experiment.config.trial_command = 'python model.py' +experiment.config.trial_code_directory = '.' +# %% +# When ``trial_code_directory`` is a relative path, it relates to current working directory. +# To run ``main.py`` in a different path, you can set trial code directory to ``Path(__file__).parent``. +# (`__file__ `__ +# is only available in standard Python, not in Jupyter Notebook.) +# +# .. attention:: +# +# If you are using Linux system without Conda, +# you may need to change ``"python model.py"`` to ``"python3 model.py"``. + +# %% +# Configure search space +# ^^^^^^^^^^^^^^^^^^^^^^ +experiment.config.search_space = search_space + +# %% +# Configure tuning algorithm +# ^^^^^^^^^^^^^^^^^^^^^^^^^^ +# Here we use :doc:`TPE tuner `. +experiment.config.tuner.name = 'TPE' +experiment.config.tuner.class_args['optimize_mode'] = 'maximize' + +# %% +# Configure how many trials to run +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# Here we evaluate 10 sets of hyperparameters in total, and concurrently evaluate 2 sets at a time. +experiment.config.max_trial_number = 10 +experiment.config.trial_concurrency = 2 +# %% +# You may also set ``max_experiment_duration = '1h'`` to limit running time. +# +# If neither ``max_trial_number`` nor ``max_experiment_duration`` are set, +# the experiment will run forever until you press Ctrl-C. +# +# .. note:: +# +# ``max_trial_number`` is set to 10 here for a fast example. +# In real world it should be set to a larger number. +# With default config TPE tuner requires 20 trials to warm up. + +# %% +# Step 4: Run the experiment +# -------------------------- +# Now the experiment is ready. Choose a port and launch it. (Here we use port 8080.) +# +# You can use the web portal to view experiment status: http://localhost:8080. +experiment.run(8080) + +# %% +# After the experiment is done +# ---------------------------- +# Everything is done and it is safe to exit now. The following are optional. +# +# If you are using standard Python instead of Jupyter Notebook, +# you can add ``input()`` or ``signal.pause()`` to prevent Python from exiting, +# allowing you to view the web portal after the experiment is done. + +# input('Press enter to quit') +experiment.stop() + +# %% +# :meth:`nni.experiment.Experiment.stop` is automatically invoked when Python exits, +# so it can be omitted in your code. +# +# After the experiment is stopped, you can run :meth:`nni.experiment.Experiment.view` to restart web portal. +# +# .. tip:: +# +# This example uses :doc:`Python API ` to create experiment. +# +# You can also create and manage experiments with :doc:`command line tool <../hpo_nnictl/nnictl>`. diff --git a/docs/source/tutorials/hpo_quickstart_tensorflow/main.py.md5 b/docs/source/tutorials/hpo_quickstart_tensorflow/main.py.md5 new file mode 100644 index 0000000000000000000000000000000000000000..eebd9825494e9e93eed3693e8b2ccb2e62f0dc0d --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_tensorflow/main.py.md5 @@ -0,0 +1 @@ +b8a9880a36233005ade7a8dae6d428a8 \ No newline at end of file diff --git a/docs/source/tutorials/hpo_quickstart_tensorflow/main.rst b/docs/source/tutorials/hpo_quickstart_tensorflow/main.rst new file mode 100644 index 0000000000000000000000000000000000000000..39dded2a1ff8c07dde256d439b683a2010b52a95 --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_tensorflow/main.rst @@ -0,0 +1,337 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "tutorials/hpo_quickstart_tensorflow/main.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_tutorials_hpo_quickstart_tensorflow_main.py: + + +HPO Quickstart with TensorFlow +============================== +This tutorial optimizes the model in `official TensorFlow quickstart`_ with auto-tuning. + +The tutorial consists of 4 steps: + +1. Modify the model for auto-tuning. +2. Define hyperparameters' search space. +3. Configure the experiment. +4. Run the experiment. + +.. _official TensorFlow quickstart: https://www.tensorflow.org/tutorials/quickstart/beginner + +.. GENERATED FROM PYTHON SOURCE LINES 17-34 + +Step 1: Prepare the model +------------------------- +In first step, we need to prepare the model to be tuned. + +The model should be put in a separate script. +It will be evaluated many times concurrently, +and possibly will be trained on distributed platforms. + +In this tutorial, the model is defined in :doc:`model.py `. + +In short, it is a TensorFlow model with 3 additional API calls: + +1. Use :func:`nni.get_next_parameter` to fetch the hyperparameters to be evalutated. +2. Use :func:`nni.report_intermediate_result` to report per-epoch accuracy metrics. +3. Use :func:`nni.report_final_result` to report final accuracy. + +Please understand the model code before continue to next step. + +.. GENERATED FROM PYTHON SOURCE LINES 36-58 + +Step 2: Define search space +--------------------------- +In model code, we have prepared 4 hyperparameters to be tuned: +*dense_units*, *activation_type*, *dropout_rate*, and *learning_rate*. + +Here we need to define their *search space* so the tuning algorithm can sample them in desired range. + +Assuming we have following prior knowledge for these hyperparameters: + +1. *dense_units* should be one of 64, 128, 256. +2. *activation_type* should be one of 'relu', 'tanh', 'swish', or None. +3. *dropout_rate* should be a float between 0.5 and 0.9. +4. *learning_rate* should be a float between 0.0001 and 0.1, and it follows exponential distribution. + +In NNI, the space of *dense_units* and *activation_type* is called ``choice``; +the space of *dropout_rate* is called ``uniform``; +and the space of *learning_rate* is called ``loguniform``. +You may have noticed, these names are derived from ``numpy.random``. + +For full specification of search space, check :doc:`the reference `. + +Now we can define the search space as follow: + +.. GENERATED FROM PYTHON SOURCE LINES 58-66 + +.. code-block:: default + + + search_space = { + 'dense_units': {'_type': 'choice', '_value': [64, 128, 256]}, + 'activation_type': {'_type': 'choice', '_value': ['relu', 'tanh', 'swish', None]}, + 'dropout_rate': {'_type': 'uniform', '_value': [0.5, 0.9]}, + 'learning_rate': {'_type': 'loguniform', '_value': [0.0001, 0.1]}, + } + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 67-74 + +Step 3: Configure the experiment +-------------------------------- +NNI uses an *experiment* to manage the HPO process. +The *experiment config* defines how to train the models and how to explore the search space. + +In this tutorial we use a *local* mode experiment, +which means models will be trained on local machine, without using any special training platform. + +.. GENERATED FROM PYTHON SOURCE LINES 74-77 + +.. code-block:: default + + from nni.experiment import Experiment + experiment = Experiment('local') + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 78-84 + +Now we start to configure the experiment. + +Configure trial code +^^^^^^^^^^^^^^^^^^^^ +In NNI evaluation of each hyperparameter set is called a *trial*. +So the model script is called *trial code*. + +.. GENERATED FROM PYTHON SOURCE LINES 84-86 + +.. code-block:: default + + experiment.config.trial_command = 'python model.py' + experiment.config.trial_code_directory = '.' + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 87-96 + +When ``trial_code_directory`` is a relative path, it relates to current working directory. +To run ``main.py`` in a different path, you can set trial code directory to ``Path(__file__).parent``. +(`__file__ `__ +is only available in standard Python, not in Jupyter Notebook.) + +.. attention:: + + If you are using Linux system without Conda, + you may need to change ``"python model.py"`` to ``"python3 model.py"``. + +.. GENERATED FROM PYTHON SOURCE LINES 98-100 + +Configure search space +^^^^^^^^^^^^^^^^^^^^^^ + +.. GENERATED FROM PYTHON SOURCE LINES 100-102 + +.. code-block:: default + + experiment.config.search_space = search_space + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 103-106 + +Configure tuning algorithm +^^^^^^^^^^^^^^^^^^^^^^^^^^ +Here we use :doc:`TPE tuner `. + +.. GENERATED FROM PYTHON SOURCE LINES 106-109 + +.. code-block:: default + + experiment.config.tuner.name = 'TPE' + experiment.config.tuner.class_args['optimize_mode'] = 'maximize' + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 110-113 + +Configure how many trials to run +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Here we evaluate 10 sets of hyperparameters in total, and concurrently evaluate 2 sets at a time. + +.. GENERATED FROM PYTHON SOURCE LINES 113-115 + +.. code-block:: default + + experiment.config.max_trial_number = 10 + experiment.config.trial_concurrency = 2 + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 116-126 + +You may also set ``max_experiment_duration = '1h'`` to limit running time. + +If neither ``max_trial_number`` nor ``max_experiment_duration`` are set, +the experiment will run forever until you press Ctrl-C. + +.. note:: + + ``max_trial_number`` is set to 10 here for a fast example. + In real world it should be set to a larger number. + With default config TPE tuner requires 20 trials to warm up. + +.. GENERATED FROM PYTHON SOURCE LINES 128-133 + +Step 4: Run the experiment +-------------------------- +Now the experiment is ready. Choose a port and launch it. (Here we use port 8080.) + +You can use the web portal to view experiment status: http://localhost:8080. + +.. GENERATED FROM PYTHON SOURCE LINES 133-135 + +.. code-block:: default + + experiment.run(8080) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + [2022-04-13 12:11:34] Creating experiment, Experiment ID: enw27qxj + [2022-04-13 12:11:34] Starting web server... + [2022-04-13 12:11:35] Setting up... + [2022-04-13 12:11:35] Web portal URLs: http://127.0.0.1:8080 http://192.168.100.103:8080 + + True + + + +.. GENERATED FROM PYTHON SOURCE LINES 136-143 + +After the experiment is done +---------------------------- +Everything is done and it is safe to exit now. The following are optional. + +If you are using standard Python instead of Jupyter Notebook, +you can add ``input()`` or ``signal.pause()`` to prevent Python from exiting, +allowing you to view the web portal after the experiment is done. + +.. GENERATED FROM PYTHON SOURCE LINES 143-147 + +.. code-block:: default + + + # input('Press enter to quit') + experiment.stop() + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + [2022-04-13 12:12:55] Stopping experiment, please wait... + [2022-04-13 12:12:58] Experiment stopped + + + + +.. GENERATED FROM PYTHON SOURCE LINES 148-158 + +:meth:`nni.experiment.Experiment.stop` is automatically invoked when Python exits, +so it can be omitted in your code. + +After the experiment is stopped, you can run :meth:`nni.experiment.Experiment.view` to restart web portal. + +.. tip:: + + This example uses :doc:`Python API ` to create experiment. + + You can also create and manage experiments with :doc:`command line tool <../hpo_nnictl/nnictl>`. + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 1 minutes 24.384 seconds) + + +.. _sphx_glr_download_tutorials_hpo_quickstart_tensorflow_main.py: + + +.. only :: html + + .. container:: sphx-glr-footer + :class: sphx-glr-footer-example + + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: main.py ` + + + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: main.ipynb ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/hpo_quickstart_tensorflow/main_codeobj.pickle b/docs/source/tutorials/hpo_quickstart_tensorflow/main_codeobj.pickle new file mode 100644 index 0000000000000000000000000000000000000000..3b14701367d48087415f613c2b674fcfd217039d Binary files /dev/null and b/docs/source/tutorials/hpo_quickstart_tensorflow/main_codeobj.pickle differ diff --git a/docs/source/tutorials/hpo_quickstart_tensorflow/model.ipynb b/docs/source/tutorials/hpo_quickstart_tensorflow/model.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..16fb6e59de10fa989efe0ffff66103dbd4c31fb4 --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_tensorflow/model.ipynb @@ -0,0 +1,180 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# Port TensorFlow Quickstart to NNI\nThis is a modified version of `TensorFlow quickstart`_.\n\nIt can be run directly and will have the exact same result as original version.\n\nFurthermore, it enables the ability of auto tuning with an NNI *experiment*, which will be detailed later.\n\nIt is recommended to run this script directly first to verify the environment.\n\nThere are 3 key differences from the original version:\n\n1. In `Get optimized hyperparameters`_ part, it receives generated hyperparameters.\n2. In `(Optional) Report intermediate results`_ part, it reports per-epoch accuracy metrics.\n3. In `Report final result`_ part, it reports final accuracy.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import nni\nimport tensorflow as tf" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Hyperparameters to be tuned\nThese are the hyperparameters that will be tuned later.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "params = {\n 'dense_units': 128,\n 'activation_type': 'relu',\n 'dropout_rate': 0.2,\n 'learning_rate': 0.001,\n}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Get optimized hyperparameters\nIf run directly, :func:`nni.get_next_parameter` is a no-op and returns an empty dict.\nBut with an NNI *experiment*, it will receive optimized hyperparameters from tuning algorithm.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "optimized_params = nni.get_next_parameter()\nparams.update(optimized_params)\nprint(params)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load dataset\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mnist = tf.keras.datasets.mnist\n\n(x_train, y_train), (x_test, y_test) = mnist.load_data()\nx_train, x_test = x_train / 255.0, x_test / 255.0" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Build model with hyperparameters\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model = tf.keras.models.Sequential([\n tf.keras.layers.Flatten(input_shape=(28, 28)),\n tf.keras.layers.Dense(params['dense_units'], activation=params['activation_type']),\n tf.keras.layers.Dropout(params['dropout_rate']),\n tf.keras.layers.Dense(10)\n])\n\nadam = tf.keras.optimizers.Adam(learning_rate=params['learning_rate'])\nloss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)\nmodel.compile(optimizer=adam, loss=loss_fn, metrics=['accuracy'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## (Optional) Report intermediate results\nThe callback reports per-epoch accuracy to show learning curve in the web portal.\nYou can also leverage the metrics for early stopping with :doc:`NNI assessors `.\n\nThis part can be safely skipped and the experiment will work fine.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "callback = tf.keras.callbacks.LambdaCallback(\n on_epoch_end = lambda epoch, logs: nni.report_intermediate_result(logs['accuracy'])\n)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Train and evluate the model\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model.fit(x_train, y_train, epochs=5, verbose=2, callbacks=[callback])\nloss, accuracy = model.evaluate(x_test, y_test, verbose=2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Report final result\nReport final accuracy to NNI so the tuning algorithm can suggest better hyperparameters.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "nni.report_final_result(accuracy)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.3" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/docs/source/tutorials/hpo_quickstart_tensorflow/model.py b/docs/source/tutorials/hpo_quickstart_tensorflow/model.py new file mode 100644 index 0000000000000000000000000000000000000000..c81c280dde2d33310d10f58b2f0da95b40dd1a7d --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_tensorflow/model.py @@ -0,0 +1,88 @@ +""" +Port TensorFlow Quickstart to NNI +================================= +This is a modified version of `TensorFlow quickstart`_. + +It can be run directly and will have the exact same result as original version. + +Furthermore, it enables the ability of auto tuning with an NNI *experiment*, which will be detailed later. + +It is recommended to run this script directly first to verify the environment. + +There are 3 key differences from the original version: + +1. In `Get optimized hyperparameters`_ part, it receives generated hyperparameters. +2. In `(Optional) Report intermediate results`_ part, it reports per-epoch accuracy metrics. +3. In `Report final result`_ part, it reports final accuracy. + +.. _TensorFlow quickstart: https://www.tensorflow.org/tutorials/quickstart/beginner +""" + +# %% +import nni +import tensorflow as tf + +# %% +# Hyperparameters to be tuned +# --------------------------- +# These are the hyperparameters that will be tuned later. +params = { + 'dense_units': 128, + 'activation_type': 'relu', + 'dropout_rate': 0.2, + 'learning_rate': 0.001, +} + +# %% +# Get optimized hyperparameters +# ----------------------------- +# If run directly, :func:`nni.get_next_parameter` is a no-op and returns an empty dict. +# But with an NNI *experiment*, it will receive optimized hyperparameters from tuning algorithm. +optimized_params = nni.get_next_parameter() +params.update(optimized_params) +print(params) + +# %% +# Load dataset +# ------------ +mnist = tf.keras.datasets.mnist + +(x_train, y_train), (x_test, y_test) = mnist.load_data() +x_train, x_test = x_train / 255.0, x_test / 255.0 + +# %% +# Build model with hyperparameters +# -------------------------------- +model = tf.keras.models.Sequential([ + tf.keras.layers.Flatten(input_shape=(28, 28)), + tf.keras.layers.Dense(params['dense_units'], activation=params['activation_type']), + tf.keras.layers.Dropout(params['dropout_rate']), + tf.keras.layers.Dense(10) +]) + +adam = tf.keras.optimizers.Adam(learning_rate=params['learning_rate']) +loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True) +model.compile(optimizer=adam, loss=loss_fn, metrics=['accuracy']) + +# %% +# (Optional) Report intermediate results +# -------------------------------------- +# The callback reports per-epoch accuracy to show learning curve in the web portal. +# You can also leverage the metrics for early stopping with :doc:`NNI assessors `. +# +# This part can be safely skipped and the experiment will work fine. +callback = tf.keras.callbacks.LambdaCallback( + on_epoch_end = lambda epoch, logs: nni.report_intermediate_result(logs['accuracy']) +) + +# %% +# Train and evluate the model +# --------------------------- +model.fit(x_train, y_train, epochs=5, verbose=2, callbacks=[callback]) +loss, accuracy = model.evaluate(x_test, y_test, verbose=2) + +# %% +# Report final result +# ------------------- +# Report final accuracy to NNI so the tuning algorithm can suggest better hyperparameters. +nni.report_final_result(accuracy) diff --git a/docs/source/tutorials/hpo_quickstart_tensorflow/model.py.md5 b/docs/source/tutorials/hpo_quickstart_tensorflow/model.py.md5 new file mode 100644 index 0000000000000000000000000000000000000000..29a82de303b62e8462470732a0da656199257b7c --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_tensorflow/model.py.md5 @@ -0,0 +1 @@ +d0c869d9d7c7f9208abc10357de52056 \ No newline at end of file diff --git a/docs/source/tutorials/hpo_quickstart_tensorflow/model.rst b/docs/source/tutorials/hpo_quickstart_tensorflow/model.rst new file mode 100644 index 0000000000000000000000000000000000000000..e1cd53d1d08551c9db3a22c0e9bc30c5ae2972a3 --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_tensorflow/model.rst @@ -0,0 +1,279 @@ +:orphan: + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "tutorials/hpo_quickstart_tensorflow/model.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_tutorials_hpo_quickstart_tensorflow_model.py: + + +Port TensorFlow Quickstart to NNI +================================= +This is a modified version of `TensorFlow quickstart`_. + +It can be run directly and will have the exact same result as original version. + +Furthermore, it enables the ability of auto tuning with an NNI *experiment*, which will be detailed later. + +It is recommended to run this script directly first to verify the environment. + +There are 3 key differences from the original version: + +1. In `Get optimized hyperparameters`_ part, it receives generated hyperparameters. +2. In `(Optional) Report intermediate results`_ part, it reports per-epoch accuracy metrics. +3. In `Report final result`_ part, it reports final accuracy. + +.. _TensorFlow quickstart: https://www.tensorflow.org/tutorials/quickstart/beginner + +.. GENERATED FROM PYTHON SOURCE LINES 22-25 + +.. code-block:: default + + import nni + import tensorflow as tf + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 26-29 + +Hyperparameters to be tuned +--------------------------- +These are the hyperparameters that will be tuned later. + +.. GENERATED FROM PYTHON SOURCE LINES 29-36 + +.. code-block:: default + + params = { + 'dense_units': 128, + 'activation_type': 'relu', + 'dropout_rate': 0.2, + 'learning_rate': 0.001, + } + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 37-41 + +Get optimized hyperparameters +----------------------------- +If run directly, :func:`nni.get_next_parameter` is a no-op and returns an empty dict. +But with an NNI *experiment*, it will receive optimized hyperparameters from tuning algorithm. + +.. GENERATED FROM PYTHON SOURCE LINES 41-45 + +.. code-block:: default + + optimized_params = nni.get_next_parameter() + params.update(optimized_params) + print(params) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + {'dense_units': 128, 'activation_type': 'relu', 'dropout_rate': 0.2, 'learning_rate': 0.001} + + + + +.. GENERATED FROM PYTHON SOURCE LINES 46-48 + +Load dataset +------------ + +.. GENERATED FROM PYTHON SOURCE LINES 48-53 + +.. code-block:: default + + mnist = tf.keras.datasets.mnist + + (x_train, y_train), (x_test, y_test) = mnist.load_data() + x_train, x_test = x_train / 255.0, x_test / 255.0 + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 54-56 + +Build model with hyperparameters +-------------------------------- + +.. GENERATED FROM PYTHON SOURCE LINES 56-67 + +.. code-block:: default + + model = tf.keras.models.Sequential([ + tf.keras.layers.Flatten(input_shape=(28, 28)), + tf.keras.layers.Dense(params['dense_units'], activation=params['activation_type']), + tf.keras.layers.Dropout(params['dropout_rate']), + tf.keras.layers.Dense(10) + ]) + + adam = tf.keras.optimizers.Adam(learning_rate=params['learning_rate']) + loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True) + model.compile(optimizer=adam, loss=loss_fn, metrics=['accuracy']) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 68-74 + +(Optional) Report intermediate results +-------------------------------------- +The callback reports per-epoch accuracy to show learning curve in the web portal. +You can also leverage the metrics for early stopping with :doc:`NNI assessors `. + +This part can be safely skipped and the experiment will work fine. + +.. GENERATED FROM PYTHON SOURCE LINES 74-78 + +.. code-block:: default + + callback = tf.keras.callbacks.LambdaCallback( + on_epoch_end = lambda epoch, logs: nni.report_intermediate_result(logs['accuracy']) + ) + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 79-81 + +Train and evluate the model +--------------------------- + +.. GENERATED FROM PYTHON SOURCE LINES 81-84 + +.. code-block:: default + + model.fit(x_train, y_train, epochs=5, verbose=2, callbacks=[callback]) + loss, accuracy = model.evaluate(x_test, y_test, verbose=2) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + Epoch 1/5 + [2022-03-21 01:25:00] INFO (nni/MainThread) Intermediate result: 0.9153500199317932 (Index 0) + 1875/1875 - 17s - loss: 0.2914 - accuracy: 0.9154 - 17s/epoch - 9ms/step + Epoch 2/5 + [2022-03-21 01:25:18] INFO (nni/MainThread) Intermediate result: 0.9588666558265686 (Index 1) + 1875/1875 - 18s - loss: 0.1387 - accuracy: 0.9589 - 18s/epoch - 10ms/step + Epoch 3/5 + [2022-03-21 01:25:38] INFO (nni/MainThread) Intermediate result: 0.9677000045776367 (Index 2) + 1875/1875 - 20s - loss: 0.1073 - accuracy: 0.9677 - 20s/epoch - 11ms/step + Epoch 4/5 + [2022-03-21 01:25:56] INFO (nni/MainThread) Intermediate result: 0.9738666415214539 (Index 3) + 1875/1875 - 18s - loss: 0.0866 - accuracy: 0.9739 - 18s/epoch - 10ms/step + Epoch 5/5 + [2022-03-21 01:26:16] INFO (nni/MainThread) Intermediate result: 0.977483332157135 (Index 4) + 1875/1875 - 21s - loss: 0.0728 - accuracy: 0.9775 - 21s/epoch - 11ms/step + 313/313 - 2s - loss: 0.0702 - accuracy: 0.9776 - 2s/epoch - 6ms/step + + + + +.. GENERATED FROM PYTHON SOURCE LINES 85-88 + +Report final result +------------------- +Report final accuracy to NNI so the tuning algorithm can suggest better hyperparameters. + +.. GENERATED FROM PYTHON SOURCE LINES 88-89 + +.. code-block:: default + + nni.report_final_result(accuracy) + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + [2022-03-21 01:27:08] INFO (nni/MainThread) Final result: 0.9775999784469604 + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 2 minutes 27.156 seconds) + + +.. _sphx_glr_download_tutorials_hpo_quickstart_tensorflow_model.py: + + +.. only :: html + + .. container:: sphx-glr-footer + :class: sphx-glr-footer-example + + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: model.py ` + + + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: model.ipynb ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/hpo_quickstart_tensorflow/model_codeobj.pickle b/docs/source/tutorials/hpo_quickstart_tensorflow/model_codeobj.pickle new file mode 100644 index 0000000000000000000000000000000000000000..45c67c4d74f1ef22bcde31a5fb2659df6eff72c7 Binary files /dev/null and b/docs/source/tutorials/hpo_quickstart_tensorflow/model_codeobj.pickle differ diff --git a/docs/source/tutorials/hpo_quickstart_tensorflow/sg_execution_times.rst b/docs/source/tutorials/hpo_quickstart_tensorflow/sg_execution_times.rst new file mode 100644 index 0000000000000000000000000000000000000000..fdbfe7c3d562d8a98fc08ce480ba649a749523e6 --- /dev/null +++ b/docs/source/tutorials/hpo_quickstart_tensorflow/sg_execution_times.rst @@ -0,0 +1,14 @@ + +:orphan: + +.. _sphx_glr_tutorials_hpo_quickstart_tensorflow_sg_execution_times: + +Computation times +================= +**01:24.384** total execution time for **tutorials_hpo_quickstart_tensorflow** files: + ++-----------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_tutorials_hpo_quickstart_tensorflow_main.py` (``main.py``) | 01:24.384 | 0.0 MB | ++-----------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_tutorials_hpo_quickstart_tensorflow_model.py` (``model.py``) | 00:00.000 | 0.0 MB | ++-----------------------------------------------------------------------------+-----------+--------+ diff --git a/docs/source/tutorials/images/thumb/sphx_glr_hello_nas_thumb.png b/docs/source/tutorials/images/thumb/sphx_glr_hello_nas_thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..025bdaa7e26f250342fd9bea93512e923f16e834 Binary files /dev/null and b/docs/source/tutorials/images/thumb/sphx_glr_hello_nas_thumb.png differ diff --git a/docs/source/tutorials/images/thumb/sphx_glr_nasbench_as_dataset_thumb.png b/docs/source/tutorials/images/thumb/sphx_glr_nasbench_as_dataset_thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..025bdaa7e26f250342fd9bea93512e923f16e834 Binary files /dev/null and b/docs/source/tutorials/images/thumb/sphx_glr_nasbench_as_dataset_thumb.png differ diff --git a/docs/source/tutorials/images/thumb/sphx_glr_pruning_customize_thumb.png b/docs/source/tutorials/images/thumb/sphx_glr_pruning_customize_thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..025bdaa7e26f250342fd9bea93512e923f16e834 Binary files /dev/null and b/docs/source/tutorials/images/thumb/sphx_glr_pruning_customize_thumb.png differ diff --git a/docs/source/tutorials/images/thumb/sphx_glr_pruning_quick_start_mnist_thumb.png b/docs/source/tutorials/images/thumb/sphx_glr_pruning_quick_start_mnist_thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..b06c4e6a17748efb9e7d009eb1e161759cfa2b74 Binary files /dev/null and b/docs/source/tutorials/images/thumb/sphx_glr_pruning_quick_start_mnist_thumb.png differ diff --git a/docs/source/tutorials/images/thumb/sphx_glr_pruning_speedup_thumb.png b/docs/source/tutorials/images/thumb/sphx_glr_pruning_speedup_thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..b06c4e6a17748efb9e7d009eb1e161759cfa2b74 Binary files /dev/null and b/docs/source/tutorials/images/thumb/sphx_glr_pruning_speedup_thumb.png differ diff --git a/docs/source/tutorials/images/thumb/sphx_glr_quantization_customize_thumb.png b/docs/source/tutorials/images/thumb/sphx_glr_quantization_customize_thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..025bdaa7e26f250342fd9bea93512e923f16e834 Binary files /dev/null and b/docs/source/tutorials/images/thumb/sphx_glr_quantization_customize_thumb.png differ diff --git a/docs/source/tutorials/images/thumb/sphx_glr_quantization_quick_start_mnist_thumb.png b/docs/source/tutorials/images/thumb/sphx_glr_quantization_quick_start_mnist_thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..b06c4e6a17748efb9e7d009eb1e161759cfa2b74 Binary files /dev/null and b/docs/source/tutorials/images/thumb/sphx_glr_quantization_quick_start_mnist_thumb.png differ diff --git a/docs/source/tutorials/images/thumb/sphx_glr_quantization_speedup_thumb.png b/docs/source/tutorials/images/thumb/sphx_glr_quantization_speedup_thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..b06c4e6a17748efb9e7d009eb1e161759cfa2b74 Binary files /dev/null and b/docs/source/tutorials/images/thumb/sphx_glr_quantization_speedup_thumb.png differ diff --git a/docs/source/tutorials/index.rst b/docs/source/tutorials/index.rst index 883277d4dc49c54d1cb045a6fa947329a3d7d650..16974c63043ae66c022d18ddbe89739498f8c378 100644 --- a/docs/source/tutorials/index.rst +++ b/docs/source/tutorials/index.rst @@ -11,14 +11,14 @@ Tutorials .. raw:: html -
+
.. only:: html - .. figure:: /tutorials/images/thumb/sphx_glr_nas_quick_start_mnist_thumb.png - :alt: Get started with NAS on MNIST + .. figure:: /tutorials/images/thumb/sphx_glr_pruning_speedup_thumb.png + :alt: Speedup Model with Mask - :ref:`sphx_glr_tutorials_nas_quick_start_mnist.py` + :ref:`sphx_glr_tutorials_pruning_speedup.py` .. raw:: html @@ -28,18 +28,18 @@ Tutorials .. toctree:: :hidden: - /tutorials/nas_quick_start_mnist + /tutorials/pruning_speedup .. raw:: html -
+
.. only:: html - .. figure:: /tutorials/images/thumb/sphx_glr_nni_experiment_thumb.png - :alt: Start and Manage a New Experiment + .. figure:: /tutorials/images/thumb/sphx_glr_quantization_speedup_thumb.png + :alt: SpeedUp Model with Calibration Config - :ref:`sphx_glr_tutorials_nni_experiment.py` + :ref:`sphx_glr_tutorials_quantization_speedup.py` .. raw:: html @@ -49,7 +49,237 @@ Tutorials .. toctree:: :hidden: - /tutorials/nni_experiment + /tutorials/quantization_speedup + +.. raw:: html + +
+ +.. only:: html + + .. figure:: /tutorials/images/thumb/sphx_glr_quantization_quick_start_mnist_thumb.png + :alt: Quantization Quickstart + + :ref:`sphx_glr_tutorials_quantization_quick_start_mnist.py` + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /tutorials/quantization_quick_start_mnist + +.. raw:: html + +
+ +.. only:: html + + .. figure:: /tutorials/images/thumb/sphx_glr_pruning_quick_start_mnist_thumb.png + :alt: Pruning Quickstart + + :ref:`sphx_glr_tutorials_pruning_quick_start_mnist.py` + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /tutorials/pruning_quick_start_mnist + +.. raw:: html + +
+ +.. only:: html + + .. figure:: /tutorials/images/thumb/sphx_glr_quantization_customize_thumb.png + :alt: Customize a new quantization algorithm + + :ref:`sphx_glr_tutorials_quantization_customize.py` + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /tutorials/quantization_customize + +.. raw:: html + +
+ +.. only:: html + + .. figure:: /tutorials/images/thumb/sphx_glr_nasbench_as_dataset_thumb.png + :alt: Use NAS Benchmarks as Datasets + + :ref:`sphx_glr_tutorials_nasbench_as_dataset.py` + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /tutorials/nasbench_as_dataset + +.. raw:: html + +
+ +.. only:: html + + .. figure:: /tutorials/images/thumb/sphx_glr_pruning_customize_thumb.png + :alt: Customize Basic Pruner + + :ref:`sphx_glr_tutorials_pruning_customize.py` + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /tutorials/pruning_customize + +.. raw:: html + +
+ +.. only:: html + + .. figure:: /tutorials/images/thumb/sphx_glr_hello_nas_thumb.png + :alt: Hello, NAS! + + :ref:`sphx_glr_tutorials_hello_nas.py` + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /tutorials/hello_nas +.. raw:: html + +
+ + + +.. _sphx_glr_tutorials_hpo_quickstart_pytorch: + + + + +.. raw:: html + +
+ +.. only:: html + + .. figure:: /tutorials/hpo_quickstart_pytorch/images/thumb/sphx_glr_main_thumb.png + :alt: HPO Quickstart with PyTorch + + :ref:`sphx_glr_tutorials_hpo_quickstart_pytorch_main.py` + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /tutorials/hpo_quickstart_pytorch/main + +.. raw:: html + +
+ +.. only:: html + + .. figure:: /tutorials/hpo_quickstart_pytorch/images/thumb/sphx_glr_model_thumb.png + :alt: Port PyTorch Quickstart to NNI + + :ref:`sphx_glr_tutorials_hpo_quickstart_pytorch_model.py` + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /tutorials/hpo_quickstart_pytorch/model +.. raw:: html + +
+ + + +.. _sphx_glr_tutorials_hpo_quickstart_tensorflow: + + + + +.. raw:: html + +
+ +.. only:: html + + .. figure:: /tutorials/hpo_quickstart_tensorflow/images/thumb/sphx_glr_main_thumb.png + :alt: HPO Quickstart with TensorFlow + + :ref:`sphx_glr_tutorials_hpo_quickstart_tensorflow_main.py` + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /tutorials/hpo_quickstart_tensorflow/main + +.. raw:: html + +
+ +.. only:: html + + .. figure:: /tutorials/hpo_quickstart_tensorflow/images/thumb/sphx_glr_model_thumb.png + :alt: Port TensorFlow Quickstart to NNI + + :ref:`sphx_glr_tutorials_hpo_quickstart_tensorflow_model.py` + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /tutorials/hpo_quickstart_tensorflow/model .. raw:: html
diff --git a/docs/source/tutorials/nas_quick_start_mnist.ipynb b/docs/source/tutorials/nas_quick_start_mnist.ipynb deleted file mode 100644 index 0ed38ebd40130d09ed55ce6bd8e91c766a6e24dc..0000000000000000000000000000000000000000 --- a/docs/source/tutorials/nas_quick_start_mnist.ipynb +++ /dev/null @@ -1,65 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "%matplotlib inline" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# Get started with NAS on MNIST\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "a = (1, 2, 3)\na" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "print('hello')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.8" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file diff --git a/docs/source/tutorials/nas_quick_start_mnist.py b/docs/source/tutorials/nas_quick_start_mnist.py deleted file mode 100644 index 7e5827823212b9d5c2d5666478a3e23b38a3dc10..0000000000000000000000000000000000000000 --- a/docs/source/tutorials/nas_quick_start_mnist.py +++ /dev/null @@ -1,11 +0,0 @@ -""" -Get started with NAS on MNIST -============================= -""" - -# %% -a = (1, 2, 3) -a - -# %% -print('hello') diff --git a/docs/source/tutorials/nas_quick_start_mnist.py.md5 b/docs/source/tutorials/nas_quick_start_mnist.py.md5 deleted file mode 100644 index d5985319db2dbc8dc9520f96a018f057dfcb46d0..0000000000000000000000000000000000000000 --- a/docs/source/tutorials/nas_quick_start_mnist.py.md5 +++ /dev/null @@ -1 +0,0 @@ -f87a716bc3274d0f9a77db503198ac4a \ No newline at end of file diff --git a/docs/source/tutorials/nas_quick_start_mnist.rst b/docs/source/tutorials/nas_quick_start_mnist.rst deleted file mode 100644 index 61f70b8d8a05fa96bcd2e6c322038928484776a4..0000000000000000000000000000000000000000 --- a/docs/source/tutorials/nas_quick_start_mnist.rst +++ /dev/null @@ -1,97 +0,0 @@ - -.. DO NOT EDIT. -.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. -.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: -.. "tutorials/nas_quick_start_mnist.py" -.. LINE NUMBERS ARE GIVEN BELOW. - -.. only:: html - - .. note:: - :class: sphx-glr-download-link-note - - Click :ref:`here ` - to download the full example code - -.. rst-class:: sphx-glr-example-title - -.. _sphx_glr_tutorials_nas_quick_start_mnist.py: - - -Get started with NAS on MNIST -============================= - -.. GENERATED FROM PYTHON SOURCE LINES 7-10 - -.. code-block:: default - - a = (1, 2, 3) - a - - - - - -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - - (1, 2, 3) - - - -.. GENERATED FROM PYTHON SOURCE LINES 11-12 - -.. code-block:: default - - print('hello') - - - - -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - hello - - - - - -.. rst-class:: sphx-glr-timing - - **Total running time of the script:** ( 0 minutes 0.002 seconds) - - -.. _sphx_glr_download_tutorials_nas_quick_start_mnist.py: - - -.. only :: html - - .. container:: sphx-glr-footer - :class: sphx-glr-footer-example - - - - .. container:: sphx-glr-download sphx-glr-download-python - - :download:`Download Python source code: nas_quick_start_mnist.py ` - - - - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: nas_quick_start_mnist.ipynb ` - - -.. only:: html - - .. rst-class:: sphx-glr-signature - - `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/nas_quick_start_mnist_codeobj.pickle b/docs/source/tutorials/nas_quick_start_mnist_codeobj.pickle deleted file mode 100644 index a1aa43e911b0ff88de811fb305eac4b3febc9917..0000000000000000000000000000000000000000 Binary files a/docs/source/tutorials/nas_quick_start_mnist_codeobj.pickle and /dev/null differ diff --git a/docs/source/tutorials/nasbench_as_dataset.ipynb b/docs/source/tutorials/nasbench_as_dataset.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..ce56dea80f1809708e569b8af99480d3dbba7c84 --- /dev/null +++ b/docs/source/tutorials/nasbench_as_dataset.ipynb @@ -0,0 +1,238 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# Use NAS Benchmarks as Datasets\n\nIn this tutorial, we show how to use NAS Benchmarks as datasets.\nFor research purposes we sometimes desire to query the benchmarks for architecture accuracies,\nrather than train them one by one from scratch.\nNNI has provided query tools so that users can easily get the retrieve the data in NAS benchmarks.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Prerequisites\nThis tutorial assumes that you have already prepared your NAS benchmarks under cache directory\n(by default, ``~/.cache/nni/nasbenchmark``).\nIf you haven't, please follow the data preparation guide in :doc:`/nas/benchmarks`.\n\nAs a result, the directory should look like:\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import os\nos.listdir(os.path.expanduser('~/.cache/nni/nasbenchmark'))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import pprint\n\nfrom nni.nas.benchmarks.nasbench101 import query_nb101_trial_stats\nfrom nni.nas.benchmarks.nasbench201 import query_nb201_trial_stats\nfrom nni.nas.benchmarks.nds import query_nds_trial_stats" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## NAS-Bench-101\n\nUse the following architecture as an example:\n\n\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "arch = {\n 'op1': 'conv3x3-bn-relu',\n 'op2': 'maxpool3x3',\n 'op3': 'conv3x3-bn-relu',\n 'op4': 'conv3x3-bn-relu',\n 'op5': 'conv1x1-bn-relu',\n 'input1': [0],\n 'input2': [1],\n 'input3': [2],\n 'input4': [0],\n 'input5': [0, 3, 4],\n 'input6': [2, 5]\n}\nfor t in query_nb101_trial_stats(arch, 108, include_intermediates=True):\n pprint.pprint(t)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "An architecture of NAS-Bench-101 could be trained more than once.\nEach element of the returned generator is a dict which contains one of the training results of this trial config\n(architecture + hyper-parameters) including train/valid/test accuracy,\ntraining time, number of epochs, etc. The results of NAS-Bench-201 and NDS follow similar formats.\n\n## NAS-Bench-201\n\nUse the following architecture as an example:\n\n\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "arch = {\n '0_1': 'avg_pool_3x3',\n '0_2': 'conv_1x1',\n '1_2': 'skip_connect',\n '0_3': 'conv_1x1',\n '1_3': 'skip_connect',\n '2_3': 'skip_connect'\n}\nfor t in query_nb201_trial_stats(arch, 200, 'cifar100'):\n pprint.pprint(t)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Intermediate results are also available.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "for t in query_nb201_trial_stats(arch, None, 'imagenet16-120', include_intermediates=True):\n print(t['config'])\n print('Intermediates:', len(t['intermediates']))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## NDS\n\nUse the following architecture as an example:\n\n\n\nHere, ``bot_muls``, ``ds``, ``num_gs``, ``ss`` and ``ws`` stand for \"bottleneck multipliers\",\n\"depths\", \"number of groups\", \"strides\" and \"widths\" respectively.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model_spec = {\n 'bot_muls': [0.0, 0.25, 0.25, 0.25],\n 'ds': [1, 16, 1, 4],\n 'num_gs': [1, 2, 1, 2],\n 'ss': [1, 1, 2, 2],\n 'ws': [16, 64, 128, 16]\n}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Use none as a wildcard.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "for t in query_nds_trial_stats('residual_bottleneck', None, None, model_spec, None, 'cifar10'):\n pprint.pprint(t)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model_spec = {\n 'bot_muls': [0.0, 0.25, 0.25, 0.25],\n 'ds': [1, 16, 1, 4],\n 'num_gs': [1, 2, 1, 2],\n 'ss': [1, 1, 2, 2],\n 'ws': [16, 64, 128, 16]\n}\nfor t in query_nds_trial_stats('residual_bottleneck', None, None, model_spec, None, 'cifar10', include_intermediates=True):\n pprint.pprint(t['intermediates'][:10])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model_spec = {'ds': [1, 12, 12, 12], 'ss': [1, 1, 2, 2], 'ws': [16, 24, 24, 40]}\nfor t in query_nds_trial_stats('residual_basic', 'resnet', 'random', model_spec, {}, 'cifar10'):\n pprint.pprint(t)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get the first one.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "pprint.pprint(next(query_nds_trial_stats('vanilla', None, None, None, None, None)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Count number.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model_spec = {'num_nodes_normal': 5, 'num_nodes_reduce': 5, 'depth': 12, 'width': 32, 'aux': False, 'drop_prob': 0.0}\ncell_spec = {\n 'normal_0_op_x': 'avg_pool_3x3',\n 'normal_0_input_x': 0,\n 'normal_0_op_y': 'conv_7x1_1x7',\n 'normal_0_input_y': 1,\n 'normal_1_op_x': 'sep_conv_3x3',\n 'normal_1_input_x': 2,\n 'normal_1_op_y': 'sep_conv_5x5',\n 'normal_1_input_y': 0,\n 'normal_2_op_x': 'dil_sep_conv_3x3',\n 'normal_2_input_x': 2,\n 'normal_2_op_y': 'dil_sep_conv_3x3',\n 'normal_2_input_y': 2,\n 'normal_3_op_x': 'skip_connect',\n 'normal_3_input_x': 4,\n 'normal_3_op_y': 'dil_sep_conv_3x3',\n 'normal_3_input_y': 4,\n 'normal_4_op_x': 'conv_7x1_1x7',\n 'normal_4_input_x': 2,\n 'normal_4_op_y': 'sep_conv_3x3',\n 'normal_4_input_y': 4,\n 'normal_concat': [3, 5, 6],\n 'reduce_0_op_x': 'avg_pool_3x3',\n 'reduce_0_input_x': 0,\n 'reduce_0_op_y': 'dil_sep_conv_3x3',\n 'reduce_0_input_y': 1,\n 'reduce_1_op_x': 'sep_conv_3x3',\n 'reduce_1_input_x': 0,\n 'reduce_1_op_y': 'sep_conv_3x3',\n 'reduce_1_input_y': 0,\n 'reduce_2_op_x': 'skip_connect',\n 'reduce_2_input_x': 2,\n 'reduce_2_op_y': 'sep_conv_7x7',\n 'reduce_2_input_y': 0,\n 'reduce_3_op_x': 'conv_7x1_1x7',\n 'reduce_3_input_x': 4,\n 'reduce_3_op_y': 'skip_connect',\n 'reduce_3_input_y': 4,\n 'reduce_4_op_x': 'conv_7x1_1x7',\n 'reduce_4_input_x': 0,\n 'reduce_4_op_y': 'conv_7x1_1x7',\n 'reduce_4_input_y': 5,\n 'reduce_concat': [3, 6]\n}\n\nfor t in query_nds_trial_stats('nas_cell', None, None, model_spec, cell_spec, 'cifar10'):\n assert t['config']['model_spec'] == model_spec\n assert t['config']['cell_spec'] == cell_spec\n pprint.pprint(t)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Count number.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print('NDS (amoeba) count:', len(list(query_nds_trial_stats(None, 'amoeba', None, None, None, None, None))))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/docs/source/tutorials/nasbench_as_dataset.py b/docs/source/tutorials/nasbench_as_dataset.py new file mode 100644 index 0000000000000000000000000000000000000000..91cb377575f4e13152c3ef61eecffc80ae5433ff --- /dev/null +++ b/docs/source/tutorials/nasbench_as_dataset.py @@ -0,0 +1,185 @@ +""" +Use NAS Benchmarks as Datasets +============================== + +In this tutorial, we show how to use NAS Benchmarks as datasets. +For research purposes we sometimes desire to query the benchmarks for architecture accuracies, +rather than train them one by one from scratch. +NNI has provided query tools so that users can easily get the retrieve the data in NAS benchmarks. +""" + +# %% +# Prerequisites +# ------------- +# This tutorial assumes that you have already prepared your NAS benchmarks under cache directory +# (by default, ``~/.cache/nni/nasbenchmark``). +# If you haven't, please follow the data preparation guide in :doc:`/nas/benchmarks`. +# +# As a result, the directory should look like: + +import os +os.listdir(os.path.expanduser('~/.cache/nni/nasbenchmark')) + +# %% +import pprint + +from nni.nas.benchmarks.nasbench101 import query_nb101_trial_stats +from nni.nas.benchmarks.nasbench201 import query_nb201_trial_stats +from nni.nas.benchmarks.nds import query_nds_trial_stats + +# %% +# NAS-Bench-101 +# ------------- +# +# Use the following architecture as an example: +# +# .. image:: ../../img/nas-bench-101-example.png + +arch = { + 'op1': 'conv3x3-bn-relu', + 'op2': 'maxpool3x3', + 'op3': 'conv3x3-bn-relu', + 'op4': 'conv3x3-bn-relu', + 'op5': 'conv1x1-bn-relu', + 'input1': [0], + 'input2': [1], + 'input3': [2], + 'input4': [0], + 'input5': [0, 3, 4], + 'input6': [2, 5] +} +for t in query_nb101_trial_stats(arch, 108, include_intermediates=True): + pprint.pprint(t) + +# %% +# An architecture of NAS-Bench-101 could be trained more than once. +# Each element of the returned generator is a dict which contains one of the training results of this trial config +# (architecture + hyper-parameters) including train/valid/test accuracy, +# training time, number of epochs, etc. The results of NAS-Bench-201 and NDS follow similar formats. +# +# NAS-Bench-201 +# ------------- +# +# Use the following architecture as an example: +# +# .. image:: ../../img/nas-bench-201-example.png + +arch = { + '0_1': 'avg_pool_3x3', + '0_2': 'conv_1x1', + '1_2': 'skip_connect', + '0_3': 'conv_1x1', + '1_3': 'skip_connect', + '2_3': 'skip_connect' +} +for t in query_nb201_trial_stats(arch, 200, 'cifar100'): + pprint.pprint(t) + +# %% +# Intermediate results are also available. + +for t in query_nb201_trial_stats(arch, None, 'imagenet16-120', include_intermediates=True): + print(t['config']) + print('Intermediates:', len(t['intermediates'])) + +# %% +# NDS +# --- +# +# Use the following architecture as an example: +# +# .. image:: ../../img/nas-bench-nds-example.png +# +# Here, ``bot_muls``, ``ds``, ``num_gs``, ``ss`` and ``ws`` stand for "bottleneck multipliers", +# "depths", "number of groups", "strides" and "widths" respectively. + +# %% +model_spec = { + 'bot_muls': [0.0, 0.25, 0.25, 0.25], + 'ds': [1, 16, 1, 4], + 'num_gs': [1, 2, 1, 2], + 'ss': [1, 1, 2, 2], + 'ws': [16, 64, 128, 16] +} + +# %% +# Use none as a wildcard. +for t in query_nds_trial_stats('residual_bottleneck', None, None, model_spec, None, 'cifar10'): + pprint.pprint(t) + +# %% +model_spec = { + 'bot_muls': [0.0, 0.25, 0.25, 0.25], + 'ds': [1, 16, 1, 4], + 'num_gs': [1, 2, 1, 2], + 'ss': [1, 1, 2, 2], + 'ws': [16, 64, 128, 16] +} +for t in query_nds_trial_stats('residual_bottleneck', None, None, model_spec, None, 'cifar10', include_intermediates=True): + pprint.pprint(t['intermediates'][:10]) + +# %% +model_spec = {'ds': [1, 12, 12, 12], 'ss': [1, 1, 2, 2], 'ws': [16, 24, 24, 40]} +for t in query_nds_trial_stats('residual_basic', 'resnet', 'random', model_spec, {}, 'cifar10'): + pprint.pprint(t) + +# %% +# Get the first one. +pprint.pprint(next(query_nds_trial_stats('vanilla', None, None, None, None, None))) + +# %% +# Count number. +model_spec = {'num_nodes_normal': 5, 'num_nodes_reduce': 5, 'depth': 12, 'width': 32, 'aux': False, 'drop_prob': 0.0} +cell_spec = { + 'normal_0_op_x': 'avg_pool_3x3', + 'normal_0_input_x': 0, + 'normal_0_op_y': 'conv_7x1_1x7', + 'normal_0_input_y': 1, + 'normal_1_op_x': 'sep_conv_3x3', + 'normal_1_input_x': 2, + 'normal_1_op_y': 'sep_conv_5x5', + 'normal_1_input_y': 0, + 'normal_2_op_x': 'dil_sep_conv_3x3', + 'normal_2_input_x': 2, + 'normal_2_op_y': 'dil_sep_conv_3x3', + 'normal_2_input_y': 2, + 'normal_3_op_x': 'skip_connect', + 'normal_3_input_x': 4, + 'normal_3_op_y': 'dil_sep_conv_3x3', + 'normal_3_input_y': 4, + 'normal_4_op_x': 'conv_7x1_1x7', + 'normal_4_input_x': 2, + 'normal_4_op_y': 'sep_conv_3x3', + 'normal_4_input_y': 4, + 'normal_concat': [3, 5, 6], + 'reduce_0_op_x': 'avg_pool_3x3', + 'reduce_0_input_x': 0, + 'reduce_0_op_y': 'dil_sep_conv_3x3', + 'reduce_0_input_y': 1, + 'reduce_1_op_x': 'sep_conv_3x3', + 'reduce_1_input_x': 0, + 'reduce_1_op_y': 'sep_conv_3x3', + 'reduce_1_input_y': 0, + 'reduce_2_op_x': 'skip_connect', + 'reduce_2_input_x': 2, + 'reduce_2_op_y': 'sep_conv_7x7', + 'reduce_2_input_y': 0, + 'reduce_3_op_x': 'conv_7x1_1x7', + 'reduce_3_input_x': 4, + 'reduce_3_op_y': 'skip_connect', + 'reduce_3_input_y': 4, + 'reduce_4_op_x': 'conv_7x1_1x7', + 'reduce_4_input_x': 0, + 'reduce_4_op_y': 'conv_7x1_1x7', + 'reduce_4_input_y': 5, + 'reduce_concat': [3, 6] +} + +for t in query_nds_trial_stats('nas_cell', None, None, model_spec, cell_spec, 'cifar10'): + assert t['config']['model_spec'] == model_spec + assert t['config']['cell_spec'] == cell_spec + pprint.pprint(t) + +# %% +# Count number. +print('NDS (amoeba) count:', len(list(query_nds_trial_stats(None, 'amoeba', None, None, None, None, None)))) diff --git a/docs/source/tutorials/nasbench_as_dataset.py.md5 b/docs/source/tutorials/nasbench_as_dataset.py.md5 new file mode 100644 index 0000000000000000000000000000000000000000..73343d3cac2a0074f112a1ad5a897a33d6088463 --- /dev/null +++ b/docs/source/tutorials/nasbench_as_dataset.py.md5 @@ -0,0 +1 @@ +715de24d20c57f3639033f6f10376c21 \ No newline at end of file diff --git a/docs/source/tutorials/nasbench_as_dataset.rst b/docs/source/tutorials/nasbench_as_dataset.rst new file mode 100644 index 0000000000000000000000000000000000000000..2fdfcc23d84c8c5bf23ee27b8b37c060cc55c573 --- /dev/null +++ b/docs/source/tutorials/nasbench_as_dataset.rst @@ -0,0 +1,834 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "tutorials/nasbench_as_dataset.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_tutorials_nasbench_as_dataset.py: + + +Use NAS Benchmarks as Datasets +============================== + +In this tutorial, we show how to use NAS Benchmarks as datasets. +For research purposes we sometimes desire to query the benchmarks for architecture accuracies, +rather than train them one by one from scratch. +NNI has provided query tools so that users can easily get the retrieve the data in NAS benchmarks. + +.. GENERATED FROM PYTHON SOURCE LINES 12-19 + +Prerequisites +------------- +This tutorial assumes that you have already prepared your NAS benchmarks under cache directory +(by default, ``~/.cache/nni/nasbenchmark``). +If you haven't, please follow the data preparation guide in :doc:`/nas/benchmarks`. + +As a result, the directory should look like: + +.. GENERATED FROM PYTHON SOURCE LINES 19-23 + +.. code-block:: default + + + import os + os.listdir(os.path.expanduser('~/.cache/nni/nasbenchmark')) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + + ['nasbench101-209f5694.db', 'nasbench201-b2b60732.db', 'nds-5745c235.db'] + + + +.. GENERATED FROM PYTHON SOURCE LINES 24-30 + +.. code-block:: default + + import pprint + + from nni.nas.benchmarks.nasbench101 import query_nb101_trial_stats + from nni.nas.benchmarks.nasbench201 import query_nb201_trial_stats + from nni.nas.benchmarks.nds import query_nds_trial_stats + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 31-37 + +NAS-Bench-101 +------------- + +Use the following architecture as an example: + +.. image:: ../../img/nas-bench-101-example.png + +.. GENERATED FROM PYTHON SOURCE LINES 37-54 + +.. code-block:: default + + + arch = { + 'op1': 'conv3x3-bn-relu', + 'op2': 'maxpool3x3', + 'op3': 'conv3x3-bn-relu', + 'op4': 'conv3x3-bn-relu', + 'op5': 'conv1x1-bn-relu', + 'input1': [0], + 'input2': [1], + 'input3': [2], + 'input4': [0], + 'input5': [0, 3, 4], + 'input6': [2, 5] + } + for t in query_nb101_trial_stats(arch, 108, include_intermediates=True): + pprint.pprint(t) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + [2022-02-28 13:48:51] INFO (nni.nas.benchmarks.utils/MainThread) "/home/yugzhan/.cache/nni/nasbenchmark/nasbench101-209f5694.db" already exists. Checking hash. + {'config': {'arch': {'input1': [0], + 'input2': [1], + 'input3': [2], + 'input4': [0], + 'input5': [0, 3, 4], + 'input6': [2, 5], + 'op1': 'conv3x3-bn-relu', + 'op2': 'maxpool3x3', + 'op3': 'conv3x3-bn-relu', + 'op4': 'conv3x3-bn-relu', + 'op5': 'conv1x1-bn-relu'}, + 'hash': '00005c142e6f48ac74fdcf73e3439874', + 'id': 4, + 'num_epochs': 108, + 'num_vertices': 7}, + 'id': 10, + 'intermediates': [{'current_epoch': 54, + 'id': 19, + 'test_acc': 77.40384340286255, + 'train_acc': 82.82251358032227, + 'training_time': 883.4580078125, + 'valid_acc': 77.76442170143127}, + {'current_epoch': 108, + 'id': 20, + 'test_acc': 92.11738705635071, + 'train_acc': 100.0, + 'training_time': 1769.1279296875, + 'valid_acc': 92.41786599159241}], + 'parameters': 8.55553, + 'test_acc': 92.11738705635071, + 'train_acc': 100.0, + 'training_time': 106147.67578125, + 'valid_acc': 92.41786599159241} + {'config': {'arch': {'input1': [0], + 'input2': [1], + 'input3': [2], + 'input4': [0], + 'input5': [0, 3, 4], + 'input6': [2, 5], + 'op1': 'conv3x3-bn-relu', + 'op2': 'maxpool3x3', + 'op3': 'conv3x3-bn-relu', + 'op4': 'conv3x3-bn-relu', + 'op5': 'conv1x1-bn-relu'}, + 'hash': '00005c142e6f48ac74fdcf73e3439874', + 'id': 4, + 'num_epochs': 108, + 'num_vertices': 7}, + 'id': 11, + 'intermediates': [{'current_epoch': 54, + 'id': 21, + 'test_acc': 82.04126358032227, + 'train_acc': 87.96073794364929, + 'training_time': 883.6810302734375, + 'valid_acc': 82.91265964508057}, + {'current_epoch': 108, + 'id': 22, + 'test_acc': 91.90705418586731, + 'train_acc': 100.0, + 'training_time': 1768.2509765625, + 'valid_acc': 92.45793223381042}], + 'parameters': 8.55553, + 'test_acc': 91.90705418586731, + 'train_acc': 100.0, + 'training_time': 106095.05859375, + 'valid_acc': 92.45793223381042} + {'config': {'arch': {'input1': [0], + 'input2': [1], + 'input3': [2], + 'input4': [0], + 'input5': [0, 3, 4], + 'input6': [2, 5], + 'op1': 'conv3x3-bn-relu', + 'op2': 'maxpool3x3', + 'op3': 'conv3x3-bn-relu', + 'op4': 'conv3x3-bn-relu', + 'op5': 'conv1x1-bn-relu'}, + 'hash': '00005c142e6f48ac74fdcf73e3439874', + 'id': 4, + 'num_epochs': 108, + 'num_vertices': 7}, + 'id': 12, + 'intermediates': [{'current_epoch': 54, + 'id': 23, + 'test_acc': 80.58894276618958, + 'train_acc': 86.34815812110901, + 'training_time': 883.4569702148438, + 'valid_acc': 81.1598539352417}, + {'current_epoch': 108, + 'id': 24, + 'test_acc': 92.15745329856873, + 'train_acc': 100.0, + 'training_time': 1768.9759521484375, + 'valid_acc': 93.04887652397156}], + 'parameters': 8.55553, + 'test_acc': 92.15745329856873, + 'train_acc': 100.0, + 'training_time': 106138.55712890625, + 'valid_acc': 93.04887652397156} + + + + +.. GENERATED FROM PYTHON SOURCE LINES 55-66 + +An architecture of NAS-Bench-101 could be trained more than once. +Each element of the returned generator is a dict which contains one of the training results of this trial config +(architecture + hyper-parameters) including train/valid/test accuracy, +training time, number of epochs, etc. The results of NAS-Bench-201 and NDS follow similar formats. + +NAS-Bench-201 +------------- + +Use the following architecture as an example: + +.. image:: ../../img/nas-bench-201-example.png + +.. GENERATED FROM PYTHON SOURCE LINES 66-78 + +.. code-block:: default + + + arch = { + '0_1': 'avg_pool_3x3', + '0_2': 'conv_1x1', + '1_2': 'skip_connect', + '0_3': 'conv_1x1', + '1_3': 'skip_connect', + '2_3': 'skip_connect' + } + for t in query_nb201_trial_stats(arch, 200, 'cifar100'): + pprint.pprint(t) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + [2022-02-28 13:49:09] INFO (nni.nas.benchmarks.utils/MainThread) "/home/yugzhan/.cache/nni/nasbenchmark/nasbench201-b2b60732.db" already exists. Checking hash. + {'config': {'arch': {'0_1': 'avg_pool_3x3', + '0_2': 'conv_1x1', + '0_3': 'conv_1x1', + '1_2': 'skip_connect', + '1_3': 'skip_connect', + '2_3': 'skip_connect'}, + 'dataset': 'cifar100', + 'id': 7, + 'num_cells': 5, + 'num_channels': 16, + 'num_epochs': 200}, + 'flops': 15.65322, + 'id': 3, + 'latency': 0.013182918230692545, + 'ori_test_acc': 53.11, + 'ori_test_evaluation_time': 1.0195916947864352, + 'ori_test_loss': 1.7307863704681397, + 'parameters': 0.135156, + 'seed': 999, + 'test_acc': 53.07999995727539, + 'test_evaluation_time': 0.5097958473932176, + 'test_loss': 1.731276072692871, + 'train_acc': 57.82, + 'train_loss': 1.5116578379058838, + 'training_time': 2888.4371995925903, + 'valid_acc': 53.14000000610351, + 'valid_evaluation_time': 0.5097958473932176, + 'valid_loss': 1.7302966793060304} + {'config': {'arch': {'0_1': 'avg_pool_3x3', + '0_2': 'conv_1x1', + '0_3': 'conv_1x1', + '1_2': 'skip_connect', + '1_3': 'skip_connect', + '2_3': 'skip_connect'}, + 'dataset': 'cifar100', + 'id': 7, + 'num_cells': 5, + 'num_channels': 16, + 'num_epochs': 200}, + 'flops': 15.65322, + 'id': 7, + 'latency': 0.013182918230692545, + 'ori_test_acc': 51.93, + 'ori_test_evaluation_time': 1.0195916947864352, + 'ori_test_loss': 1.7572312774658203, + 'parameters': 0.135156, + 'seed': 777, + 'test_acc': 51.979999938964845, + 'test_evaluation_time': 0.5097958473932176, + 'test_loss': 1.7429540189743042, + 'train_acc': 57.578, + 'train_loss': 1.5114233912658692, + 'training_time': 2888.4371995925903, + 'valid_acc': 51.88, + 'valid_evaluation_time': 0.5097958473932176, + 'valid_loss': 1.7715086591720581} + {'config': {'arch': {'0_1': 'avg_pool_3x3', + '0_2': 'conv_1x1', + '0_3': 'conv_1x1', + '1_2': 'skip_connect', + '1_3': 'skip_connect', + '2_3': 'skip_connect'}, + 'dataset': 'cifar100', + 'id': 7, + 'num_cells': 5, + 'num_channels': 16, + 'num_epochs': 200}, + 'flops': 15.65322, + 'id': 11, + 'latency': 0.013182918230692545, + 'ori_test_acc': 53.38, + 'ori_test_evaluation_time': 1.0195916947864352, + 'ori_test_loss': 1.7281623031616211, + 'parameters': 0.135156, + 'seed': 888, + 'test_acc': 53.67999998779297, + 'test_evaluation_time': 0.5097958473932176, + 'test_loss': 1.7327697801589965, + 'train_acc': 57.792, + 'train_loss': 1.5091403088760376, + 'training_time': 2888.4371995925903, + 'valid_acc': 53.08000000610352, + 'valid_evaluation_time': 0.5097958473932176, + 'valid_loss': 1.7235548280715942} + + + + +.. GENERATED FROM PYTHON SOURCE LINES 79-80 + +Intermediate results are also available. + +.. GENERATED FROM PYTHON SOURCE LINES 80-85 + +.. code-block:: default + + + for t in query_nb201_trial_stats(arch, None, 'imagenet16-120', include_intermediates=True): + print(t['config']) + print('Intermediates:', len(t['intermediates'])) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + {'id': 4, 'arch': {'0_1': 'avg_pool_3x3', '0_2': 'conv_1x1', '0_3': 'conv_1x1', '1_2': 'skip_connect', '1_3': 'skip_connect', '2_3': 'skip_connect'}, 'num_epochs': 12, 'num_channels': 16, 'num_cells': 5, 'dataset': 'imagenet16-120'} + Intermediates: 12 + {'id': 8, 'arch': {'0_1': 'avg_pool_3x3', '0_2': 'conv_1x1', '0_3': 'conv_1x1', '1_2': 'skip_connect', '1_3': 'skip_connect', '2_3': 'skip_connect'}, 'num_epochs': 200, 'num_channels': 16, 'num_cells': 5, 'dataset': 'imagenet16-120'} + Intermediates: 200 + {'id': 8, 'arch': {'0_1': 'avg_pool_3x3', '0_2': 'conv_1x1', '0_3': 'conv_1x1', '1_2': 'skip_connect', '1_3': 'skip_connect', '2_3': 'skip_connect'}, 'num_epochs': 200, 'num_channels': 16, 'num_cells': 5, 'dataset': 'imagenet16-120'} + Intermediates: 200 + {'id': 8, 'arch': {'0_1': 'avg_pool_3x3', '0_2': 'conv_1x1', '0_3': 'conv_1x1', '1_2': 'skip_connect', '1_3': 'skip_connect', '2_3': 'skip_connect'}, 'num_epochs': 200, 'num_channels': 16, 'num_cells': 5, 'dataset': 'imagenet16-120'} + Intermediates: 200 + + + + +.. GENERATED FROM PYTHON SOURCE LINES 86-95 + +NDS +--- + +Use the following architecture as an example: + +.. image:: ../../img/nas-bench-nds-example.png + +Here, ``bot_muls``, ``ds``, ``num_gs``, ``ss`` and ``ws`` stand for "bottleneck multipliers", +"depths", "number of groups", "strides" and "widths" respectively. + +.. GENERATED FROM PYTHON SOURCE LINES 97-105 + +.. code-block:: default + + model_spec = { + 'bot_muls': [0.0, 0.25, 0.25, 0.25], + 'ds': [1, 16, 1, 4], + 'num_gs': [1, 2, 1, 2], + 'ss': [1, 1, 2, 2], + 'ws': [16, 64, 128, 16] + } + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 106-107 + +Use none as a wildcard. + +.. GENERATED FROM PYTHON SOURCE LINES 107-110 + +.. code-block:: default + + for t in query_nds_trial_stats('residual_bottleneck', None, None, model_spec, None, 'cifar10'): + pprint.pprint(t) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + [2022-02-28 13:49:36] INFO (nni.nas.benchmarks.utils/MainThread) "/home/yugzhan/.cache/nni/nasbenchmark/nds-5745c235.db" already exists. Checking hash. + {'best_test_acc': 90.48, + 'best_train_acc': 96.356, + 'best_train_loss': 0.116, + 'config': {'base_lr': 0.1, + 'cell_spec': {}, + 'dataset': 'cifar10', + 'generator': 'random', + 'id': 45505, + 'model_family': 'residual_bottleneck', + 'model_spec': {'bot_muls': [0.0, 0.25, 0.25, 0.25], + 'ds': [1, 16, 1, 4], + 'num_gs': [1, 2, 1, 2], + 'ss': [1, 1, 2, 2], + 'ws': [16, 64, 128, 16]}, + 'num_epochs': 100, + 'proposer': 'resnext-a', + 'weight_decay': 0.0005}, + 'final_test_acc': 90.39, + 'final_train_acc': 96.298, + 'final_train_loss': 0.116, + 'flops': 69.890986, + 'id': 45505, + 'iter_time': 0.065, + 'parameters': 0.083002, + 'seed': 1} + + + + +.. GENERATED FROM PYTHON SOURCE LINES 111-121 + +.. code-block:: default + + model_spec = { + 'bot_muls': [0.0, 0.25, 0.25, 0.25], + 'ds': [1, 16, 1, 4], + 'num_gs': [1, 2, 1, 2], + 'ss': [1, 1, 2, 2], + 'ws': [16, 64, 128, 16] + } + for t in query_nds_trial_stats('residual_bottleneck', None, None, model_spec, None, 'cifar10', include_intermediates=True): + pprint.pprint(t['intermediates'][:10]) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + [{'current_epoch': 1, + 'id': 4494501, + 'test_acc': 41.76, + 'train_acc': 30.421000000000006, + 'train_loss': 1.793}, + {'current_epoch': 2, + 'id': 4494502, + 'test_acc': 54.66, + 'train_acc': 47.24, + 'train_loss': 1.415}, + {'current_epoch': 3, + 'id': 4494503, + 'test_acc': 59.97, + 'train_acc': 56.983, + 'train_loss': 1.179}, + {'current_epoch': 4, + 'id': 4494504, + 'test_acc': 62.91, + 'train_acc': 61.955, + 'train_loss': 1.048}, + {'current_epoch': 5, + 'id': 4494505, + 'test_acc': 66.16, + 'train_acc': 64.493, + 'train_loss': 0.983}, + {'current_epoch': 6, + 'id': 4494506, + 'test_acc': 66.5, + 'train_acc': 66.274, + 'train_loss': 0.937}, + {'current_epoch': 7, + 'id': 4494507, + 'test_acc': 67.55, + 'train_acc': 67.426, + 'train_loss': 0.907}, + {'current_epoch': 8, + 'id': 4494508, + 'test_acc': 69.45, + 'train_acc': 68.45400000000001, + 'train_loss': 0.878}, + {'current_epoch': 9, + 'id': 4494509, + 'test_acc': 70.14, + 'train_acc': 69.295, + 'train_loss': 0.857}, + {'current_epoch': 10, + 'id': 4494510, + 'test_acc': 69.47, + 'train_acc': 70.304, + 'train_loss': 0.832}] + + + + +.. GENERATED FROM PYTHON SOURCE LINES 122-126 + +.. code-block:: default + + model_spec = {'ds': [1, 12, 12, 12], 'ss': [1, 1, 2, 2], 'ws': [16, 24, 24, 40]} + for t in query_nds_trial_stats('residual_basic', 'resnet', 'random', model_spec, {}, 'cifar10'): + pprint.pprint(t) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + {'best_test_acc': 93.58, + 'best_train_acc': 99.772, + 'best_train_loss': 0.011, + 'config': {'base_lr': 0.1, + 'cell_spec': {}, + 'dataset': 'cifar10', + 'generator': 'random', + 'id': 108998, + 'model_family': 'residual_basic', + 'model_spec': {'ds': [1, 12, 12, 12], + 'ss': [1, 1, 2, 2], + 'ws': [16, 24, 24, 40]}, + 'num_epochs': 100, + 'proposer': 'resnet', + 'weight_decay': 0.0005}, + 'final_test_acc': 93.49, + 'final_train_acc': 99.772, + 'final_train_loss': 0.011, + 'flops': 184.519578, + 'id': 108998, + 'iter_time': 0.059, + 'parameters': 0.594138, + 'seed': 1} + + + + +.. GENERATED FROM PYTHON SOURCE LINES 127-128 + +Get the first one. + +.. GENERATED FROM PYTHON SOURCE LINES 128-130 + +.. code-block:: default + + pprint.pprint(next(query_nds_trial_stats('vanilla', None, None, None, None, None))) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + {'best_test_acc': 84.5, + 'best_train_acc': 89.66499999999999, + 'best_train_loss': 0.302, + 'config': {'base_lr': 0.1, + 'cell_spec': {}, + 'dataset': 'cifar10', + 'generator': 'random', + 'id': 139492, + 'model_family': 'vanilla', + 'model_spec': {'ds': [1, 12, 12, 12], + 'ss': [1, 1, 2, 2], + 'ws': [16, 24, 32, 40]}, + 'num_epochs': 100, + 'proposer': 'vanilla', + 'weight_decay': 0.0005}, + 'final_test_acc': 84.35, + 'final_train_acc': 89.633, + 'final_train_loss': 0.303, + 'flops': 208.36393, + 'id': 154692, + 'iter_time': 0.058, + 'parameters': 0.68977, + 'seed': 1} + + + + +.. GENERATED FROM PYTHON SOURCE LINES 131-132 + +Count number. + +.. GENERATED FROM PYTHON SOURCE LINES 132-183 + +.. code-block:: default + + model_spec = {'num_nodes_normal': 5, 'num_nodes_reduce': 5, 'depth': 12, 'width': 32, 'aux': False, 'drop_prob': 0.0} + cell_spec = { + 'normal_0_op_x': 'avg_pool_3x3', + 'normal_0_input_x': 0, + 'normal_0_op_y': 'conv_7x1_1x7', + 'normal_0_input_y': 1, + 'normal_1_op_x': 'sep_conv_3x3', + 'normal_1_input_x': 2, + 'normal_1_op_y': 'sep_conv_5x5', + 'normal_1_input_y': 0, + 'normal_2_op_x': 'dil_sep_conv_3x3', + 'normal_2_input_x': 2, + 'normal_2_op_y': 'dil_sep_conv_3x3', + 'normal_2_input_y': 2, + 'normal_3_op_x': 'skip_connect', + 'normal_3_input_x': 4, + 'normal_3_op_y': 'dil_sep_conv_3x3', + 'normal_3_input_y': 4, + 'normal_4_op_x': 'conv_7x1_1x7', + 'normal_4_input_x': 2, + 'normal_4_op_y': 'sep_conv_3x3', + 'normal_4_input_y': 4, + 'normal_concat': [3, 5, 6], + 'reduce_0_op_x': 'avg_pool_3x3', + 'reduce_0_input_x': 0, + 'reduce_0_op_y': 'dil_sep_conv_3x3', + 'reduce_0_input_y': 1, + 'reduce_1_op_x': 'sep_conv_3x3', + 'reduce_1_input_x': 0, + 'reduce_1_op_y': 'sep_conv_3x3', + 'reduce_1_input_y': 0, + 'reduce_2_op_x': 'skip_connect', + 'reduce_2_input_x': 2, + 'reduce_2_op_y': 'sep_conv_7x7', + 'reduce_2_input_y': 0, + 'reduce_3_op_x': 'conv_7x1_1x7', + 'reduce_3_input_x': 4, + 'reduce_3_op_y': 'skip_connect', + 'reduce_3_input_y': 4, + 'reduce_4_op_x': 'conv_7x1_1x7', + 'reduce_4_input_x': 0, + 'reduce_4_op_y': 'conv_7x1_1x7', + 'reduce_4_input_y': 5, + 'reduce_concat': [3, 6] + } + + for t in query_nds_trial_stats('nas_cell', None, None, model_spec, cell_spec, 'cifar10'): + assert t['config']['model_spec'] == model_spec + assert t['config']['cell_spec'] == cell_spec + pprint.pprint(t) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + {'best_test_acc': 93.37, + 'best_train_acc': 99.91, + 'best_train_loss': 0.006, + 'config': {'base_lr': 0.1, + 'cell_spec': {'normal_0_input_x': 0, + 'normal_0_input_y': 1, + 'normal_0_op_x': 'avg_pool_3x3', + 'normal_0_op_y': 'conv_7x1_1x7', + 'normal_1_input_x': 2, + 'normal_1_input_y': 0, + 'normal_1_op_x': 'sep_conv_3x3', + 'normal_1_op_y': 'sep_conv_5x5', + 'normal_2_input_x': 2, + 'normal_2_input_y': 2, + 'normal_2_op_x': 'dil_sep_conv_3x3', + 'normal_2_op_y': 'dil_sep_conv_3x3', + 'normal_3_input_x': 4, + 'normal_3_input_y': 4, + 'normal_3_op_x': 'skip_connect', + 'normal_3_op_y': 'dil_sep_conv_3x3', + 'normal_4_input_x': 2, + 'normal_4_input_y': 4, + 'normal_4_op_x': 'conv_7x1_1x7', + 'normal_4_op_y': 'sep_conv_3x3', + 'normal_concat': [3, 5, 6], + 'reduce_0_input_x': 0, + 'reduce_0_input_y': 1, + 'reduce_0_op_x': 'avg_pool_3x3', + 'reduce_0_op_y': 'dil_sep_conv_3x3', + 'reduce_1_input_x': 0, + 'reduce_1_input_y': 0, + 'reduce_1_op_x': 'sep_conv_3x3', + 'reduce_1_op_y': 'sep_conv_3x3', + 'reduce_2_input_x': 2, + 'reduce_2_input_y': 0, + 'reduce_2_op_x': 'skip_connect', + 'reduce_2_op_y': 'sep_conv_7x7', + 'reduce_3_input_x': 4, + 'reduce_3_input_y': 4, + 'reduce_3_op_x': 'conv_7x1_1x7', + 'reduce_3_op_y': 'skip_connect', + 'reduce_4_input_x': 0, + 'reduce_4_input_y': 5, + 'reduce_4_op_x': 'conv_7x1_1x7', + 'reduce_4_op_y': 'conv_7x1_1x7', + 'reduce_concat': [3, 6]}, + 'dataset': 'cifar10', + 'generator': 'random', + 'id': 1, + 'model_family': 'nas_cell', + 'model_spec': {'aux': False, + 'depth': 12, + 'drop_prob': 0.0, + 'num_nodes_normal': 5, + 'num_nodes_reduce': 5, + 'width': 32}, + 'num_epochs': 100, + 'proposer': 'amoeba', + 'weight_decay': 0.0005}, + 'final_test_acc': 93.27, + 'final_train_acc': 99.91, + 'final_train_loss': 0.006, + 'flops': 664.400586, + 'id': 1, + 'iter_time': 0.281, + 'parameters': 4.190314, + 'seed': 1} + + + + +.. GENERATED FROM PYTHON SOURCE LINES 184-185 + +Count number. + +.. GENERATED FROM PYTHON SOURCE LINES 185-186 + +.. code-block:: default + + print('NDS (amoeba) count:', len(list(query_nds_trial_stats(None, 'amoeba', None, None, None, None, None)))) + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + NDS (amoeba) count: 5107 + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 1 minutes 2.214 seconds) + + +.. _sphx_glr_download_tutorials_nasbench_as_dataset.py: + + +.. only :: html + + .. container:: sphx-glr-footer + :class: sphx-glr-footer-example + + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: nasbench_as_dataset.py ` + + + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: nasbench_as_dataset.ipynb ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/nasbench_as_dataset_codeobj.pickle b/docs/source/tutorials/nasbench_as_dataset_codeobj.pickle new file mode 100644 index 0000000000000000000000000000000000000000..656b3e1233fb7f7569c73ef5518d793579099c08 Binary files /dev/null and b/docs/source/tutorials/nasbench_as_dataset_codeobj.pickle differ diff --git a/docs/source/tutorials/nni_experiment.ipynb b/docs/source/tutorials/nni_experiment.ipynb deleted file mode 100644 index bfd30a4521b536ad8dd2854698b234ddf7f556c6..0000000000000000000000000000000000000000 --- a/docs/source/tutorials/nni_experiment.ipynb +++ /dev/null @@ -1,187 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "%matplotlib inline" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# Start and Manage a New Experiment\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Configure Search Space\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "search_space = {\n \"C\": {\"_type\": \"quniform\", \"_value\": [0.1, 1, 0.1]},\n \"kernel\": {\"_type\": \"choice\", \"_value\": [\"linear\", \"rbf\", \"poly\", \"sigmoid\"]},\n \"degree\": {\"_type\": \"choice\", \"_value\": [1, 2, 3, 4]},\n \"gamma\": {\"_type\": \"quniform\", \"_value\": [0.01, 0.1, 0.01]},\n \"coef0\": {\"_type\": \"quniform\", \"_value\": [0.01, 0.1, 0.01]}\n}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Configure Experiment\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "from nni.experiment import Experiment\nexperiment = Experiment('local')\nexperiment.config.experiment_name = 'Example'\nexperiment.config.trial_concurrency = 2\nexperiment.config.max_trial_number = 10\nexperiment.config.search_space = search_space\nexperiment.config.trial_command = 'python scripts/trial_sklearn.py'\nexperiment.config.trial_code_directory = './'\nexperiment.config.tuner.name = 'TPE'\nexperiment.config.tuner.class_args['optimize_mode'] = 'maximize'\nexperiment.config.training_service.use_active_gpu = True" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Start Experiment\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "experiment.start(8080)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Experiment View & Control\n\nView the status of experiment.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "experiment.get_status()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Wait until at least one trial finishes.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "import time\n\nfor _ in range(10):\n stats = experiment.get_job_statistics()\n if any(stat['trialJobStatus'] == 'SUCCEEDED' for stat in stats):\n break\n time.sleep(10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Export the experiment data.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "experiment.export_data()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get metric of jobs\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "experiment.get_job_metrics()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Stop Experiment\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "experiment.stop()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.8" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file diff --git a/docs/source/tutorials/nni_experiment.py b/docs/source/tutorials/nni_experiment.py deleted file mode 100644 index f6619dd31dff76eb6ff2978e0c2c7d33c06f88a4..0000000000000000000000000000000000000000 --- a/docs/source/tutorials/nni_experiment.py +++ /dev/null @@ -1,67 +0,0 @@ -""" -Start and Manage a New Experiment -================================= -""" - -# %% -# Configure Search Space -# ---------------------- - -search_space = { - "C": {"_type": "quniform", "_value": [0.1, 1, 0.1]}, - "kernel": {"_type": "choice", "_value": ["linear", "rbf", "poly", "sigmoid"]}, - "degree": {"_type": "choice", "_value": [1, 2, 3, 4]}, - "gamma": {"_type": "quniform", "_value": [0.01, 0.1, 0.01]}, - "coef0": {"_type": "quniform", "_value": [0.01, 0.1, 0.01]} -} - -# %% -# Configure Experiment -# -------------------- - -from nni.experiment import Experiment -experiment = Experiment('local') -experiment.config.experiment_name = 'Example' -experiment.config.trial_concurrency = 2 -experiment.config.max_trial_number = 10 -experiment.config.search_space = search_space -experiment.config.trial_command = 'python scripts/trial_sklearn.py' -experiment.config.trial_code_directory = './' -experiment.config.tuner.name = 'TPE' -experiment.config.tuner.class_args['optimize_mode'] = 'maximize' -experiment.config.training_service.use_active_gpu = True - -# %% -# Start Experiment -# ---------------- -experiment.start(8080) - -# %% -# Experiment View & Control -# ------------------------- -# -# View the status of experiment. -experiment.get_status() - -# %% -# Wait until at least one trial finishes. -import time - -for _ in range(10): - stats = experiment.get_job_statistics() - if any(stat['trialJobStatus'] == 'SUCCEEDED' for stat in stats): - break - time.sleep(10) - -# %% -# Export the experiment data. -experiment.export_data() - -# %% -# Get metric of jobs -experiment.get_job_metrics() - -# %% -# Stop Experiment -# --------------- -experiment.stop() diff --git a/docs/source/tutorials/nni_experiment.py.md5 b/docs/source/tutorials/nni_experiment.py.md5 deleted file mode 100644 index 6ca09d53840687cd0665521edc6b817898d3cc09..0000000000000000000000000000000000000000 --- a/docs/source/tutorials/nni_experiment.py.md5 +++ /dev/null @@ -1 +0,0 @@ -9f822647d89f05264b70d1ae1c473be1 \ No newline at end of file diff --git a/docs/source/tutorials/nni_experiment.rst b/docs/source/tutorials/nni_experiment.rst deleted file mode 100644 index 13133bda76f3bbbfbd5e3d1bed5bb7167c207716..0000000000000000000000000000000000000000 --- a/docs/source/tutorials/nni_experiment.rst +++ /dev/null @@ -1,265 +0,0 @@ - -.. DO NOT EDIT. -.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. -.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: -.. "tutorials/nni_experiment.py" -.. LINE NUMBERS ARE GIVEN BELOW. - -.. only:: html - - .. note:: - :class: sphx-glr-download-link-note - - Click :ref:`here ` - to download the full example code - -.. rst-class:: sphx-glr-example-title - -.. _sphx_glr_tutorials_nni_experiment.py: - - -Start and Manage a New Experiment -================================= - -.. GENERATED FROM PYTHON SOURCE LINES 7-9 - -Configure Search Space ----------------------- - -.. GENERATED FROM PYTHON SOURCE LINES 9-18 - -.. code-block:: default - - - search_space = { - "C": {"_type": "quniform", "_value": [0.1, 1, 0.1]}, - "kernel": {"_type": "choice", "_value": ["linear", "rbf", "poly", "sigmoid"]}, - "degree": {"_type": "choice", "_value": [1, 2, 3, 4]}, - "gamma": {"_type": "quniform", "_value": [0.01, 0.1, 0.01]}, - "coef0": {"_type": "quniform", "_value": [0.01, 0.1, 0.01]} - } - - - - - - - - -.. GENERATED FROM PYTHON SOURCE LINES 19-21 - -Configure Experiment --------------------- - -.. GENERATED FROM PYTHON SOURCE LINES 21-34 - -.. code-block:: default - - - from nni.experiment import Experiment - experiment = Experiment('local') - experiment.config.experiment_name = 'Example' - experiment.config.trial_concurrency = 2 - experiment.config.max_trial_number = 10 - experiment.config.search_space = search_space - experiment.config.trial_command = 'python scripts/trial_sklearn.py' - experiment.config.trial_code_directory = './' - experiment.config.tuner.name = 'TPE' - experiment.config.tuner.class_args['optimize_mode'] = 'maximize' - experiment.config.training_service.use_active_gpu = True - - - - - - - - -.. GENERATED FROM PYTHON SOURCE LINES 35-37 - -Start Experiment ----------------- - -.. GENERATED FROM PYTHON SOURCE LINES 37-39 - -.. code-block:: default - - experiment.start(8080) - - - - - -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - [2022-02-07 18:56:04] Creating experiment, Experiment ID: fl9vu67z - [2022-02-07 18:56:04] Starting web server... - [2022-02-07 18:56:05] Setting up... - [2022-02-07 18:56:05] Web UI URLs: http://127.0.0.1:8080 http://10.190.173.211:8080 http://172.17.0.1:8080 http://192.168.49.1:8080 - - - - -.. GENERATED FROM PYTHON SOURCE LINES 40-44 - -Experiment View & Control -------------------------- - -View the status of experiment. - -.. GENERATED FROM PYTHON SOURCE LINES 44-46 - -.. code-block:: default - - experiment.get_status() - - - - - -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - - 'RUNNING' - - - -.. GENERATED FROM PYTHON SOURCE LINES 47-48 - -Wait until at least one trial finishes. - -.. GENERATED FROM PYTHON SOURCE LINES 48-56 - -.. code-block:: default - - import time - - for _ in range(10): - stats = experiment.get_job_statistics() - if any(stat['trialJobStatus'] == 'SUCCEEDED' for stat in stats): - break - time.sleep(10) - - - - - - - - -.. GENERATED FROM PYTHON SOURCE LINES 57-58 - -Export the experiment data. - -.. GENERATED FROM PYTHON SOURCE LINES 58-60 - -.. code-block:: default - - experiment.export_data() - - - - - -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - - [TrialResult(parameter={'C': 0.9, 'kernel': 'rbf', 'degree': 4, 'gamma': 0.07, 'coef0': 0.03}, value=0.9733333333333334, trialJobId='dNOZt'), TrialResult(parameter={'C': 0.8, 'kernel': 'sigmoid', 'degree': 2, 'gamma': 0.01, 'coef0': 0.01}, value=0.9733333333333334, trialJobId='okYSD')] - - - -.. GENERATED FROM PYTHON SOURCE LINES 61-62 - -Get metric of jobs - -.. GENERATED FROM PYTHON SOURCE LINES 62-64 - -.. code-block:: default - - experiment.get_job_metrics() - - - - - -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - - {'okYSD': [TrialMetricData(timestamp=1644227777089, trialJobId='okYSD', parameterId='1', type='FINAL', sequence=0, data=0.9733333333333334)], 'dNOZt': [TrialMetricData(timestamp=1644227777357, trialJobId='dNOZt', parameterId='0', type='FINAL', sequence=0, data=0.9733333333333334)]} - - - -.. GENERATED FROM PYTHON SOURCE LINES 65-67 - -Stop Experiment ---------------- - -.. GENERATED FROM PYTHON SOURCE LINES 67-68 - -.. code-block:: default - - experiment.stop() - - - - -.. rst-class:: sphx-glr-script-out - - Out: - - .. code-block:: none - - [2022-02-07 18:56:25] Stopping experiment, please wait... - [2022-02-07 18:56:28] Experiment stopped - - - - - -.. rst-class:: sphx-glr-timing - - **Total running time of the script:** ( 0 minutes 24.662 seconds) - - -.. _sphx_glr_download_tutorials_nni_experiment.py: - - -.. only :: html - - .. container:: sphx-glr-footer - :class: sphx-glr-footer-example - - - - .. container:: sphx-glr-download sphx-glr-download-python - - :download:`Download Python source code: nni_experiment.py ` - - - - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: nni_experiment.ipynb ` - - -.. only:: html - - .. rst-class:: sphx-glr-signature - - `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/nni_experiment_codeobj.pickle b/docs/source/tutorials/nni_experiment_codeobj.pickle deleted file mode 100644 index 197b9a575ad154c5e716255aff7ab7f4d6d9efbf..0000000000000000000000000000000000000000 Binary files a/docs/source/tutorials/nni_experiment_codeobj.pickle and /dev/null differ diff --git a/docs/source/tutorials/pruning_customize.ipynb b/docs/source/tutorials/pruning_customize.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..394274eb3eaa643f9310581fabb93c7767bd5831 --- /dev/null +++ b/docs/source/tutorials/pruning_customize.ipynb @@ -0,0 +1,97 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# Customize Basic Pruner\n\nUsers can easily customize a basic pruner in NNI. A large number of basic modules have been provided and can be reused.\nFollow the NNI pruning interface, users only need to focus on their creative parts without worrying about other regular modules.\n\nIn this tutorial, we show how to customize a basic pruner.\n\n## Concepts\n\nNNI abstracts the basic pruning process into three steps, collecting data, calculating metrics, allocating sparsity.\nMost pruning algorithms rely on a metric to decide where should be pruned. Using L1 norm pruner as an example,\nthe first step is collecting model weights, the second step is calculating L1 norm for weight per output channel,\nthe third step is ranking L1 norm metric and masking the output channels that have small L1 norm.\n\nIn NNI basic pruner, these three step is implement as ``DataCollector``, ``MetricsCalculator`` and ``SparsityAllocator``.\n\n- ``DataCollector``: This module take pruner as initialize parameter.\n It will get the relevant information of the model from the pruner,\n and sometimes it will also hook the model to get input, output or gradient of a layer or a tensor.\n It can also patch optimizer if some special steps need to be executed before or after ``optimizer.step()``.\n\n- ``MetricsCalculator``: This module will take the data collected from the ``DataCollector``,\n then calculate the metrics. The metric shape is usually reduced from the data shape.\n The ``dim`` taken by ``MetricsCalculator`` means which dimension will be kept after calculate metrics.\n i.e., the collected data shape is (10, 20, 30), and the ``dim`` is 1, then the dimension-1 will be kept,\n the output metrics shape should be (20,).\n\n- ``SparsityAllocator``: This module take the metrics and generate the masks.\n Different ``SparsityAllocator`` has different masks generation strategies.\n A common and simple strategy is sorting the metrics' values and calculating a threshold according to the configured sparsity,\n mask the positions which metric value smaller than the threshold.\n The ``dim`` taken by ``SparsityAllocator`` means the metrics are for which dimension, the mask will be expanded to weight shape.\n i.e., the metric shape is (20,), the corresponding layer weight shape is (20, 40), and the ``dim`` is 0.\n ``SparsityAllocator`` will first generate a mask with shape (20,), then expand this mask to shape (20, 40).\n\n## Simple Example: Customize a Block-L1NormPruner\n\nNNI already have L1NormPruner, but for the reason of reproducing the paper and reducing user configuration items,\nit only support pruning layer output channels. In this example, we will customize a pruner that supports block granularity for Linear.\n\nNote that you don't need to implement all these three kinds of tools for each time,\nNNI supports many predefined tools, and you can directly use these to customize your own pruner.\nThis is a tutorial so we show how to define all these three kinds of pruning tools.\n\nCustomize the pruning tools used by the pruner at first.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import torch\nfrom nni.algorithms.compression.v2.pytorch.pruning.basic_pruner import BasicPruner\nfrom nni.algorithms.compression.v2.pytorch.pruning.tools import (\n DataCollector,\n MetricsCalculator,\n SparsityAllocator\n)\n\n\n# This data collector collects weight in wrapped module as data.\n# The wrapped module is the module configured in pruner's config_list.\n# This implementation is similar as nni.algorithms.compression.v2.pytorch.pruning.tools.WeightDataCollector\nclass WeightDataCollector(DataCollector):\n def collect(self):\n data = {}\n # get_modules_wrapper will get all the wrapper in the compressor (pruner),\n # it returns a dict with format {wrapper_name: wrapper},\n # use wrapper.module to get the wrapped module.\n for _, wrapper in self.compressor.get_modules_wrapper().items():\n data[wrapper.name] = wrapper.module.weight.data\n # return {wrapper_name: weight_data}\n return data\n\n\nclass BlockNormMetricsCalculator(MetricsCalculator):\n def __init__(self, block_sparse_size):\n # Because we will keep all dimension with block granularity, so fix ``dim=None``,\n # means all dimensions will be kept.\n super().__init__(dim=None, block_sparse_size=block_sparse_size)\n\n def calculate_metrics(self, data):\n data_length = len(self.block_sparse_size)\n reduce_unfold_dims = list(range(data_length, 2 * data_length))\n\n metrics = {}\n for name, t in data.items():\n # Unfold t as block size, and calculate L1 Norm for each block.\n for dim, size in enumerate(self.block_sparse_size):\n t = t.unfold(dim, size, size)\n metrics[name] = t.norm(dim=reduce_unfold_dims, p=1)\n # return {wrapper_name: block_metric}\n return metrics\n\n\n# This implementation is similar as nni.algorithms.compression.v2.pytorch.pruning.tools.NormalSparsityAllocator\nclass BlockSparsityAllocator(SparsityAllocator):\n def __init__(self, pruner, block_sparse_size):\n super().__init__(pruner, dim=None, block_sparse_size=block_sparse_size, continuous_mask=True)\n\n def generate_sparsity(self, metrics):\n masks = {}\n for name, wrapper in self.pruner.get_modules_wrapper().items():\n # wrapper.config['total_sparsity'] can get the configured sparsity ratio for this wrapped module\n sparsity_rate = wrapper.config['total_sparsity']\n # get metric for this wrapped module\n metric = metrics[name]\n # mask the metric with old mask, if the masked position need never recover,\n # just keep this is ok if you are new in NNI pruning\n if self.continuous_mask:\n metric *= self._compress_mask(wrapper.weight_mask)\n # convert sparsity ratio to prune number\n prune_num = int(sparsity_rate * metric.numel())\n # calculate the metric threshold\n threshold = torch.topk(metric.view(-1), prune_num, largest=False)[0].max()\n # generate mask, keep the metric positions that metric values greater than the threshold\n mask = torch.gt(metric, threshold).type_as(metric)\n # expand the mask to weight size, if the block is masked, this block will be filled with zeros,\n # otherwise filled with ones\n masks[name] = self._expand_mask(name, mask)\n # merge the new mask with old mask, if the masked position need never recover,\n # just keep this is ok if you are new in NNI pruning\n if self.continuous_mask:\n masks[name]['weight'] *= wrapper.weight_mask\n return masks" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Customize the pruner.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "class BlockL1NormPruner(BasicPruner):\n def __init__(self, model, config_list, block_sparse_size):\n self.block_sparse_size = block_sparse_size\n super().__init__(model, config_list)\n\n # Implement reset_tools is enough for this pruner.\n def reset_tools(self):\n if self.data_collector is None:\n self.data_collector = WeightDataCollector(self)\n else:\n self.data_collector.reset()\n if self.metrics_calculator is None:\n self.metrics_calculator = BlockNormMetricsCalculator(self.block_sparse_size)\n if self.sparsity_allocator is None:\n self.sparsity_allocator = BlockSparsityAllocator(self, self.block_sparse_size)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Try this pruner.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Define a simple model.\nclass TestModel(torch.nn.Module):\n def __init__(self) -> None:\n super().__init__()\n self.fc1 = torch.nn.Linear(4, 8)\n self.fc2 = torch.nn.Linear(8, 4)\n\n def forward(self, x):\n return self.fc2(self.fc1(x))\n\nmodel = TestModel()\nconfig_list = [{'op_types': ['Linear'], 'total_sparsity': 0.5}]\n# use 2x2 block\n_, masks = BlockL1NormPruner(model, config_list, [2, 2]).compress()\n\n# show the generated masks\nprint('fc1 masks:\\n', masks['fc1']['weight'])\nprint('fc2 masks:\\n', masks['fc2']['weight'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This time we successfully define a new pruner with pruning block granularity!\nNote that we don't put validation logic in this example, like ``_validate_config_before_canonical``,\nbut for a robust implementation, we suggest you involve the validation logic.\n\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/docs/source/tutorials/pruning_customize.py b/docs/source/tutorials/pruning_customize.py new file mode 100644 index 0000000000000000000000000000000000000000..278b6fce638d02f25f5f4d0f47ea9cd82f30cd79 --- /dev/null +++ b/docs/source/tutorials/pruning_customize.py @@ -0,0 +1,174 @@ +""" +Customize Basic Pruner +====================== + +Users can easily customize a basic pruner in NNI. A large number of basic modules have been provided and can be reused. +Follow the NNI pruning interface, users only need to focus on their creative parts without worrying about other regular modules. + +In this tutorial, we show how to customize a basic pruner. + +Concepts +-------- + +NNI abstracts the basic pruning process into three steps, collecting data, calculating metrics, allocating sparsity. +Most pruning algorithms rely on a metric to decide where should be pruned. Using L1 norm pruner as an example, +the first step is collecting model weights, the second step is calculating L1 norm for weight per output channel, +the third step is ranking L1 norm metric and masking the output channels that have small L1 norm. + +In NNI basic pruner, these three step is implement as ``DataCollector``, ``MetricsCalculator`` and ``SparsityAllocator``. + +- ``DataCollector``: This module take pruner as initialize parameter. + It will get the relevant information of the model from the pruner, + and sometimes it will also hook the model to get input, output or gradient of a layer or a tensor. + It can also patch optimizer if some special steps need to be executed before or after ``optimizer.step()``. + +- ``MetricsCalculator``: This module will take the data collected from the ``DataCollector``, + then calculate the metrics. The metric shape is usually reduced from the data shape. + The ``dim`` taken by ``MetricsCalculator`` means which dimension will be kept after calculate metrics. + i.e., the collected data shape is (10, 20, 30), and the ``dim`` is 1, then the dimension-1 will be kept, + the output metrics shape should be (20,). + +- ``SparsityAllocator``: This module take the metrics and generate the masks. + Different ``SparsityAllocator`` has different masks generation strategies. + A common and simple strategy is sorting the metrics' values and calculating a threshold according to the configured sparsity, + mask the positions which metric value smaller than the threshold. + The ``dim`` taken by ``SparsityAllocator`` means the metrics are for which dimension, the mask will be expanded to weight shape. + i.e., the metric shape is (20,), the corresponding layer weight shape is (20, 40), and the ``dim`` is 0. + ``SparsityAllocator`` will first generate a mask with shape (20,), then expand this mask to shape (20, 40). + +Simple Example: Customize a Block-L1NormPruner +---------------------------------------------- + +NNI already have L1NormPruner, but for the reason of reproducing the paper and reducing user configuration items, +it only support pruning layer output channels. In this example, we will customize a pruner that supports block granularity for Linear. + +Note that you don't need to implement all these three kinds of tools for each time, +NNI supports many predefined tools, and you can directly use these to customize your own pruner. +This is a tutorial so we show how to define all these three kinds of pruning tools. + +Customize the pruning tools used by the pruner at first. +""" + +import torch +from nni.algorithms.compression.v2.pytorch.pruning.basic_pruner import BasicPruner +from nni.algorithms.compression.v2.pytorch.pruning.tools import ( + DataCollector, + MetricsCalculator, + SparsityAllocator +) + + +# This data collector collects weight in wrapped module as data. +# The wrapped module is the module configured in pruner's config_list. +# This implementation is similar as nni.algorithms.compression.v2.pytorch.pruning.tools.WeightDataCollector +class WeightDataCollector(DataCollector): + def collect(self): + data = {} + # get_modules_wrapper will get all the wrapper in the compressor (pruner), + # it returns a dict with format {wrapper_name: wrapper}, + # use wrapper.module to get the wrapped module. + for _, wrapper in self.compressor.get_modules_wrapper().items(): + data[wrapper.name] = wrapper.module.weight.data + # return {wrapper_name: weight_data} + return data + + +class BlockNormMetricsCalculator(MetricsCalculator): + def __init__(self, block_sparse_size): + # Because we will keep all dimension with block granularity, so fix ``dim=None``, + # means all dimensions will be kept. + super().__init__(dim=None, block_sparse_size=block_sparse_size) + + def calculate_metrics(self, data): + data_length = len(self.block_sparse_size) + reduce_unfold_dims = list(range(data_length, 2 * data_length)) + + metrics = {} + for name, t in data.items(): + # Unfold t as block size, and calculate L1 Norm for each block. + for dim, size in enumerate(self.block_sparse_size): + t = t.unfold(dim, size, size) + metrics[name] = t.norm(dim=reduce_unfold_dims, p=1) + # return {wrapper_name: block_metric} + return metrics + + +# This implementation is similar as nni.algorithms.compression.v2.pytorch.pruning.tools.NormalSparsityAllocator +class BlockSparsityAllocator(SparsityAllocator): + def __init__(self, pruner, block_sparse_size): + super().__init__(pruner, dim=None, block_sparse_size=block_sparse_size, continuous_mask=True) + + def generate_sparsity(self, metrics): + masks = {} + for name, wrapper in self.pruner.get_modules_wrapper().items(): + # wrapper.config['total_sparsity'] can get the configured sparsity ratio for this wrapped module + sparsity_rate = wrapper.config['total_sparsity'] + # get metric for this wrapped module + metric = metrics[name] + # mask the metric with old mask, if the masked position need never recover, + # just keep this is ok if you are new in NNI pruning + if self.continuous_mask: + metric *= self._compress_mask(wrapper.weight_mask) + # convert sparsity ratio to prune number + prune_num = int(sparsity_rate * metric.numel()) + # calculate the metric threshold + threshold = torch.topk(metric.view(-1), prune_num, largest=False)[0].max() + # generate mask, keep the metric positions that metric values greater than the threshold + mask = torch.gt(metric, threshold).type_as(metric) + # expand the mask to weight size, if the block is masked, this block will be filled with zeros, + # otherwise filled with ones + masks[name] = self._expand_mask(name, mask) + # merge the new mask with old mask, if the masked position need never recover, + # just keep this is ok if you are new in NNI pruning + if self.continuous_mask: + masks[name]['weight'] *= wrapper.weight_mask + return masks + + +# %% +# Customize the pruner. + +class BlockL1NormPruner(BasicPruner): + def __init__(self, model, config_list, block_sparse_size): + self.block_sparse_size = block_sparse_size + super().__init__(model, config_list) + + # Implement reset_tools is enough for this pruner. + def reset_tools(self): + if self.data_collector is None: + self.data_collector = WeightDataCollector(self) + else: + self.data_collector.reset() + if self.metrics_calculator is None: + self.metrics_calculator = BlockNormMetricsCalculator(self.block_sparse_size) + if self.sparsity_allocator is None: + self.sparsity_allocator = BlockSparsityAllocator(self, self.block_sparse_size) + + +# %% +# Try this pruner. + +# Define a simple model. +class TestModel(torch.nn.Module): + def __init__(self) -> None: + super().__init__() + self.fc1 = torch.nn.Linear(4, 8) + self.fc2 = torch.nn.Linear(8, 4) + + def forward(self, x): + return self.fc2(self.fc1(x)) + +model = TestModel() +config_list = [{'op_types': ['Linear'], 'total_sparsity': 0.5}] +# use 2x2 block +_, masks = BlockL1NormPruner(model, config_list, [2, 2]).compress() + +# show the generated masks +print('fc1 masks:\n', masks['fc1']['weight']) +print('fc2 masks:\n', masks['fc2']['weight']) + + +# %% +# This time we successfully define a new pruner with pruning block granularity! +# Note that we don't put validation logic in this example, like ``_validate_config_before_canonical``, +# but for a robust implementation, we suggest you involve the validation logic. diff --git a/docs/source/tutorials/pruning_customize.py.md5 b/docs/source/tutorials/pruning_customize.py.md5 new file mode 100644 index 0000000000000000000000000000000000000000..3ae92c7513f73eb544e8572aeaa2ab56eb359a01 --- /dev/null +++ b/docs/source/tutorials/pruning_customize.py.md5 @@ -0,0 +1 @@ +5b92fe6666938105b07998c198077299 \ No newline at end of file diff --git a/docs/source/tutorials/pruning_customize.rst b/docs/source/tutorials/pruning_customize.rst new file mode 100644 index 0000000000000000000000000000000000000000..4f32862cfcaad89b55d986bd4584c4ecee88afdc --- /dev/null +++ b/docs/source/tutorials/pruning_customize.rst @@ -0,0 +1,285 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "tutorials/pruning_customize.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_tutorials_pruning_customize.py: + + +Customize Basic Pruner +====================== + +Users can easily customize a basic pruner in NNI. A large number of basic modules have been provided and can be reused. +Follow the NNI pruning interface, users only need to focus on their creative parts without worrying about other regular modules. + +In this tutorial, we show how to customize a basic pruner. + +Concepts +-------- + +NNI abstracts the basic pruning process into three steps, collecting data, calculating metrics, allocating sparsity. +Most pruning algorithms rely on a metric to decide where should be pruned. Using L1 norm pruner as an example, +the first step is collecting model weights, the second step is calculating L1 norm for weight per output channel, +the third step is ranking L1 norm metric and masking the output channels that have small L1 norm. + +In NNI basic pruner, these three step is implement as ``DataCollector``, ``MetricsCalculator`` and ``SparsityAllocator``. + +- ``DataCollector``: This module take pruner as initialize parameter. + It will get the relevant information of the model from the pruner, + and sometimes it will also hook the model to get input, output or gradient of a layer or a tensor. + It can also patch optimizer if some special steps need to be executed before or after ``optimizer.step()``. + +- ``MetricsCalculator``: This module will take the data collected from the ``DataCollector``, + then calculate the metrics. The metric shape is usually reduced from the data shape. + The ``dim`` taken by ``MetricsCalculator`` means which dimension will be kept after calculate metrics. + i.e., the collected data shape is (10, 20, 30), and the ``dim`` is 1, then the dimension-1 will be kept, + the output metrics shape should be (20,). + +- ``SparsityAllocator``: This module take the metrics and generate the masks. + Different ``SparsityAllocator`` has different masks generation strategies. + A common and simple strategy is sorting the metrics' values and calculating a threshold according to the configured sparsity, + mask the positions which metric value smaller than the threshold. + The ``dim`` taken by ``SparsityAllocator`` means the metrics are for which dimension, the mask will be expanded to weight shape. + i.e., the metric shape is (20,), the corresponding layer weight shape is (20, 40), and the ``dim`` is 0. + ``SparsityAllocator`` will first generate a mask with shape (20,), then expand this mask to shape (20, 40). + +Simple Example: Customize a Block-L1NormPruner +---------------------------------------------- + +NNI already have L1NormPruner, but for the reason of reproducing the paper and reducing user configuration items, +it only support pruning layer output channels. In this example, we will customize a pruner that supports block granularity for Linear. + +Note that you don't need to implement all these three kinds of tools for each time, +NNI supports many predefined tools, and you can directly use these to customize your own pruner. +This is a tutorial so we show how to define all these three kinds of pruning tools. + +Customize the pruning tools used by the pruner at first. + +.. GENERATED FROM PYTHON SOURCE LINES 51-128 + +.. code-block:: default + + + import torch + from nni.algorithms.compression.v2.pytorch.pruning.basic_pruner import BasicPruner + from nni.algorithms.compression.v2.pytorch.pruning.tools import ( + DataCollector, + MetricsCalculator, + SparsityAllocator + ) + + + # This data collector collects weight in wrapped module as data. + # The wrapped module is the module configured in pruner's config_list. + # This implementation is similar as nni.algorithms.compression.v2.pytorch.pruning.tools.WeightDataCollector + class WeightDataCollector(DataCollector): + def collect(self): + data = {} + # get_modules_wrapper will get all the wrapper in the compressor (pruner), + # it returns a dict with format {wrapper_name: wrapper}, + # use wrapper.module to get the wrapped module. + for _, wrapper in self.compressor.get_modules_wrapper().items(): + data[wrapper.name] = wrapper.module.weight.data + # return {wrapper_name: weight_data} + return data + + + class BlockNormMetricsCalculator(MetricsCalculator): + def __init__(self, block_sparse_size): + # Because we will keep all dimension with block granularity, so fix ``dim=None``, + # means all dimensions will be kept. + super().__init__(dim=None, block_sparse_size=block_sparse_size) + + def calculate_metrics(self, data): + data_length = len(self.block_sparse_size) + reduce_unfold_dims = list(range(data_length, 2 * data_length)) + + metrics = {} + for name, t in data.items(): + # Unfold t as block size, and calculate L1 Norm for each block. + for dim, size in enumerate(self.block_sparse_size): + t = t.unfold(dim, size, size) + metrics[name] = t.norm(dim=reduce_unfold_dims, p=1) + # return {wrapper_name: block_metric} + return metrics + + + # This implementation is similar as nni.algorithms.compression.v2.pytorch.pruning.tools.NormalSparsityAllocator + class BlockSparsityAllocator(SparsityAllocator): + def __init__(self, pruner, block_sparse_size): + super().__init__(pruner, dim=None, block_sparse_size=block_sparse_size, continuous_mask=True) + + def generate_sparsity(self, metrics): + masks = {} + for name, wrapper in self.pruner.get_modules_wrapper().items(): + # wrapper.config['total_sparsity'] can get the configured sparsity ratio for this wrapped module + sparsity_rate = wrapper.config['total_sparsity'] + # get metric for this wrapped module + metric = metrics[name] + # mask the metric with old mask, if the masked position need never recover, + # just keep this is ok if you are new in NNI pruning + if self.continuous_mask: + metric *= self._compress_mask(wrapper.weight_mask) + # convert sparsity ratio to prune number + prune_num = int(sparsity_rate * metric.numel()) + # calculate the metric threshold + threshold = torch.topk(metric.view(-1), prune_num, largest=False)[0].max() + # generate mask, keep the metric positions that metric values greater than the threshold + mask = torch.gt(metric, threshold).type_as(metric) + # expand the mask to weight size, if the block is masked, this block will be filled with zeros, + # otherwise filled with ones + masks[name] = self._expand_mask(name, mask) + # merge the new mask with old mask, if the masked position need never recover, + # just keep this is ok if you are new in NNI pruning + if self.continuous_mask: + masks[name]['weight'] *= wrapper.weight_mask + return masks + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 129-130 + +Customize the pruner. + +.. GENERATED FROM PYTHON SOURCE LINES 130-148 + +.. code-block:: default + + + class BlockL1NormPruner(BasicPruner): + def __init__(self, model, config_list, block_sparse_size): + self.block_sparse_size = block_sparse_size + super().__init__(model, config_list) + + # Implement reset_tools is enough for this pruner. + def reset_tools(self): + if self.data_collector is None: + self.data_collector = WeightDataCollector(self) + else: + self.data_collector.reset() + if self.metrics_calculator is None: + self.metrics_calculator = BlockNormMetricsCalculator(self.block_sparse_size) + if self.sparsity_allocator is None: + self.sparsity_allocator = BlockSparsityAllocator(self, self.block_sparse_size) + + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 149-150 + +Try this pruner. + +.. GENERATED FROM PYTHON SOURCE LINES 150-171 + +.. code-block:: default + + + # Define a simple model. + class TestModel(torch.nn.Module): + def __init__(self) -> None: + super().__init__() + self.fc1 = torch.nn.Linear(4, 8) + self.fc2 = torch.nn.Linear(8, 4) + + def forward(self, x): + return self.fc2(self.fc1(x)) + + model = TestModel() + config_list = [{'op_types': ['Linear'], 'total_sparsity': 0.5}] + # use 2x2 block + _, masks = BlockL1NormPruner(model, config_list, [2, 2]).compress() + + # show the generated masks + print('fc1 masks:\n', masks['fc1']['weight']) + print('fc2 masks:\n', masks['fc2']['weight']) + + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + fc1 masks: + tensor([[0., 0., 0., 0.], + [0., 0., 0., 0.], + [0., 0., 0., 0.], + [0., 0., 0., 0.], + [1., 1., 1., 1.], + [1., 1., 1., 1.], + [1., 1., 1., 1.], + [1., 1., 1., 1.]]) + fc2 masks: + tensor([[0., 0., 0., 0., 1., 1., 1., 1.], + [0., 0., 0., 0., 1., 1., 1., 1.], + [0., 0., 0., 0., 1., 1., 1., 1.], + [0., 0., 0., 0., 1., 1., 1., 1.]]) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 172-175 + +This time we successfully define a new pruner with pruning block granularity! +Note that we don't put validation logic in this example, like ``_validate_config_before_canonical``, +but for a robust implementation, we suggest you involve the validation logic. + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 1.175 seconds) + + +.. _sphx_glr_download_tutorials_pruning_customize.py: + + +.. only :: html + + .. container:: sphx-glr-footer + :class: sphx-glr-footer-example + + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: pruning_customize.py ` + + + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: pruning_customize.ipynb ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/pruning_customize_codeobj.pickle b/docs/source/tutorials/pruning_customize_codeobj.pickle new file mode 100644 index 0000000000000000000000000000000000000000..335f30263167ae26669dcec44c16b0de6e1ec5e9 Binary files /dev/null and b/docs/source/tutorials/pruning_customize_codeobj.pickle differ diff --git a/docs/source/tutorials/pruning_quick_start_mnist.ipynb b/docs/source/tutorials/pruning_quick_start_mnist.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..65389f50ac4d423f4a8c34c2b93bd765c804cfab --- /dev/null +++ b/docs/source/tutorials/pruning_quick_start_mnist.ipynb @@ -0,0 +1,173 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# Pruning Quickstart\n\nModel pruning is a technique to reduce the model size and computation by reducing model weight size or intermediate state size.\nThere are three common practices for pruning a DNN model:\n\n#. Pre-training a model -> Pruning the model -> Fine-tuning the pruned model\n#. Pruning a model during training (i.e., pruning aware training) -> Fine-tuning the pruned model\n#. Pruning a model -> Training the pruned model from scratch\n\nNNI supports all of the above pruning practices by working on the key pruning stage.\nFollowing this tutorial for a quick look at how to use NNI to prune a model in a common practice.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Preparation\n\nIn this tutorial, we use a simple model and pre-trained on MNIST dataset.\nIf you are familiar with defining a model and training in pytorch, you can skip directly to `Pruning Model`_.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import torch\nimport torch.nn.functional as F\nfrom torch.optim import SGD\n\nfrom scripts.compression_mnist_model import TorchModel, trainer, evaluator, device\n\n# define the model\nmodel = TorchModel().to(device)\n\n# show the model structure, note that pruner will wrap the model layer.\nprint(model)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# define the optimizer and criterion for pre-training\n\noptimizer = SGD(model.parameters(), 1e-2)\ncriterion = F.nll_loss\n\n# pre-train and evaluate the model on MNIST dataset\nfor epoch in range(3):\n trainer(model, optimizer, criterion)\n evaluator(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Pruning Model\n\nUsing L1NormPruner to prune the model and generate the masks.\nUsually, a pruner requires original model and ``config_list`` as its inputs.\nDetailed about how to write ``config_list`` please refer :doc:`compression config specification <../compression/compression_config_list>`.\n\nThe following `config_list` means all layers whose type is `Linear` or `Conv2d` will be pruned,\nexcept the layer named `fc3`, because `fc3` is `exclude`.\nThe final sparsity ratio for each layer is 50%. The layer named `fc3` will not be pruned.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "config_list = [{\n 'sparsity_per_layer': 0.5,\n 'op_types': ['Linear', 'Conv2d']\n}, {\n 'exclude': True,\n 'op_names': ['fc3']\n}]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pruners usually require `model` and `config_list` as input arguments.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from nni.compression.pytorch.pruning import L1NormPruner\npruner = L1NormPruner(model, config_list)\n\n# show the wrapped model structure, `PrunerModuleWrapper` have wrapped the layers that configured in the config_list.\nprint(model)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# compress the model and generate the masks\n_, masks = pruner.compress()\n# show the masks sparsity\nfor name, mask in masks.items():\n print(name, ' sparsity : ', '{:.2}'.format(mask['weight'].sum() / mask['weight'].numel()))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Speedup the original model with masks, note that `ModelSpeedup` requires an unwrapped model.\nThe model becomes smaller after speedup,\nand reaches a higher sparsity ratio because `ModelSpeedup` will propagate the masks across layers.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# need to unwrap the model, if the model is wrapped before speedup\npruner._unwrap_model()\n\n# speedup the model, for more information about speedup, please refer :doc:`pruning_speedup`.\nfrom nni.compression.pytorch.speedup import ModelSpeedup\n\nModelSpeedup(model, torch.rand(3, 1, 28, 28).to(device), masks).speedup_model()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "the model will become real smaller after speedup\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Fine-tuning Compacted Model\nNote that if the model has been sped up, you need to re-initialize a new optimizer for fine-tuning.\nBecause speedup will replace the masked big layers with dense small ones.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "optimizer = SGD(model.parameters(), 1e-2)\nfor epoch in range(3):\n trainer(model, optimizer, criterion)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/docs/source/tutorials/pruning_quick_start_mnist.py b/docs/source/tutorials/pruning_quick_start_mnist.py new file mode 100644 index 0000000000000000000000000000000000000000..a2cee7d99bafdb44a6aab65c1f7cfcd62286683b --- /dev/null +++ b/docs/source/tutorials/pruning_quick_start_mnist.py @@ -0,0 +1,109 @@ +""" +Pruning Quickstart +================== + +Model pruning is a technique to reduce the model size and computation by reducing model weight size or intermediate state size. +There are three common practices for pruning a DNN model: + +#. Pre-training a model -> Pruning the model -> Fine-tuning the pruned model +#. Pruning a model during training (i.e., pruning aware training) -> Fine-tuning the pruned model +#. Pruning a model -> Training the pruned model from scratch + +NNI supports all of the above pruning practices by working on the key pruning stage. +Following this tutorial for a quick look at how to use NNI to prune a model in a common practice. +""" + +# %% +# Preparation +# ----------- +# +# In this tutorial, we use a simple model and pre-trained on MNIST dataset. +# If you are familiar with defining a model and training in pytorch, you can skip directly to `Pruning Model`_. + +import torch +import torch.nn.functional as F +from torch.optim import SGD + +from scripts.compression_mnist_model import TorchModel, trainer, evaluator, device + +# define the model +model = TorchModel().to(device) + +# show the model structure, note that pruner will wrap the model layer. +print(model) + +# %% + +# define the optimizer and criterion for pre-training + +optimizer = SGD(model.parameters(), 1e-2) +criterion = F.nll_loss + +# pre-train and evaluate the model on MNIST dataset +for epoch in range(3): + trainer(model, optimizer, criterion) + evaluator(model) + +# %% +# Pruning Model +# ------------- +# +# Using L1NormPruner to prune the model and generate the masks. +# Usually, a pruner requires original model and ``config_list`` as its inputs. +# Detailed about how to write ``config_list`` please refer :doc:`compression config specification <../compression/compression_config_list>`. +# +# The following `config_list` means all layers whose type is `Linear` or `Conv2d` will be pruned, +# except the layer named `fc3`, because `fc3` is `exclude`. +# The final sparsity ratio for each layer is 50%. The layer named `fc3` will not be pruned. + +config_list = [{ + 'sparsity_per_layer': 0.5, + 'op_types': ['Linear', 'Conv2d'] +}, { + 'exclude': True, + 'op_names': ['fc3'] +}] + +# %% +# Pruners usually require `model` and `config_list` as input arguments. + +from nni.compression.pytorch.pruning import L1NormPruner +pruner = L1NormPruner(model, config_list) + +# show the wrapped model structure, `PrunerModuleWrapper` have wrapped the layers that configured in the config_list. +print(model) + +# %% + +# compress the model and generate the masks +_, masks = pruner.compress() +# show the masks sparsity +for name, mask in masks.items(): + print(name, ' sparsity : ', '{:.2}'.format(mask['weight'].sum() / mask['weight'].numel())) + +# %% +# Speedup the original model with masks, note that `ModelSpeedup` requires an unwrapped model. +# The model becomes smaller after speedup, +# and reaches a higher sparsity ratio because `ModelSpeedup` will propagate the masks across layers. + +# need to unwrap the model, if the model is wrapped before speedup +pruner._unwrap_model() + +# speedup the model, for more information about speedup, please refer :doc:`pruning_speedup`. +from nni.compression.pytorch.speedup import ModelSpeedup + +ModelSpeedup(model, torch.rand(3, 1, 28, 28).to(device), masks).speedup_model() + +# %% +# the model will become real smaller after speedup +print(model) + +# %% +# Fine-tuning Compacted Model +# --------------------------- +# Note that if the model has been sped up, you need to re-initialize a new optimizer for fine-tuning. +# Because speedup will replace the masked big layers with dense small ones. + +optimizer = SGD(model.parameters(), 1e-2) +for epoch in range(3): + trainer(model, optimizer, criterion) diff --git a/docs/source/tutorials/pruning_quick_start_mnist.py.md5 b/docs/source/tutorials/pruning_quick_start_mnist.py.md5 new file mode 100644 index 0000000000000000000000000000000000000000..8952d6490ebfb30a3e24fc8f9d98e0aa033a92de --- /dev/null +++ b/docs/source/tutorials/pruning_quick_start_mnist.py.md5 @@ -0,0 +1 @@ +930f8ee2f57b70037e3231152a72606c \ No newline at end of file diff --git a/docs/source/tutorials/pruning_quick_start_mnist.rst b/docs/source/tutorials/pruning_quick_start_mnist.rst new file mode 100644 index 0000000000000000000000000000000000000000..9c685293a29a1945124019d1cf25678f2856d1af --- /dev/null +++ b/docs/source/tutorials/pruning_quick_start_mnist.rst @@ -0,0 +1,357 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "tutorials/pruning_quick_start_mnist.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_tutorials_pruning_quick_start_mnist.py: + + +Pruning Quickstart +================== + +Model pruning is a technique to reduce the model size and computation by reducing model weight size or intermediate state size. +There are three common practices for pruning a DNN model: + +#. Pre-training a model -> Pruning the model -> Fine-tuning the pruned model +#. Pruning a model during training (i.e., pruning aware training) -> Fine-tuning the pruned model +#. Pruning a model -> Training the pruned model from scratch + +NNI supports all of the above pruning practices by working on the key pruning stage. +Following this tutorial for a quick look at how to use NNI to prune a model in a common practice. + +.. GENERATED FROM PYTHON SOURCE LINES 17-22 + +Preparation +----------- + +In this tutorial, we use a simple model and pre-trained on MNIST dataset. +If you are familiar with defining a model and training in pytorch, you can skip directly to `Pruning Model`_. + +.. GENERATED FROM PYTHON SOURCE LINES 22-35 + +.. code-block:: default + + + import torch + import torch.nn.functional as F + from torch.optim import SGD + + from scripts.compression_mnist_model import TorchModel, trainer, evaluator, device + + # define the model + model = TorchModel().to(device) + + # show the model structure, note that pruner will wrap the model layer. + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + TorchModel( + (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1)) + (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1)) + (fc1): Linear(in_features=256, out_features=120, bias=True) + (fc2): Linear(in_features=120, out_features=84, bias=True) + (fc3): Linear(in_features=84, out_features=10, bias=True) + (relu1): ReLU() + (relu2): ReLU() + (relu3): ReLU() + (relu4): ReLU() + (pool1): MaxPool2d(kernel_size=(2, 2), stride=(2, 2), padding=0, dilation=1, ceil_mode=False) + (pool2): MaxPool2d(kernel_size=(2, 2), stride=(2, 2), padding=0, dilation=1, ceil_mode=False) + ) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 36-47 + +.. code-block:: default + + + # define the optimizer and criterion for pre-training + + optimizer = SGD(model.parameters(), 1e-2) + criterion = F.nll_loss + + # pre-train and evaluate the model on MNIST dataset + for epoch in range(3): + trainer(model, optimizer, criterion) + evaluator(model) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + Average test loss: 0.5368, Accuracy: 8321/10000 (83%) + Average test loss: 0.3092, Accuracy: 9104/10000 (91%) + Average test loss: 0.2070, Accuracy: 9380/10000 (94%) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 48-58 + +Pruning Model +------------- + +Using L1NormPruner to prune the model and generate the masks. +Usually, a pruner requires original model and ``config_list`` as its inputs. +Detailed about how to write ``config_list`` please refer :doc:`compression config specification <../compression/compression_config_list>`. + +The following `config_list` means all layers whose type is `Linear` or `Conv2d` will be pruned, +except the layer named `fc3`, because `fc3` is `exclude`. +The final sparsity ratio for each layer is 50%. The layer named `fc3` will not be pruned. + +.. GENERATED FROM PYTHON SOURCE LINES 58-67 + +.. code-block:: default + + + config_list = [{ + 'sparsity_per_layer': 0.5, + 'op_types': ['Linear', 'Conv2d'] + }, { + 'exclude': True, + 'op_names': ['fc3'] + }] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 68-69 + +Pruners usually require `model` and `config_list` as input arguments. + +.. GENERATED FROM PYTHON SOURCE LINES 69-76 + +.. code-block:: default + + + from nni.compression.pytorch.pruning import L1NormPruner + pruner = L1NormPruner(model, config_list) + + # show the wrapped model structure, `PrunerModuleWrapper` have wrapped the layers that configured in the config_list. + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + TorchModel( + (conv1): PrunerModuleWrapper( + (module): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1)) + ) + (conv2): PrunerModuleWrapper( + (module): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1)) + ) + (fc1): PrunerModuleWrapper( + (module): Linear(in_features=256, out_features=120, bias=True) + ) + (fc2): PrunerModuleWrapper( + (module): Linear(in_features=120, out_features=84, bias=True) + ) + (fc3): Linear(in_features=84, out_features=10, bias=True) + (relu1): ReLU() + (relu2): ReLU() + (relu3): ReLU() + (relu4): ReLU() + (pool1): MaxPool2d(kernel_size=(2, 2), stride=(2, 2), padding=0, dilation=1, ceil_mode=False) + (pool2): MaxPool2d(kernel_size=(2, 2), stride=(2, 2), padding=0, dilation=1, ceil_mode=False) + ) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 77-84 + +.. code-block:: default + + + # compress the model and generate the masks + _, masks = pruner.compress() + # show the masks sparsity + for name, mask in masks.items(): + print(name, ' sparsity : ', '{:.2}'.format(mask['weight'].sum() / mask['weight'].numel())) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + conv1 sparsity : 0.5 + conv2 sparsity : 0.5 + fc1 sparsity : 0.5 + fc2 sparsity : 0.5 + + + + +.. GENERATED FROM PYTHON SOURCE LINES 85-88 + +Speedup the original model with masks, note that `ModelSpeedup` requires an unwrapped model. +The model becomes smaller after speedup, +and reaches a higher sparsity ratio because `ModelSpeedup` will propagate the masks across layers. + +.. GENERATED FROM PYTHON SOURCE LINES 88-97 + +.. code-block:: default + + + # need to unwrap the model, if the model is wrapped before speedup + pruner._unwrap_model() + + # speedup the model, for more information about speedup, please refer :doc:`pruning_speedup`. + from nni.compression.pytorch.speedup import ModelSpeedup + + ModelSpeedup(model, torch.rand(3, 1, 28, 28).to(device), masks).speedup_model() + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + aten::log_softmax is not Supported! Please report an issue at https://github.com/microsoft/nni. Thanks~ + Note: .aten::log_softmax.12 does not have corresponding mask inference object + /home/nishang/anaconda3/envs/MCM/lib/python3.9/site-packages/torch/_tensor.py:1013: UserWarning: The .grad attribute of a Tensor that is not a leaf Tensor is being accessed. Its .grad attribute won't be populated during autograd.backward(). If you indeed want the .grad field to be populated for a non-leaf Tensor, use .retain_grad() on the non-leaf Tensor. If you access the non-leaf Tensor by mistake, make sure you access the leaf Tensor instead. See github.com/pytorch/pytorch/pull/30531 for more informations. (Triggered internally at /opt/conda/conda-bld/pytorch_1640811803361/work/build/aten/src/ATen/core/TensorBody.h:417.) + return self._grad + + + + +.. GENERATED FROM PYTHON SOURCE LINES 98-99 + +the model will become real smaller after speedup + +.. GENERATED FROM PYTHON SOURCE LINES 99-101 + +.. code-block:: default + + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + TorchModel( + (conv1): Conv2d(1, 3, kernel_size=(5, 5), stride=(1, 1)) + (conv2): Conv2d(3, 8, kernel_size=(5, 5), stride=(1, 1)) + (fc1): Linear(in_features=128, out_features=60, bias=True) + (fc2): Linear(in_features=60, out_features=42, bias=True) + (fc3): Linear(in_features=42, out_features=10, bias=True) + (relu1): ReLU() + (relu2): ReLU() + (relu3): ReLU() + (relu4): ReLU() + (pool1): MaxPool2d(kernel_size=(2, 2), stride=(2, 2), padding=0, dilation=1, ceil_mode=False) + (pool2): MaxPool2d(kernel_size=(2, 2), stride=(2, 2), padding=0, dilation=1, ceil_mode=False) + ) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 102-106 + +Fine-tuning Compacted Model +--------------------------- +Note that if the model has been sped up, you need to re-initialize a new optimizer for fine-tuning. +Because speedup will replace the masked big layers with dense small ones. + +.. GENERATED FROM PYTHON SOURCE LINES 106-110 + +.. code-block:: default + + + optimizer = SGD(model.parameters(), 1e-2) + for epoch in range(3): + trainer(model, optimizer, criterion) + + + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 58.337 seconds) + + +.. _sphx_glr_download_tutorials_pruning_quick_start_mnist.py: + + +.. only :: html + + .. container:: sphx-glr-footer + :class: sphx-glr-footer-example + + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: pruning_quick_start_mnist.py ` + + + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: pruning_quick_start_mnist.ipynb ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/pruning_quick_start_mnist_codeobj.pickle b/docs/source/tutorials/pruning_quick_start_mnist_codeobj.pickle new file mode 100644 index 0000000000000000000000000000000000000000..436554a7c076f33c1cb77190764d97d3987465d0 Binary files /dev/null and b/docs/source/tutorials/pruning_quick_start_mnist_codeobj.pickle differ diff --git a/docs/source/tutorials/pruning_quick_start_mnist_zh.rst b/docs/source/tutorials/pruning_quick_start_mnist_zh.rst new file mode 100644 index 0000000000000000000000000000000000000000..b529bbb1402a5661920ddd66d488a83bf9408a01 --- /dev/null +++ b/docs/source/tutorials/pruning_quick_start_mnist_zh.rst @@ -0,0 +1,332 @@ +.. 5f266ace988c9ca9e44555fdc497e9ba + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_tutorials_pruning_quick_start_mnist.py: + + +模型剪枝入门 +============ + +模型剪枝是一种通过减小模型权重规模或中间状态规模来减小模型大小和计算量的技术。 +修剪 DNN 模型有三种常见做法: + +#. 训练一个模型 -> 对模型进行剪枝 -> 对剪枝后模型进行微调 +#. 在模型训练过程中进行剪枝 -> 对剪枝后模型进行微调 +#. 对模型进行剪枝 -> 从头训练剪枝后模型 + +NNI 主要通过在剪枝阶段进行工作来支持上述所有剪枝过程。 +通过本教程可以快速了解如何在常见实践中使用 NNI 修剪模型。 + +.. GENERATED FROM PYTHON SOURCE LINES 17-22 + +准备工作 +-------- + +在本教程中,我们使用一个简单的模型在 MNIST 数据集上进行了预训练。 +如果你熟悉在 pytorch 中定义模型和训练模型,可以直接跳到 `模型剪枝`_。 + +.. GENERATED FROM PYTHON SOURCE LINES 22-35 + +.. code-block:: default + + + import torch + import torch.nn.functional as F + from torch.optim import SGD + + from scripts.compression_mnist_model import TorchModel, trainer, evaluator, device + + # define the model + model = TorchModel().to(device) + + # show the model structure, note that pruner will wrap the model layer. + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + TorchModel( + (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1)) + (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1)) + (fc1): Linear(in_features=256, out_features=120, bias=True) + (fc2): Linear(in_features=120, out_features=84, bias=True) + (fc3): Linear(in_features=84, out_features=10, bias=True) + ) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 36-47 + +.. code-block:: default + + + # define the optimizer and criterion for pre-training + + optimizer = SGD(model.parameters(), 1e-2) + criterion = F.nll_loss + + # pre-train and evaluate the model on MNIST dataset + for epoch in range(3): + trainer(model, optimizer, criterion) + evaluator(model) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + Average test loss: 0.5266, Accuracy: 8345/10000 (83%) + Average test loss: 0.2713, Accuracy: 9209/10000 (92%) + Average test loss: 0.1919, Accuracy: 9356/10000 (94%) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 48-58 + +模型剪枝 +-------- + +使用 L1NormPruner 对模型进行剪枝并生成掩码。 +通常情况下,pruner 需要原始模型和一个 ``config_list`` 作为输入参数。 +具体关于如何写 ``config_list`` 请参考 :doc:`compression config specification <../compression/compression_config_list>`。 + +以下 `config_list` 表示 pruner 将修剪类型为 `Linear` 或 `Conv2d` 的所有层除了名为 `fc3` 的层,因为 `fc3` 被设置为 `exclude`。 +每层的最终稀疏率是 50%。而名为 `fc3` 的层将不会被修剪。 + +.. GENERATED FROM PYTHON SOURCE LINES 58-67 + +.. code-block:: default + + + config_list = [{ + 'sparsity_per_layer': 0.5, + 'op_types': ['Linear', 'Conv2d'] + }, { + 'exclude': True, + 'op_names': ['fc3'] + }] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 68-69 + +Pruners usually require `model` and `config_list` as input arguments. + +.. GENERATED FROM PYTHON SOURCE LINES 69-76 + +.. code-block:: default + + + from nni.compression.pytorch.pruning import L1NormPruner + pruner = L1NormPruner(model, config_list) + + # show the wrapped model structure, `PrunerModuleWrapper` have wrapped the layers that configured in the config_list. + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + TorchModel( + (conv1): PrunerModuleWrapper( + (module): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1)) + ) + (conv2): PrunerModuleWrapper( + (module): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1)) + ) + (fc1): PrunerModuleWrapper( + (module): Linear(in_features=256, out_features=120, bias=True) + ) + (fc2): PrunerModuleWrapper( + (module): Linear(in_features=120, out_features=84, bias=True) + ) + (fc3): Linear(in_features=84, out_features=10, bias=True) + ) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 77-84 + +.. code-block:: default + + + # compress the model and generate the masks + _, masks = pruner.compress() + # show the masks sparsity + for name, mask in masks.items(): + print(name, ' sparsity : ', '{:.2}'.format(mask['weight'].sum() / mask['weight'].numel())) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + conv1 sparsity : 0.5 + conv2 sparsity : 0.5 + fc1 sparsity : 0.5 + fc2 sparsity : 0.5 + + + + +.. GENERATED FROM PYTHON SOURCE LINES 85-88 + +使用 NNI 的模型加速功能和 pruner 生成好的 masks 对原始模型进行加速,注意 `ModelSpeedup` 需要 unwrapped 的模型。 +模型会在加速之后真正的在规模上变小,并且可能会达到相比于 masks 更大的稀疏率,这是因为 `ModelSpeedup` 会自动在模型中传播稀疏, +识别由于掩码带来的冗余权重。 + +.. GENERATED FROM PYTHON SOURCE LINES 88-97 + +.. code-block:: default + + + # need to unwrap the model, if the model is wrapped before speedup + pruner._unwrap_model() + + # speedup the model + from nni.compression.pytorch.speedup import ModelSpeedup + + ModelSpeedup(model, torch.rand(3, 1, 28, 28).to(device), masks).speedup_model() + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + aten::log_softmax is not Supported! Please report an issue at https://github.com/microsoft/nni. Thanks~ + Note: .aten::log_softmax.12 does not have corresponding mask inference object + /home/ningshang/anaconda3/envs/nni-dev/lib/python3.8/site-packages/torch/_tensor.py:1013: UserWarning: The .grad attribute of a Tensor that is not a leaf Tensor is being accessed. Its .grad attribute won't be populated during autograd.backward(). If you indeed want the .grad field to be populated for a non-leaf Tensor, use .retain_grad() on the non-leaf Tensor. If you access the non-leaf Tensor by mistake, make sure you access the leaf Tensor instead. See github.com/pytorch/pytorch/pull/30531 for more informations. (Triggered internally at aten/src/ATen/core/TensorBody.h:417.) + return self._grad + + + + +.. GENERATED FROM PYTHON SOURCE LINES 98-99 + +模型在加速之后变小了。 + +.. GENERATED FROM PYTHON SOURCE LINES 99-101 + +.. code-block:: default + + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + TorchModel( + (conv1): Conv2d(1, 3, kernel_size=(5, 5), stride=(1, 1)) + (conv2): Conv2d(3, 8, kernel_size=(5, 5), stride=(1, 1)) + (fc1): Linear(in_features=128, out_features=60, bias=True) + (fc2): Linear(in_features=60, out_features=42, bias=True) + (fc3): Linear(in_features=42, out_features=10, bias=True) + ) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 102-106 + +微调压缩好的紧凑模型 +-------------------- + +注意当前的模型已经经过了加速,如果你需要微调模型,请重新生成 optimizer。 +这是因为在加速过程中进行了层替换,原来的 optimizer 已经不适用于现在的新模型了。 + +.. GENERATED FROM PYTHON SOURCE LINES 106-110 + +.. code-block:: default + + + optimizer = SGD(model.parameters(), 1e-2) + for epoch in range(3): + trainer(model, optimizer, criterion) + + + + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 1 minutes 24.976 seconds) + + +.. _sphx_glr_download_tutorials_pruning_quick_start_mnist.py: + + +.. only :: html + + .. container:: sphx-glr-footer + :class: sphx-glr-footer-example + + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: pruning_quick_start_mnist.py ` + + + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: pruning_quick_start_mnist.ipynb ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/pruning_speedup.ipynb b/docs/source/tutorials/pruning_speedup.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..04090cba1de1e57e3c8c679eeeae1368512d8c79 --- /dev/null +++ b/docs/source/tutorials/pruning_speedup.ipynb @@ -0,0 +1,140 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# Speedup Model with Mask\n\n## Introduction\n\nPruning algorithms usually use weight masks to simulate the real pruning. Masks can be used\nto check model performance of a specific pruning (or sparsity), but there is no real speedup.\nSince model speedup is the ultimate goal of model pruning, we try to provide a tool to users\nto convert a model to a smaller one based on user provided masks (the masks come from the\npruning algorithms).\n\nThere are two types of pruning. One is fine-grained pruning, it does not change the shape of weights,\nand input/output tensors. Sparse kernel is required to speedup a fine-grained pruned layer.\nThe other is coarse-grained pruning (e.g., channels), shape of weights and input/output tensors usually change due to such pruning.\nTo speedup this kind of pruning, there is no need to use sparse kernel, just replace the pruned layer with smaller one.\nSince the support of sparse kernels in community is limited,\nwe only support the speedup of coarse-grained pruning and leave the support of fine-grained pruning in future.\n\n## Design and Implementation\n\nTo speedup a model, the pruned layers should be replaced, either replaced with smaller layer for coarse-grained mask,\nor replaced with sparse kernel for fine-grained mask. Coarse-grained mask usually changes the shape of weights or input/output tensors,\nthus, we should do shape inference to check are there other unpruned layers should be replaced as well due to shape change.\nTherefore, in our design, there are two main steps: first, do shape inference to find out all the modules that should be replaced;\nsecond, replace the modules.\n\nThe first step requires topology (i.e., connections) of the model, we use ``jit.trace`` to obtain the model graph for PyTorch.\nThe new shape of module is auto-inference by NNI, the unchanged parts of outputs during forward and inputs during backward are prepared for reduct.\nFor each type of module, we should prepare a function for module replacement.\nThe module replacement function returns a newly created module which is smaller.\n\n## Usage\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Generate a mask for the model at first.\nWe usually use a NNI pruner to generate the masks then use ``ModelSpeedup`` to compact the model.\nBut in fact ``ModelSpeedup`` is a relatively independent tool, so you can use it independently.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import torch\nfrom scripts.compression_mnist_model import TorchModel, device\n\nmodel = TorchModel().to(device)\n# masks = {layer_name: {'weight': weight_mask, 'bias': bias_mask}}\nconv1_mask = torch.ones_like(model.conv1.weight.data)\n# mask the first three output channels in conv1\nconv1_mask[0: 3] = 0\nmasks = {'conv1': {'weight': conv1_mask}}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Show the original model structure.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Roughly test the original model inference speed.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import time\nstart = time.time()\nmodel(torch.rand(128, 1, 28, 28).to(device))\nprint('Original Model - Elapsed Time : ', time.time() - start)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Speedup the model and show the model structure after speedup.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from nni.compression.pytorch import ModelSpeedup\nModelSpeedup(model, torch.rand(10, 1, 28, 28).to(device), masks).speedup_model()\nprint(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Roughly test the model after speedup inference speed.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "start = time.time()\nmodel(torch.rand(128, 1, 28, 28).to(device))\nprint('Speedup Model - Elapsed Time : ', time.time() - start)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For combining usage of ``Pruner`` masks generation with ``ModelSpeedup``,\nplease refer to :doc:`Pruning Quick Start `.\n\nNOTE: The current implementation supports PyTorch 1.3.1 or newer.\n\n## Limitations\n\nFor PyTorch we can only replace modules, if functions in ``forward`` should be replaced,\nour current implementation does not work. One workaround is make the function a PyTorch module.\n\nIf you want to speedup your own model which cannot supported by the current implementation,\nyou need implement the replace function for module replacement, welcome to contribute.\n\n## Speedup Results of Examples\n\nThe code of these experiments can be found :githublink:`here `.\n\nThese result are tested on the `legacy pruning framework `_, new results will coming soon.\n\n### slim pruner example\n\non one V100 GPU,\ninput tensor: ``torch.randn(64, 3, 32, 32)``\n\n.. list-table::\n :header-rows: 1\n :widths: auto\n\n * - Times\n - Mask Latency\n - Speedup Latency\n * - 1\n - 0.01197\n - 0.005107\n * - 2\n - 0.02019\n - 0.008769\n * - 4\n - 0.02733\n - 0.014809\n * - 8\n - 0.04310\n - 0.027441\n * - 16\n - 0.07731\n - 0.05008\n * - 32\n - 0.14464\n - 0.10027\n\n### fpgm pruner example\n\non cpu,\ninput tensor: ``torch.randn(64, 1, 28, 28)``\\ ,\ntoo large variance\n\n.. list-table::\n :header-rows: 1\n :widths: auto\n\n * - Times\n - Mask Latency\n - Speedup Latency\n * - 1\n - 0.01383\n - 0.01839\n * - 2\n - 0.01167\n - 0.003558\n * - 4\n - 0.01636\n - 0.01088\n * - 40\n - 0.14412\n - 0.08268\n * - 40\n - 1.29385\n - 0.14408\n * - 40\n - 0.41035\n - 0.46162\n * - 400\n - 6.29020\n - 5.82143\n\n### l1filter pruner example\n\non one V100 GPU,\ninput tensor: ``torch.randn(64, 3, 32, 32)``\n\n.. list-table::\n :header-rows: 1\n :widths: auto\n\n * - Times\n - Mask Latency\n - Speedup Latency\n * - 1\n - 0.01026\n - 0.003677\n * - 2\n - 0.01657\n - 0.008161\n * - 4\n - 0.02458\n - 0.020018\n * - 8\n - 0.03498\n - 0.025504\n * - 16\n - 0.06757\n - 0.047523\n * - 32\n - 0.10487\n - 0.086442\n\n### APoZ pruner example\n\non one V100 GPU,\ninput tensor: ``torch.randn(64, 3, 32, 32)``\n\n.. list-table::\n :header-rows: 1\n :widths: auto\n\n * - Times\n - Mask Latency\n - Speedup Latency\n * - 1\n - 0.01389\n - 0.004208\n * - 2\n - 0.01628\n - 0.008310\n * - 4\n - 0.02521\n - 0.014008\n * - 8\n - 0.03386\n - 0.023923\n * - 16\n - 0.06042\n - 0.046183\n * - 32\n - 0.12421\n - 0.087113\n\n### SimulatedAnnealing pruner example\n\nIn this experiment, we use SimulatedAnnealing pruner to prune the resnet18 on the cifar10 dataset.\nWe measure the latencies and accuracies of the pruned model under different sparsity ratios, as shown in the following figure.\nThe latency is measured on one V100 GPU and the input tensor is ``torch.randn(128, 3, 32, 32)``.\n\n\n\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/docs/source/tutorials/pruning_speedup.py b/docs/source/tutorials/pruning_speedup.py new file mode 100644 index 0000000000000000000000000000000000000000..7cb4fd45606c43eb5647727cf89cb7c97f61965e --- /dev/null +++ b/docs/source/tutorials/pruning_speedup.py @@ -0,0 +1,239 @@ +""" +Speedup Model with Mask +======================== + +Introduction +------------ + +Pruning algorithms usually use weight masks to simulate the real pruning. Masks can be used +to check model performance of a specific pruning (or sparsity), but there is no real speedup. +Since model speedup is the ultimate goal of model pruning, we try to provide a tool to users +to convert a model to a smaller one based on user provided masks (the masks come from the +pruning algorithms). + +There are two types of pruning. One is fine-grained pruning, it does not change the shape of weights, +and input/output tensors. Sparse kernel is required to speedup a fine-grained pruned layer. +The other is coarse-grained pruning (e.g., channels), shape of weights and input/output tensors usually change due to such pruning. +To speedup this kind of pruning, there is no need to use sparse kernel, just replace the pruned layer with smaller one. +Since the support of sparse kernels in community is limited, +we only support the speedup of coarse-grained pruning and leave the support of fine-grained pruning in future. + +Design and Implementation +------------------------- + +To speedup a model, the pruned layers should be replaced, either replaced with smaller layer for coarse-grained mask, +or replaced with sparse kernel for fine-grained mask. Coarse-grained mask usually changes the shape of weights or input/output tensors, +thus, we should do shape inference to check are there other unpruned layers should be replaced as well due to shape change. +Therefore, in our design, there are two main steps: first, do shape inference to find out all the modules that should be replaced; +second, replace the modules. + +The first step requires topology (i.e., connections) of the model, we use ``jit.trace`` to obtain the model graph for PyTorch. +The new shape of module is auto-inference by NNI, the unchanged parts of outputs during forward and inputs during backward are prepared for reduct. +For each type of module, we should prepare a function for module replacement. +The module replacement function returns a newly created module which is smaller. + +Usage +----- + +""" + +# %% +# Generate a mask for the model at first. +# We usually use a NNI pruner to generate the masks then use ``ModelSpeedup`` to compact the model. +# But in fact ``ModelSpeedup`` is a relatively independent tool, so you can use it independently. + +import torch +from scripts.compression_mnist_model import TorchModel, device + +model = TorchModel().to(device) +# masks = {layer_name: {'weight': weight_mask, 'bias': bias_mask}} +conv1_mask = torch.ones_like(model.conv1.weight.data) +# mask the first three output channels in conv1 +conv1_mask[0: 3] = 0 +masks = {'conv1': {'weight': conv1_mask}} + +# %% +# Show the original model structure. +print(model) + +# %% +# Roughly test the original model inference speed. +import time +start = time.time() +model(torch.rand(128, 1, 28, 28).to(device)) +print('Original Model - Elapsed Time : ', time.time() - start) + +# %% +# Speedup the model and show the model structure after speedup. +from nni.compression.pytorch import ModelSpeedup +ModelSpeedup(model, torch.rand(10, 1, 28, 28).to(device), masks).speedup_model() +print(model) + +# %% +# Roughly test the model after speedup inference speed. +start = time.time() +model(torch.rand(128, 1, 28, 28).to(device)) +print('Speedup Model - Elapsed Time : ', time.time() - start) + +# %% +# For combining usage of ``Pruner`` masks generation with ``ModelSpeedup``, +# please refer to :doc:`Pruning Quick Start `. +# +# NOTE: The current implementation supports PyTorch 1.3.1 or newer. +# +# Limitations +# ----------- +# +# For PyTorch we can only replace modules, if functions in ``forward`` should be replaced, +# our current implementation does not work. One workaround is make the function a PyTorch module. +# +# If you want to speedup your own model which cannot supported by the current implementation, +# you need implement the replace function for module replacement, welcome to contribute. +# +# Speedup Results of Examples +# --------------------------- +# +# The code of these experiments can be found :githublink:`here `. +# +# These result are tested on the `legacy pruning framework `_, new results will coming soon. +# +# slim pruner example +# ^^^^^^^^^^^^^^^^^^^ +# +# on one V100 GPU, +# input tensor: ``torch.randn(64, 3, 32, 32)`` +# +# .. list-table:: +# :header-rows: 1 +# :widths: auto +# +# * - Times +# - Mask Latency +# - Speedup Latency +# * - 1 +# - 0.01197 +# - 0.005107 +# * - 2 +# - 0.02019 +# - 0.008769 +# * - 4 +# - 0.02733 +# - 0.014809 +# * - 8 +# - 0.04310 +# - 0.027441 +# * - 16 +# - 0.07731 +# - 0.05008 +# * - 32 +# - 0.14464 +# - 0.10027 +# +# fpgm pruner example +# ^^^^^^^^^^^^^^^^^^^ +# +# on cpu, +# input tensor: ``torch.randn(64, 1, 28, 28)``\ , +# too large variance +# +# .. list-table:: +# :header-rows: 1 +# :widths: auto +# +# * - Times +# - Mask Latency +# - Speedup Latency +# * - 1 +# - 0.01383 +# - 0.01839 +# * - 2 +# - 0.01167 +# - 0.003558 +# * - 4 +# - 0.01636 +# - 0.01088 +# * - 40 +# - 0.14412 +# - 0.08268 +# * - 40 +# - 1.29385 +# - 0.14408 +# * - 40 +# - 0.41035 +# - 0.46162 +# * - 400 +# - 6.29020 +# - 5.82143 +# +# l1filter pruner example +# ^^^^^^^^^^^^^^^^^^^^^^^ +# +# on one V100 GPU, +# input tensor: ``torch.randn(64, 3, 32, 32)`` +# +# .. list-table:: +# :header-rows: 1 +# :widths: auto +# +# * - Times +# - Mask Latency +# - Speedup Latency +# * - 1 +# - 0.01026 +# - 0.003677 +# * - 2 +# - 0.01657 +# - 0.008161 +# * - 4 +# - 0.02458 +# - 0.020018 +# * - 8 +# - 0.03498 +# - 0.025504 +# * - 16 +# - 0.06757 +# - 0.047523 +# * - 32 +# - 0.10487 +# - 0.086442 +# +# APoZ pruner example +# ^^^^^^^^^^^^^^^^^^^ +# +# on one V100 GPU, +# input tensor: ``torch.randn(64, 3, 32, 32)`` +# +# .. list-table:: +# :header-rows: 1 +# :widths: auto +# +# * - Times +# - Mask Latency +# - Speedup Latency +# * - 1 +# - 0.01389 +# - 0.004208 +# * - 2 +# - 0.01628 +# - 0.008310 +# * - 4 +# - 0.02521 +# - 0.014008 +# * - 8 +# - 0.03386 +# - 0.023923 +# * - 16 +# - 0.06042 +# - 0.046183 +# * - 32 +# - 0.12421 +# - 0.087113 +# +# SimulatedAnnealing pruner example +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# +# In this experiment, we use SimulatedAnnealing pruner to prune the resnet18 on the cifar10 dataset. +# We measure the latencies and accuracies of the pruned model under different sparsity ratios, as shown in the following figure. +# The latency is measured on one V100 GPU and the input tensor is ``torch.randn(128, 3, 32, 32)``. +# +# .. image:: ../../img/SA_latency_accuracy.png diff --git a/docs/source/tutorials/pruning_speedup.py.md5 b/docs/source/tutorials/pruning_speedup.py.md5 new file mode 100644 index 0000000000000000000000000000000000000000..9f9728e3d9571b01e18473e1202a647204ffa0d1 --- /dev/null +++ b/docs/source/tutorials/pruning_speedup.py.md5 @@ -0,0 +1 @@ +dc5c2369666206591238118f0f746e46 \ No newline at end of file diff --git a/docs/source/tutorials/pruning_speedup.rst b/docs/source/tutorials/pruning_speedup.rst new file mode 100644 index 0000000000000000000000000000000000000000..068d7a9eb7ee265919a357a96f1dc27640f7a2a4 --- /dev/null +++ b/docs/source/tutorials/pruning_speedup.rst @@ -0,0 +1,415 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "tutorials/pruning_speedup.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_tutorials_pruning_speedup.py: + + +Speedup Model with Mask +======================== + +Introduction +------------ + +Pruning algorithms usually use weight masks to simulate the real pruning. Masks can be used +to check model performance of a specific pruning (or sparsity), but there is no real speedup. +Since model speedup is the ultimate goal of model pruning, we try to provide a tool to users +to convert a model to a smaller one based on user provided masks (the masks come from the +pruning algorithms). + +There are two types of pruning. One is fine-grained pruning, it does not change the shape of weights, +and input/output tensors. Sparse kernel is required to speedup a fine-grained pruned layer. +The other is coarse-grained pruning (e.g., channels), shape of weights and input/output tensors usually change due to such pruning. +To speedup this kind of pruning, there is no need to use sparse kernel, just replace the pruned layer with smaller one. +Since the support of sparse kernels in community is limited, +we only support the speedup of coarse-grained pruning and leave the support of fine-grained pruning in future. + +Design and Implementation +------------------------- + +To speedup a model, the pruned layers should be replaced, either replaced with smaller layer for coarse-grained mask, +or replaced with sparse kernel for fine-grained mask. Coarse-grained mask usually changes the shape of weights or input/output tensors, +thus, we should do shape inference to check are there other unpruned layers should be replaced as well due to shape change. +Therefore, in our design, there are two main steps: first, do shape inference to find out all the modules that should be replaced; +second, replace the modules. + +The first step requires topology (i.e., connections) of the model, we use ``jit.trace`` to obtain the model graph for PyTorch. +The new shape of module is auto-inference by NNI, the unchanged parts of outputs during forward and inputs during backward are prepared for reduct. +For each type of module, we should prepare a function for module replacement. +The module replacement function returns a newly created module which is smaller. + +Usage +----- + +.. GENERATED FROM PYTHON SOURCE LINES 41-44 + +Generate a mask for the model at first. +We usually use a NNI pruner to generate the masks then use ``ModelSpeedup`` to compact the model. +But in fact ``ModelSpeedup`` is a relatively independent tool, so you can use it independently. + +.. GENERATED FROM PYTHON SOURCE LINES 44-55 + +.. code-block:: default + + + import torch + from scripts.compression_mnist_model import TorchModel, device + + model = TorchModel().to(device) + # masks = {layer_name: {'weight': weight_mask, 'bias': bias_mask}} + conv1_mask = torch.ones_like(model.conv1.weight.data) + # mask the first three output channels in conv1 + conv1_mask[0: 3] = 0 + masks = {'conv1': {'weight': conv1_mask}} + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 56-57 + +Show the original model structure. + +.. GENERATED FROM PYTHON SOURCE LINES 57-59 + +.. code-block:: default + + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + TorchModel( + (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1)) + (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1)) + (fc1): Linear(in_features=256, out_features=120, bias=True) + (fc2): Linear(in_features=120, out_features=84, bias=True) + (fc3): Linear(in_features=84, out_features=10, bias=True) + (relu1): ReLU() + (relu2): ReLU() + (relu3): ReLU() + (relu4): ReLU() + (pool1): MaxPool2d(kernel_size=(2, 2), stride=(2, 2), padding=0, dilation=1, ceil_mode=False) + (pool2): MaxPool2d(kernel_size=(2, 2), stride=(2, 2), padding=0, dilation=1, ceil_mode=False) + ) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 60-61 + +Roughly test the original model inference speed. + +.. GENERATED FROM PYTHON SOURCE LINES 61-66 + +.. code-block:: default + + import time + start = time.time() + model(torch.rand(128, 1, 28, 28).to(device)) + print('Original Model - Elapsed Time : ', time.time() - start) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + Original Model - Elapsed Time : 0.5094916820526123 + + + + +.. GENERATED FROM PYTHON SOURCE LINES 67-68 + +Speedup the model and show the model structure after speedup. + +.. GENERATED FROM PYTHON SOURCE LINES 68-72 + +.. code-block:: default + + from nni.compression.pytorch import ModelSpeedup + ModelSpeedup(model, torch.rand(10, 1, 28, 28).to(device), masks).speedup_model() + print(model) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + aten::log_softmax is not Supported! Please report an issue at https://github.com/microsoft/nni. Thanks~ + Note: .aten::log_softmax.12 does not have corresponding mask inference object + /home/nishang/anaconda3/envs/MCM/lib/python3.9/site-packages/torch/_tensor.py:1013: UserWarning: The .grad attribute of a Tensor that is not a leaf Tensor is being accessed. Its .grad attribute won't be populated during autograd.backward(). If you indeed want the .grad field to be populated for a non-leaf Tensor, use .retain_grad() on the non-leaf Tensor. If you access the non-leaf Tensor by mistake, make sure you access the leaf Tensor instead. See github.com/pytorch/pytorch/pull/30531 for more informations. (Triggered internally at /opt/conda/conda-bld/pytorch_1640811803361/work/build/aten/src/ATen/core/TensorBody.h:417.) + return self._grad + TorchModel( + (conv1): Conv2d(1, 3, kernel_size=(5, 5), stride=(1, 1)) + (conv2): Conv2d(3, 16, kernel_size=(5, 5), stride=(1, 1)) + (fc1): Linear(in_features=256, out_features=120, bias=True) + (fc2): Linear(in_features=120, out_features=84, bias=True) + (fc3): Linear(in_features=84, out_features=10, bias=True) + (relu1): ReLU() + (relu2): ReLU() + (relu3): ReLU() + (relu4): ReLU() + (pool1): MaxPool2d(kernel_size=(2, 2), stride=(2, 2), padding=0, dilation=1, ceil_mode=False) + (pool2): MaxPool2d(kernel_size=(2, 2), stride=(2, 2), padding=0, dilation=1, ceil_mode=False) + ) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 73-74 + +Roughly test the model after speedup inference speed. + +.. GENERATED FROM PYTHON SOURCE LINES 74-78 + +.. code-block:: default + + start = time.time() + model(torch.rand(128, 1, 28, 28).to(device)) + print('Speedup Model - Elapsed Time : ', time.time() - start) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + Speedup Model - Elapsed Time : 0.006000041961669922 + + + + +.. GENERATED FROM PYTHON SOURCE LINES 79-240 + +For combining usage of ``Pruner`` masks generation with ``ModelSpeedup``, +please refer to :doc:`Pruning Quick Start `. + +NOTE: The current implementation supports PyTorch 1.3.1 or newer. + +Limitations +----------- + +For PyTorch we can only replace modules, if functions in ``forward`` should be replaced, +our current implementation does not work. One workaround is make the function a PyTorch module. + +If you want to speedup your own model which cannot supported by the current implementation, +you need implement the replace function for module replacement, welcome to contribute. + +Speedup Results of Examples +--------------------------- + +The code of these experiments can be found :githublink:`here `. + +These result are tested on the `legacy pruning framework `_, new results will coming soon. + +slim pruner example +^^^^^^^^^^^^^^^^^^^ + +on one V100 GPU, +input tensor: ``torch.randn(64, 3, 32, 32)`` + +.. list-table:: + :header-rows: 1 + :widths: auto + + * - Times + - Mask Latency + - Speedup Latency + * - 1 + - 0.01197 + - 0.005107 + * - 2 + - 0.02019 + - 0.008769 + * - 4 + - 0.02733 + - 0.014809 + * - 8 + - 0.04310 + - 0.027441 + * - 16 + - 0.07731 + - 0.05008 + * - 32 + - 0.14464 + - 0.10027 + +fpgm pruner example +^^^^^^^^^^^^^^^^^^^ + +on cpu, +input tensor: ``torch.randn(64, 1, 28, 28)``\ , +too large variance + +.. list-table:: + :header-rows: 1 + :widths: auto + + * - Times + - Mask Latency + - Speedup Latency + * - 1 + - 0.01383 + - 0.01839 + * - 2 + - 0.01167 + - 0.003558 + * - 4 + - 0.01636 + - 0.01088 + * - 40 + - 0.14412 + - 0.08268 + * - 40 + - 1.29385 + - 0.14408 + * - 40 + - 0.41035 + - 0.46162 + * - 400 + - 6.29020 + - 5.82143 + +l1filter pruner example +^^^^^^^^^^^^^^^^^^^^^^^ + +on one V100 GPU, +input tensor: ``torch.randn(64, 3, 32, 32)`` + +.. list-table:: + :header-rows: 1 + :widths: auto + + * - Times + - Mask Latency + - Speedup Latency + * - 1 + - 0.01026 + - 0.003677 + * - 2 + - 0.01657 + - 0.008161 + * - 4 + - 0.02458 + - 0.020018 + * - 8 + - 0.03498 + - 0.025504 + * - 16 + - 0.06757 + - 0.047523 + * - 32 + - 0.10487 + - 0.086442 + +APoZ pruner example +^^^^^^^^^^^^^^^^^^^ + +on one V100 GPU, +input tensor: ``torch.randn(64, 3, 32, 32)`` + +.. list-table:: + :header-rows: 1 + :widths: auto + + * - Times + - Mask Latency + - Speedup Latency + * - 1 + - 0.01389 + - 0.004208 + * - 2 + - 0.01628 + - 0.008310 + * - 4 + - 0.02521 + - 0.014008 + * - 8 + - 0.03386 + - 0.023923 + * - 16 + - 0.06042 + - 0.046183 + * - 32 + - 0.12421 + - 0.087113 + +SimulatedAnnealing pruner example +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In this experiment, we use SimulatedAnnealing pruner to prune the resnet18 on the cifar10 dataset. +We measure the latencies and accuracies of the pruned model under different sparsity ratios, as shown in the following figure. +The latency is measured on one V100 GPU and the input tensor is ``torch.randn(128, 3, 32, 32)``. + +.. image:: ../../img/SA_latency_accuracy.png + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 4.528 seconds) + + +.. _sphx_glr_download_tutorials_pruning_speedup.py: + + +.. only :: html + + .. container:: sphx-glr-footer + :class: sphx-glr-footer-example + + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: pruning_speedup.py ` + + + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: pruning_speedup.ipynb ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/pruning_speedup_codeobj.pickle b/docs/source/tutorials/pruning_speedup_codeobj.pickle new file mode 100644 index 0000000000000000000000000000000000000000..84feb0712669541b7c126fdade9bfca2a53651af Binary files /dev/null and b/docs/source/tutorials/pruning_speedup_codeobj.pickle differ diff --git a/docs/source/tutorials/quantization_customize.ipynb b/docs/source/tutorials/quantization_customize.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..2d07a5d9d0d7ae38165a24068aaa114eb26e47bc --- /dev/null +++ b/docs/source/tutorials/quantization_customize.ipynb @@ -0,0 +1,79 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# Customize a new quantization algorithm\n\nTo write a new quantization algorithm, you can write a class that inherits ``nni.compression.pytorch.Quantizer``.\nThen, override the member functions with the logic of your algorithm. The member function to override is ``quantize_weight``.\n``quantize_weight`` directly returns the quantized weights rather than mask, because for quantization the quantized weights cannot be obtained by applying mask.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from nni.compression.pytorch import Quantizer\n\nclass YourQuantizer(Quantizer):\n def __init__(self, model, config_list):\n \"\"\"\n Suggest you to use the NNI defined spec for config\n \"\"\"\n super().__init__(model, config_list)\n\n def quantize_weight(self, weight, config, **kwargs):\n \"\"\"\n quantize should overload this method to quantize weight tensors.\n This method is effectively hooked to :meth:`forward` of the model.\n\n Parameters\n ----------\n weight : Tensor\n weight that needs to be quantized\n config : dict\n the configuration for weight quantization\n \"\"\"\n\n # Put your code to generate `new_weight` here\n new_weight = ...\n return new_weight\n\n def quantize_output(self, output, config, **kwargs):\n \"\"\"\n quantize should overload this method to quantize output.\n This method is effectively hooked to `:meth:`forward` of the model.\n\n Parameters\n ----------\n output : Tensor\n output that needs to be quantized\n config : dict\n the configuration for output quantization\n \"\"\"\n\n # Put your code to generate `new_output` here\n new_output = ...\n return new_output\n\n def quantize_input(self, *inputs, config, **kwargs):\n \"\"\"\n quantize should overload this method to quantize input.\n This method is effectively hooked to :meth:`forward` of the model.\n\n Parameters\n ----------\n inputs : Tensor\n inputs that needs to be quantized\n config : dict\n the configuration for inputs quantization\n \"\"\"\n\n # Put your code to generate `new_input` here\n new_input = ...\n return new_input\n\n def update_epoch(self, epoch_num):\n pass\n\n def step(self):\n \"\"\"\n Can do some processing based on the model or weights binded\n in the func bind_model\n \"\"\"\n pass" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Customize backward function\n\nSometimes it's necessary for a quantization operation to have a customized backward function,\nsuch as `Straight-Through Estimator `__\\ ,\nuser can customize a backward function as follow:\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from nni.compression.pytorch.compressor import Quantizer, QuantGrad, QuantType\n\nclass ClipGrad(QuantGrad):\n @staticmethod\n def quant_backward(tensor, grad_output, quant_type):\n \"\"\"\n This method should be overrided by subclass to provide customized backward function,\n default implementation is Straight-Through Estimator\n Parameters\n ----------\n tensor : Tensor\n input of quantization operation\n grad_output : Tensor\n gradient of the output of quantization operation\n quant_type : QuantType\n the type of quantization, it can be `QuantType.INPUT`, `QuantType.WEIGHT`, `QuantType.OUTPUT`,\n you can define different behavior for different types.\n Returns\n -------\n tensor\n gradient of the input of quantization operation\n \"\"\"\n\n # for quant_output function, set grad to zero if the absolute value of tensor is larger than 1\n if quant_type == QuantType.OUTPUT:\n grad_output[tensor.abs() > 1] = 0\n return grad_output\n\nclass _YourQuantizer(Quantizer):\n def __init__(self, model, config_list):\n super().__init__(model, config_list)\n # set your customized backward function to overwrite default backward function\n self.quant_grad = ClipGrad" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you do not customize ``QuantGrad``, the default backward is Straight-Through Estimator. \n\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/docs/source/tutorials/quantization_customize.py b/docs/source/tutorials/quantization_customize.py new file mode 100644 index 0000000000000000000000000000000000000000..9305e1978fc30ed62a275e0ae0410cce613379fd --- /dev/null +++ b/docs/source/tutorials/quantization_customize.py @@ -0,0 +1,123 @@ +""" +Customize a new quantization algorithm +====================================== + +To write a new quantization algorithm, you can write a class that inherits ``nni.compression.pytorch.Quantizer``. +Then, override the member functions with the logic of your algorithm. The member function to override is ``quantize_weight``. +``quantize_weight`` directly returns the quantized weights rather than mask, because for quantization the quantized weights cannot be obtained by applying mask. +""" + +from nni.compression.pytorch import Quantizer + +class YourQuantizer(Quantizer): + def __init__(self, model, config_list): + """ + Suggest you to use the NNI defined spec for config + """ + super().__init__(model, config_list) + + def quantize_weight(self, weight, config, **kwargs): + """ + quantize should overload this method to quantize weight tensors. + This method is effectively hooked to :meth:`forward` of the model. + + Parameters + ---------- + weight : Tensor + weight that needs to be quantized + config : dict + the configuration for weight quantization + """ + + # Put your code to generate `new_weight` here + new_weight = ... + return new_weight + + def quantize_output(self, output, config, **kwargs): + """ + quantize should overload this method to quantize output. + This method is effectively hooked to `:meth:`forward` of the model. + + Parameters + ---------- + output : Tensor + output that needs to be quantized + config : dict + the configuration for output quantization + """ + + # Put your code to generate `new_output` here + new_output = ... + return new_output + + def quantize_input(self, *inputs, config, **kwargs): + """ + quantize should overload this method to quantize input. + This method is effectively hooked to :meth:`forward` of the model. + + Parameters + ---------- + inputs : Tensor + inputs that needs to be quantized + config : dict + the configuration for inputs quantization + """ + + # Put your code to generate `new_input` here + new_input = ... + return new_input + + def update_epoch(self, epoch_num): + pass + + def step(self): + """ + Can do some processing based on the model or weights binded + in the func bind_model + """ + pass + +# %% +# Customize backward function +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# +# Sometimes it's necessary for a quantization operation to have a customized backward function, +# such as `Straight-Through Estimator `__\ , +# user can customize a backward function as follow: + +from nni.compression.pytorch.compressor import Quantizer, QuantGrad, QuantType + +class ClipGrad(QuantGrad): + @staticmethod + def quant_backward(tensor, grad_output, quant_type): + """ + This method should be overrided by subclass to provide customized backward function, + default implementation is Straight-Through Estimator + Parameters + ---------- + tensor : Tensor + input of quantization operation + grad_output : Tensor + gradient of the output of quantization operation + quant_type : QuantType + the type of quantization, it can be `QuantType.INPUT`, `QuantType.WEIGHT`, `QuantType.OUTPUT`, + you can define different behavior for different types. + Returns + ------- + tensor + gradient of the input of quantization operation + """ + + # for quant_output function, set grad to zero if the absolute value of tensor is larger than 1 + if quant_type == QuantType.OUTPUT: + grad_output[tensor.abs() > 1] = 0 + return grad_output + +class _YourQuantizer(Quantizer): + def __init__(self, model, config_list): + super().__init__(model, config_list) + # set your customized backward function to overwrite default backward function + self.quant_grad = ClipGrad + +# %% +# If you do not customize ``QuantGrad``, the default backward is Straight-Through Estimator. diff --git a/docs/source/tutorials/quantization_customize.py.md5 b/docs/source/tutorials/quantization_customize.py.md5 new file mode 100644 index 0000000000000000000000000000000000000000..c71bddacd5aba7ea5a4e38d1d9de409c818074a1 --- /dev/null +++ b/docs/source/tutorials/quantization_customize.py.md5 @@ -0,0 +1 @@ +387ac974594fa239c25479453b808ec8 \ No newline at end of file diff --git a/docs/source/tutorials/quantization_customize.rst b/docs/source/tutorials/quantization_customize.rst new file mode 100644 index 0000000000000000000000000000000000000000..e156df77bf3847014b1e969bb1429e5224fe4e5e --- /dev/null +++ b/docs/source/tutorials/quantization_customize.rst @@ -0,0 +1,200 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "tutorials/quantization_customize.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_tutorials_quantization_customize.py: + + +Customize a new quantization algorithm +====================================== + +To write a new quantization algorithm, you can write a class that inherits ``nni.compression.pytorch.Quantizer``. +Then, override the member functions with the logic of your algorithm. The member function to override is ``quantize_weight``. +``quantize_weight`` directly returns the quantized weights rather than mask, because for quantization the quantized weights cannot be obtained by applying mask. + +.. GENERATED FROM PYTHON SOURCE LINES 9-80 + +.. code-block:: default + + + from nni.compression.pytorch import Quantizer + + class YourQuantizer(Quantizer): + def __init__(self, model, config_list): + """ + Suggest you to use the NNI defined spec for config + """ + super().__init__(model, config_list) + + def quantize_weight(self, weight, config, **kwargs): + """ + quantize should overload this method to quantize weight tensors. + This method is effectively hooked to :meth:`forward` of the model. + + Parameters + ---------- + weight : Tensor + weight that needs to be quantized + config : dict + the configuration for weight quantization + """ + + # Put your code to generate `new_weight` here + new_weight = ... + return new_weight + + def quantize_output(self, output, config, **kwargs): + """ + quantize should overload this method to quantize output. + This method is effectively hooked to `:meth:`forward` of the model. + + Parameters + ---------- + output : Tensor + output that needs to be quantized + config : dict + the configuration for output quantization + """ + + # Put your code to generate `new_output` here + new_output = ... + return new_output + + def quantize_input(self, *inputs, config, **kwargs): + """ + quantize should overload this method to quantize input. + This method is effectively hooked to :meth:`forward` of the model. + + Parameters + ---------- + inputs : Tensor + inputs that needs to be quantized + config : dict + the configuration for inputs quantization + """ + + # Put your code to generate `new_input` here + new_input = ... + return new_input + + def update_epoch(self, epoch_num): + pass + + def step(self): + """ + Can do some processing based on the model or weights binded + in the func bind_model + """ + pass + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 81-87 + +Customize backward function +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Sometimes it's necessary for a quantization operation to have a customized backward function, +such as `Straight-Through Estimator `__\ , +user can customize a backward function as follow: + +.. GENERATED FROM PYTHON SOURCE LINES 87-122 + +.. code-block:: default + + + from nni.compression.pytorch.compressor import Quantizer, QuantGrad, QuantType + + class ClipGrad(QuantGrad): + @staticmethod + def quant_backward(tensor, grad_output, quant_type): + """ + This method should be overrided by subclass to provide customized backward function, + default implementation is Straight-Through Estimator + Parameters + ---------- + tensor : Tensor + input of quantization operation + grad_output : Tensor + gradient of the output of quantization operation + quant_type : QuantType + the type of quantization, it can be `QuantType.INPUT`, `QuantType.WEIGHT`, `QuantType.OUTPUT`, + you can define different behavior for different types. + Returns + ------- + tensor + gradient of the input of quantization operation + """ + + # for quant_output function, set grad to zero if the absolute value of tensor is larger than 1 + if quant_type == QuantType.OUTPUT: + grad_output[tensor.abs() > 1] = 0 + return grad_output + + class _YourQuantizer(Quantizer): + def __init__(self, model, config_list): + super().__init__(model, config_list) + # set your customized backward function to overwrite default backward function + self.quant_grad = ClipGrad + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 123-124 + +If you do not customize ``QuantGrad``, the default backward is Straight-Through Estimator. + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 0 minutes 1.269 seconds) + + +.. _sphx_glr_download_tutorials_quantization_customize.py: + + +.. only :: html + + .. container:: sphx-glr-footer + :class: sphx-glr-footer-example + + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: quantization_customize.py ` + + + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: quantization_customize.ipynb ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/quantization_customize_codeobj.pickle b/docs/source/tutorials/quantization_customize_codeobj.pickle new file mode 100644 index 0000000000000000000000000000000000000000..af4d95a375b38dfd033718612ae73f9810f52258 Binary files /dev/null and b/docs/source/tutorials/quantization_customize_codeobj.pickle differ diff --git a/docs/source/tutorials/quantization_quick_start_mnist.ipynb b/docs/source/tutorials/quantization_quick_start_mnist.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..1d9d3e40e21d0454ddd39453b87e6676505762f3 --- /dev/null +++ b/docs/source/tutorials/quantization_quick_start_mnist.ipynb @@ -0,0 +1,151 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# Quantization Quickstart\n\nQuantization reduces model size and speeds up inference time by reducing the number of bits required to represent weights or activations.\n\nIn NNI, both post-training quantization algorithms and quantization-aware training algorithms are supported.\nHere we use `QAT_Quantizer` as an example to show the usage of quantization in NNI.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Preparation\n\nIn this tutorial, we use a simple model and pre-train on MNIST dataset.\nIf you are familiar with defining a model and training in pytorch, you can skip directly to `Quantizing Model`_.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import torch\nimport torch.nn.functional as F\nfrom torch.optim import SGD\n\nfrom scripts.compression_mnist_model import TorchModel, trainer, evaluator, device, test_trt\n\n# define the model\nmodel = TorchModel().to(device)\n\n# define the optimizer and criterion for pre-training\n\noptimizer = SGD(model.parameters(), 1e-2)\ncriterion = F.nll_loss\n\n# pre-train and evaluate the model on MNIST dataset\nfor epoch in range(3):\n trainer(model, optimizer, criterion)\n evaluator(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Quantizing Model\n\nInitialize a `config_list`.\nDetailed about how to write ``config_list`` please refer :doc:`compression config specification <../compression/compression_config_list>`.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "config_list = [{\n 'quant_types': ['input', 'weight'],\n 'quant_bits': {'input': 8, 'weight': 8},\n 'op_types': ['Conv2d']\n}, {\n 'quant_types': ['output'],\n 'quant_bits': {'output': 8},\n 'op_types': ['ReLU']\n}, {\n 'quant_types': ['input', 'weight'],\n 'quant_bits': {'input': 8, 'weight': 8},\n 'op_names': ['fc1', 'fc2']\n}]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "finetuning the model by using QAT\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from nni.algorithms.compression.pytorch.quantization import QAT_Quantizer\ndummy_input = torch.rand(32, 1, 28, 28).to(device)\nquantizer = QAT_Quantizer(model, config_list, optimizer, dummy_input)\nquantizer.compress()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The model has now been wrapped, and quantization targets ('quant_types' setting in `config_list`)\nwill be quantized & dequantized for simulated quantization in the wrapped layers.\nQAT is a training-aware quantizer, it will update scale and zero point during training.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "for epoch in range(3):\n trainer(model, optimizer, criterion)\n evaluator(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "export model and get calibration_config\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "model_path = \"./log/mnist_model.pth\"\ncalibration_path = \"./log/mnist_calibration.pth\"\ncalibration_config = quantizer.export_model(model_path, calibration_path)\n\nprint(\"calibration_config: \", calibration_config)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "build tensorRT engine to make a real speedup, for more information about speedup, please refer :doc:`quantization_speedup`.\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from nni.compression.pytorch.quantization_speedup import ModelSpeedupTensorRT\ninput_shape = (32, 1, 28, 28)\nengine = ModelSpeedupTensorRT(model, input_shape, config=calibration_config, batchsize=32)\nengine.compress()\ntest_trt(engine)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/docs/source/tutorials/quantization_quick_start_mnist.py b/docs/source/tutorials/quantization_quick_start_mnist.py new file mode 100644 index 0000000000000000000000000000000000000000..c126e6fb4168ee2d588ee4ed358ce11a70416e2b --- /dev/null +++ b/docs/source/tutorials/quantization_quick_start_mnist.py @@ -0,0 +1,89 @@ +""" +Quantization Quickstart +======================= + +Quantization reduces model size and speeds up inference time by reducing the number of bits required to represent weights or activations. + +In NNI, both post-training quantization algorithms and quantization-aware training algorithms are supported. +Here we use `QAT_Quantizer` as an example to show the usage of quantization in NNI. +""" + +# %% +# Preparation +# ----------- +# +# In this tutorial, we use a simple model and pre-train on MNIST dataset. +# If you are familiar with defining a model and training in pytorch, you can skip directly to `Quantizing Model`_. + +import torch +import torch.nn.functional as F +from torch.optim import SGD + +from scripts.compression_mnist_model import TorchModel, trainer, evaluator, device, test_trt + +# define the model +model = TorchModel().to(device) + +# define the optimizer and criterion for pre-training + +optimizer = SGD(model.parameters(), 1e-2) +criterion = F.nll_loss + +# pre-train and evaluate the model on MNIST dataset +for epoch in range(3): + trainer(model, optimizer, criterion) + evaluator(model) + +# %% +# Quantizing Model +# ---------------- +# +# Initialize a `config_list`. +# Detailed about how to write ``config_list`` please refer :doc:`compression config specification <../compression/compression_config_list>`. + +config_list = [{ + 'quant_types': ['input', 'weight'], + 'quant_bits': {'input': 8, 'weight': 8}, + 'op_types': ['Conv2d'] +}, { + 'quant_types': ['output'], + 'quant_bits': {'output': 8}, + 'op_types': ['ReLU'] +}, { + 'quant_types': ['input', 'weight'], + 'quant_bits': {'input': 8, 'weight': 8}, + 'op_names': ['fc1', 'fc2'] +}] + +# %% +# finetuning the model by using QAT +from nni.algorithms.compression.pytorch.quantization import QAT_Quantizer +dummy_input = torch.rand(32, 1, 28, 28).to(device) +quantizer = QAT_Quantizer(model, config_list, optimizer, dummy_input) +quantizer.compress() + +# %% +# The model has now been wrapped, and quantization targets ('quant_types' setting in `config_list`) +# will be quantized & dequantized for simulated quantization in the wrapped layers. +# QAT is a training-aware quantizer, it will update scale and zero point during training. + +for epoch in range(3): + trainer(model, optimizer, criterion) + evaluator(model) + +# %% +# export model and get calibration_config +model_path = "./log/mnist_model.pth" +calibration_path = "./log/mnist_calibration.pth" +calibration_config = quantizer.export_model(model_path, calibration_path) + +print("calibration_config: ", calibration_config) + +# %% +# build tensorRT engine to make a real speedup, for more information about speedup, please refer :doc:`quantization_speedup`. + +from nni.compression.pytorch.quantization_speedup import ModelSpeedupTensorRT +input_shape = (32, 1, 28, 28) +engine = ModelSpeedupTensorRT(model, input_shape, config=calibration_config, batchsize=32) +engine.compress() +test_trt(engine) diff --git a/docs/source/tutorials/quantization_quick_start_mnist.py.md5 b/docs/source/tutorials/quantization_quick_start_mnist.py.md5 new file mode 100644 index 0000000000000000000000000000000000000000..fac5ad2ad3f62bb80a3222350644bfde941b5527 --- /dev/null +++ b/docs/source/tutorials/quantization_quick_start_mnist.py.md5 @@ -0,0 +1 @@ +bceaf8235b437428267b614af06634a0 \ No newline at end of file diff --git a/docs/source/tutorials/quantization_quick_start_mnist.rst b/docs/source/tutorials/quantization_quick_start_mnist.rst new file mode 100644 index 0000000000000000000000000000000000000000..10eaddb6323d4b55031632620124af0c5234697d --- /dev/null +++ b/docs/source/tutorials/quantization_quick_start_mnist.rst @@ -0,0 +1,290 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "tutorials/quantization_quick_start_mnist.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_tutorials_quantization_quick_start_mnist.py: + + +Quantization Quickstart +======================= + +Quantization reduces model size and speeds up inference time by reducing the number of bits required to represent weights or activations. + +In NNI, both post-training quantization algorithms and quantization-aware training algorithms are supported. +Here we use `QAT_Quantizer` as an example to show the usage of quantization in NNI. + +.. GENERATED FROM PYTHON SOURCE LINES 12-17 + +Preparation +----------- + +In this tutorial, we use a simple model and pre-train on MNIST dataset. +If you are familiar with defining a model and training in pytorch, you can skip directly to `Quantizing Model`_. + +.. GENERATED FROM PYTHON SOURCE LINES 17-37 + +.. code-block:: default + + + import torch + import torch.nn.functional as F + from torch.optim import SGD + + from scripts.compression_mnist_model import TorchModel, trainer, evaluator, device, test_trt + + # define the model + model = TorchModel().to(device) + + # define the optimizer and criterion for pre-training + + optimizer = SGD(model.parameters(), 1e-2) + criterion = F.nll_loss + + # pre-train and evaluate the model on MNIST dataset + for epoch in range(3): + trainer(model, optimizer, criterion) + evaluator(model) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + Average test loss: 0.7073, Accuracy: 7624/10000 (76%) + Average test loss: 0.2776, Accuracy: 9122/10000 (91%) + Average test loss: 0.1907, Accuracy: 9412/10000 (94%) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 38-43 + +Quantizing Model +---------------- + +Initialize a `config_list`. +Detailed about how to write ``config_list`` please refer :doc:`compression config specification <../compression/compression_config_list>`. + +.. GENERATED FROM PYTHON SOURCE LINES 43-58 + +.. code-block:: default + + + config_list = [{ + 'quant_types': ['input', 'weight'], + 'quant_bits': {'input': 8, 'weight': 8}, + 'op_types': ['Conv2d'] + }, { + 'quant_types': ['output'], + 'quant_bits': {'output': 8}, + 'op_types': ['ReLU'] + }, { + 'quant_types': ['input', 'weight'], + 'quant_bits': {'input': 8, 'weight': 8}, + 'op_names': ['fc1', 'fc2'] + }] + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 59-60 + +finetuning the model by using QAT + +.. GENERATED FROM PYTHON SOURCE LINES 60-65 + +.. code-block:: default + + from nni.algorithms.compression.pytorch.quantization import QAT_Quantizer + dummy_input = torch.rand(32, 1, 28, 28).to(device) + quantizer = QAT_Quantizer(model, config_list, optimizer, dummy_input) + quantizer.compress() + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + + TorchModel( + (conv1): QuantizerModuleWrapper( + (module): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1)) + ) + (conv2): QuantizerModuleWrapper( + (module): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1)) + ) + (fc1): QuantizerModuleWrapper( + (module): Linear(in_features=256, out_features=120, bias=True) + ) + (fc2): QuantizerModuleWrapper( + (module): Linear(in_features=120, out_features=84, bias=True) + ) + (fc3): Linear(in_features=84, out_features=10, bias=True) + (relu1): QuantizerModuleWrapper( + (module): ReLU() + ) + (relu2): QuantizerModuleWrapper( + (module): ReLU() + ) + (relu3): QuantizerModuleWrapper( + (module): ReLU() + ) + (relu4): QuantizerModuleWrapper( + (module): ReLU() + ) + (pool1): MaxPool2d(kernel_size=(2, 2), stride=(2, 2), padding=0, dilation=1, ceil_mode=False) + (pool2): MaxPool2d(kernel_size=(2, 2), stride=(2, 2), padding=0, dilation=1, ceil_mode=False) + ) + + + +.. GENERATED FROM PYTHON SOURCE LINES 66-69 + +The model has now been wrapped, and quantization targets ('quant_types' setting in `config_list`) +will be quantized & dequantized for simulated quantization in the wrapped layers. +QAT is a training-aware quantizer, it will update scale and zero point during training. + +.. GENERATED FROM PYTHON SOURCE LINES 69-74 + +.. code-block:: default + + + for epoch in range(3): + trainer(model, optimizer, criterion) + evaluator(model) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + Average test loss: 0.1542, Accuracy: 9529/10000 (95%) + Average test loss: 0.1133, Accuracy: 9664/10000 (97%) + Average test loss: 0.0919, Accuracy: 9726/10000 (97%) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 75-76 + +export model and get calibration_config + +.. GENERATED FROM PYTHON SOURCE LINES 76-82 + +.. code-block:: default + + model_path = "./log/mnist_model.pth" + calibration_path = "./log/mnist_calibration.pth" + calibration_config = quantizer.export_model(model_path, calibration_path) + + print("calibration_config: ", calibration_config) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + calibration_config: {'conv1': {'weight_bits': 8, 'weight_scale': tensor([0.0031], device='cuda:0'), 'weight_zero_point': tensor([76.], device='cuda:0'), 'input_bits': 8, 'tracked_min_input': -0.4242129623889923, 'tracked_max_input': 2.821486711502075}, 'conv2': {'weight_bits': 8, 'weight_scale': tensor([0.0018], device='cuda:0'), 'weight_zero_point': tensor([113.], device='cuda:0'), 'input_bits': 8, 'tracked_min_input': 0.0, 'tracked_max_input': 12.42452621459961}, 'fc1': {'weight_bits': 8, 'weight_scale': tensor([0.0011], device='cuda:0'), 'weight_zero_point': tensor([124.], device='cuda:0'), 'input_bits': 8, 'tracked_min_input': 0.0, 'tracked_max_input': 31.650196075439453}, 'fc2': {'weight_bits': 8, 'weight_scale': tensor([0.0013], device='cuda:0'), 'weight_zero_point': tensor([122.], device='cuda:0'), 'input_bits': 8, 'tracked_min_input': 0.0, 'tracked_max_input': 25.805370330810547}, 'relu1': {'output_bits': 8, 'tracked_min_output': 0.0, 'tracked_max_output': 12.499907493591309}, 'relu2': {'output_bits': 8, 'tracked_min_output': 0.0, 'tracked_max_output': 32.0243034362793}, 'relu3': {'output_bits': 8, 'tracked_min_output': 0.0, 'tracked_max_output': 26.491384506225586}, 'relu4': {'output_bits': 8, 'tracked_min_output': 0.0, 'tracked_max_output': 17.662996292114258}} + + + + +.. GENERATED FROM PYTHON SOURCE LINES 83-84 + +build tensorRT engine to make a real speedup, for more information about speedup, please refer :doc:`quantization_speedup`. + +.. GENERATED FROM PYTHON SOURCE LINES 84-90 + +.. code-block:: default + + + from nni.compression.pytorch.quantization_speedup import ModelSpeedupTensorRT + input_shape = (32, 1, 28, 28) + engine = ModelSpeedupTensorRT(model, input_shape, config=calibration_config, batchsize=32) + engine.compress() + test_trt(engine) + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + Loss: 0.09358334274291992 Accuracy: 97.21% + Inference elapsed_time (whole dataset): 0.04445981979370117s + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 1 minutes 36.499 seconds) + + +.. _sphx_glr_download_tutorials_quantization_quick_start_mnist.py: + + +.. only :: html + + .. container:: sphx-glr-footer + :class: sphx-glr-footer-example + + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: quantization_quick_start_mnist.py ` + + + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: quantization_quick_start_mnist.ipynb ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/quantization_quick_start_mnist_codeobj.pickle b/docs/source/tutorials/quantization_quick_start_mnist_codeobj.pickle new file mode 100644 index 0000000000000000000000000000000000000000..db853f1100c98bca758caa3641f526e92ddfad79 Binary files /dev/null and b/docs/source/tutorials/quantization_quick_start_mnist_codeobj.pickle differ diff --git a/docs/source/tutorials/quantization_speedup.ipynb b/docs/source/tutorials/quantization_speedup.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..cfbda8bc97b35de4ec6cc4e3d3b78d80d86bdb89 --- /dev/null +++ b/docs/source/tutorials/quantization_speedup.ipynb @@ -0,0 +1,115 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# SpeedUp Model with Calibration Config\n\n\n## Introduction\n\nDeep learning network has been computational intensive and memory intensive \nwhich increases the difficulty of deploying deep neural network model. Quantization is a \nfundamental technology which is widely used to reduce memory footprint and speedup inference \nprocess. Many frameworks begin to support quantization, but few of them support mixed precision \nquantization and get real speedup. Frameworks like `HAQ: Hardware-Aware Automated Quantization with Mixed Precision `__\\, only support simulated mixed precision quantization which will \nnot speedup the inference process. To get real speedup of mixed precision quantization and \nhelp people get the real feedback from hardware, we design a general framework with simple interface to allow NNI quantization algorithms to connect different \nDL model optimization backends (e.g., TensorRT, NNFusion), which gives users an end-to-end experience that after quantizing their model \nwith quantization algorithms, the quantized model can be directly speeded up with the connected optimization backend. NNI connects \nTensorRT at this stage, and will support more backends in the future.\n\n\n## Design and Implementation\n\nTo support speeding up mixed precision quantization, we divide framework into two part, frontend and backend. \nFrontend could be popular training frameworks such as PyTorch, TensorFlow etc. Backend could be inference \nframework for different hardwares, such as TensorRT. At present, we support PyTorch as frontend and \nTensorRT as backend. To convert PyTorch model to TensorRT engine, we leverage onnx as intermediate graph \nrepresentation. In this way, we convert PyTorch model to onnx model, then TensorRT parse onnx \nmodel to generate inference engine. \n\n\nQuantization aware training combines NNI quantization algorithm 'QAT' and NNI quantization speedup tool.\nUsers should set config to train quantized model using QAT algorithm(please refer to :doc:`NNI Quantization Algorithms <../compression/quantizer>` ).\nAfter quantization aware training, users can get new config with calibration parameters and model with quantized weight. By passing new config and model to quantization speedup tool, users can get real mixed precision speedup engine to do inference.\n\n\nAfter getting mixed precision engine, users can do inference with input data.\n\n\nNote\n\n\n* Recommend using \"cpu\"(host) as data device(for both inference data and calibration data) since data should be on host initially and it will be transposed to device before inference. If data type is not \"cpu\"(host), this tool will transpose it to \"cpu\" which may increases unnecessary overhead.\n* User can also do post-training quantization leveraging TensorRT directly(need to provide calibration dataset).\n* Not all op types are supported right now. At present, NNI supports Conv, Linear, Relu and MaxPool. More op types will be supported in the following release.\n\n\n## Prerequisite\nCUDA version >= 11.0\n\nTensorRT version >= 7.2\n\nNote\n\n* If you haven't installed TensorRT before or use the old version, please refer to `TensorRT Installation Guide `__\\ \n\n## Usage\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import torch\nimport torch.nn.functional as F\nfrom torch.optim import SGD\nfrom scripts.compression_mnist_model import TorchModel, device, trainer, evaluator, test_trt\n\nconfig_list = [{\n 'quant_types': ['input', 'weight'],\n 'quant_bits': {'input': 8, 'weight': 8},\n 'op_types': ['Conv2d']\n}, {\n 'quant_types': ['output'],\n 'quant_bits': {'output': 8},\n 'op_types': ['ReLU']\n}, {\n 'quant_types': ['input', 'weight'],\n 'quant_bits': {'input': 8, 'weight': 8},\n 'op_names': ['fc1', 'fc2']\n}]\n\nmodel = TorchModel().to(device)\noptimizer = SGD(model.parameters(), lr=0.01, momentum=0.5)\ncriterion = F.nll_loss\ndummy_input = torch.rand(32, 1, 28, 28).to(device)\n\nfrom nni.algorithms.compression.pytorch.quantization import QAT_Quantizer\nquantizer = QAT_Quantizer(model, config_list, optimizer, dummy_input)\nquantizer.compress()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "finetuning the model by using QAT\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "for epoch in range(3):\n trainer(model, optimizer, criterion)\n evaluator(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "export model and get calibration_config\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import os\nos.makedirs('log', exist_ok=True)\nmodel_path = \"./log/mnist_model.pth\"\ncalibration_path = \"./log/mnist_calibration.pth\"\ncalibration_config = quantizer.export_model(model_path, calibration_path)\n\nprint(\"calibration_config: \", calibration_config)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "build tensorRT engine to make a real speedup\n\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from nni.compression.pytorch.quantization_speedup import ModelSpeedupTensorRT\ninput_shape = (32, 1, 28, 28)\nengine = ModelSpeedupTensorRT(model, input_shape, config=calibration_config, batchsize=32)\nengine.compress()\ntest_trt(engine)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that NNI also supports post-training quantization directly, please refer to complete examples for detail.\n\nFor complete examples please refer to :githublink:`the code `.\n\nFor more parameters about the class 'TensorRTModelSpeedUp', you can refer to :doc:`Model Compression API Reference <../reference/compression/quantization_speedup>`.\n\n### Mnist test\n\non one GTX2080 GPU,\ninput tensor: ``torch.randn(128, 1, 28, 28)``\n\n.. list-table::\n :header-rows: 1\n :widths: auto\n\n * - quantization strategy\n - Latency\n - accuracy\n * - all in 32bit\n - 0.001199961\n - 96%\n * - mixed precision(average bit 20.4)\n - 0.000753688\n - 96%\n * - all in 8bit\n - 0.000229869\n - 93.7%\n\n### Cifar10 resnet18 test (train one epoch)\n\non one GTX2080 GPU,\ninput tensor: ``torch.randn(128, 3, 32, 32)``\n\n.. list-table::\n :header-rows: 1\n :widths: auto\n\n * - quantization strategy\n - Latency\n - accuracy\n * - all in 32bit\n - 0.003286268\n - 54.21%\n * - mixed precision(average bit 11.55)\n - 0.001358022\n - 54.78%\n * - all in 8bit\n - 0.000859139\n - 52.81%\n\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/docs/source/tutorials/quantization_speedup.py b/docs/source/tutorials/quantization_speedup.py new file mode 100644 index 0000000000000000000000000000000000000000..132fc6281cc8b0004665c93918c8b3ea43e87960 --- /dev/null +++ b/docs/source/tutorials/quantization_speedup.py @@ -0,0 +1,168 @@ +""" +SpeedUp Model with Calibration Config +====================================== + + +Introduction +------------ + +Deep learning network has been computational intensive and memory intensive +which increases the difficulty of deploying deep neural network model. Quantization is a +fundamental technology which is widely used to reduce memory footprint and speedup inference +process. Many frameworks begin to support quantization, but few of them support mixed precision +quantization and get real speedup. Frameworks like `HAQ: Hardware-Aware Automated Quantization with Mixed Precision `__\, only support simulated mixed precision quantization which will +not speedup the inference process. To get real speedup of mixed precision quantization and +help people get the real feedback from hardware, we design a general framework with simple interface to allow NNI quantization algorithms to connect different +DL model optimization backends (e.g., TensorRT, NNFusion), which gives users an end-to-end experience that after quantizing their model +with quantization algorithms, the quantized model can be directly speeded up with the connected optimization backend. NNI connects +TensorRT at this stage, and will support more backends in the future. + + +Design and Implementation +------------------------- + +To support speeding up mixed precision quantization, we divide framework into two part, frontend and backend. +Frontend could be popular training frameworks such as PyTorch, TensorFlow etc. Backend could be inference +framework for different hardwares, such as TensorRT. At present, we support PyTorch as frontend and +TensorRT as backend. To convert PyTorch model to TensorRT engine, we leverage onnx as intermediate graph +representation. In this way, we convert PyTorch model to onnx model, then TensorRT parse onnx +model to generate inference engine. + + +Quantization aware training combines NNI quantization algorithm 'QAT' and NNI quantization speedup tool. +Users should set config to train quantized model using QAT algorithm(please refer to :doc:`NNI Quantization Algorithms <../compression/quantizer>` ). +After quantization aware training, users can get new config with calibration parameters and model with quantized weight. By passing new config and model to quantization speedup tool, users can get real mixed precision speedup engine to do inference. + + +After getting mixed precision engine, users can do inference with input data. + + +Note + + +* Recommend using "cpu"(host) as data device(for both inference data and calibration data) since data should be on host initially and it will be transposed to device before inference. If data type is not "cpu"(host), this tool will transpose it to "cpu" which may increases unnecessary overhead. +* User can also do post-training quantization leveraging TensorRT directly(need to provide calibration dataset). +* Not all op types are supported right now. At present, NNI supports Conv, Linear, Relu and MaxPool. More op types will be supported in the following release. + + +Prerequisite +------------ +CUDA version >= 11.0 + +TensorRT version >= 7.2 + +Note + +* If you haven't installed TensorRT before or use the old version, please refer to `TensorRT Installation Guide `__\ + +Usage +----- + +""" + +# %% +import torch +import torch.nn.functional as F +from torch.optim import SGD +from scripts.compression_mnist_model import TorchModel, device, trainer, evaluator, test_trt + +config_list = [{ + 'quant_types': ['input', 'weight'], + 'quant_bits': {'input': 8, 'weight': 8}, + 'op_types': ['Conv2d'] +}, { + 'quant_types': ['output'], + 'quant_bits': {'output': 8}, + 'op_types': ['ReLU'] +}, { + 'quant_types': ['input', 'weight'], + 'quant_bits': {'input': 8, 'weight': 8}, + 'op_names': ['fc1', 'fc2'] +}] + +model = TorchModel().to(device) +optimizer = SGD(model.parameters(), lr=0.01, momentum=0.5) +criterion = F.nll_loss +dummy_input = torch.rand(32, 1, 28, 28).to(device) + +from nni.algorithms.compression.pytorch.quantization import QAT_Quantizer +quantizer = QAT_Quantizer(model, config_list, optimizer, dummy_input) +quantizer.compress() + +# %% +# finetuning the model by using QAT +for epoch in range(3): + trainer(model, optimizer, criterion) + evaluator(model) + +# %% +# export model and get calibration_config +import os +os.makedirs('log', exist_ok=True) +model_path = "./log/mnist_model.pth" +calibration_path = "./log/mnist_calibration.pth" +calibration_config = quantizer.export_model(model_path, calibration_path) + +print("calibration_config: ", calibration_config) + +# %% +# build tensorRT engine to make a real speedup + +from nni.compression.pytorch.quantization_speedup import ModelSpeedupTensorRT +input_shape = (32, 1, 28, 28) +engine = ModelSpeedupTensorRT(model, input_shape, config=calibration_config, batchsize=32) +engine.compress() +test_trt(engine) + +# %% +# Note that NNI also supports post-training quantization directly, please refer to complete examples for detail. +# +# For complete examples please refer to :githublink:`the code `. +# +# For more parameters about the class 'TensorRTModelSpeedUp', you can refer to :doc:`Model Compression API Reference <../reference/compression/quantization_speedup>`. +# +# Mnist test +# ^^^^^^^^^^ +# +# on one GTX2080 GPU, +# input tensor: ``torch.randn(128, 1, 28, 28)`` +# +# .. list-table:: +# :header-rows: 1 +# :widths: auto +# +# * - quantization strategy +# - Latency +# - accuracy +# * - all in 32bit +# - 0.001199961 +# - 96% +# * - mixed precision(average bit 20.4) +# - 0.000753688 +# - 96% +# * - all in 8bit +# - 0.000229869 +# - 93.7% +# +# Cifar10 resnet18 test (train one epoch) +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# +# on one GTX2080 GPU, +# input tensor: ``torch.randn(128, 3, 32, 32)`` +# +# .. list-table:: +# :header-rows: 1 +# :widths: auto +# +# * - quantization strategy +# - Latency +# - accuracy +# * - all in 32bit +# - 0.003286268 +# - 54.21% +# * - mixed precision(average bit 11.55) +# - 0.001358022 +# - 54.78% +# * - all in 8bit +# - 0.000859139 +# - 52.81% diff --git a/docs/source/tutorials/quantization_speedup.py.md5 b/docs/source/tutorials/quantization_speedup.py.md5 new file mode 100644 index 0000000000000000000000000000000000000000..76e0ef222202bd92bce0bb947a2ea878bbfe87f2 --- /dev/null +++ b/docs/source/tutorials/quantization_speedup.py.md5 @@ -0,0 +1 @@ +2404b8d0c3958a0191b77bbe882456e4 \ No newline at end of file diff --git a/docs/source/tutorials/quantization_speedup.rst b/docs/source/tutorials/quantization_speedup.rst new file mode 100644 index 0000000000000000000000000000000000000000..c408e39ba7e5388accd0085b0c882e22e03f5c57 --- /dev/null +++ b/docs/source/tutorials/quantization_speedup.rst @@ -0,0 +1,331 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "tutorials/quantization_speedup.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + Click :ref:`here ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_tutorials_quantization_speedup.py: + + +SpeedUp Model with Calibration Config +====================================== + + +Introduction +------------ + +Deep learning network has been computational intensive and memory intensive +which increases the difficulty of deploying deep neural network model. Quantization is a +fundamental technology which is widely used to reduce memory footprint and speedup inference +process. Many frameworks begin to support quantization, but few of them support mixed precision +quantization and get real speedup. Frameworks like `HAQ: Hardware-Aware Automated Quantization with Mixed Precision `__\, only support simulated mixed precision quantization which will +not speedup the inference process. To get real speedup of mixed precision quantization and +help people get the real feedback from hardware, we design a general framework with simple interface to allow NNI quantization algorithms to connect different +DL model optimization backends (e.g., TensorRT, NNFusion), which gives users an end-to-end experience that after quantizing their model +with quantization algorithms, the quantized model can be directly speeded up with the connected optimization backend. NNI connects +TensorRT at this stage, and will support more backends in the future. + + +Design and Implementation +------------------------- + +To support speeding up mixed precision quantization, we divide framework into two part, frontend and backend. +Frontend could be popular training frameworks such as PyTorch, TensorFlow etc. Backend could be inference +framework for different hardwares, such as TensorRT. At present, we support PyTorch as frontend and +TensorRT as backend. To convert PyTorch model to TensorRT engine, we leverage onnx as intermediate graph +representation. In this way, we convert PyTorch model to onnx model, then TensorRT parse onnx +model to generate inference engine. + + +Quantization aware training combines NNI quantization algorithm 'QAT' and NNI quantization speedup tool. +Users should set config to train quantized model using QAT algorithm(please refer to :doc:`NNI Quantization Algorithms <../compression/quantizer>` ). +After quantization aware training, users can get new config with calibration parameters and model with quantized weight. By passing new config and model to quantization speedup tool, users can get real mixed precision speedup engine to do inference. + + +After getting mixed precision engine, users can do inference with input data. + + +Note + + +* Recommend using "cpu"(host) as data device(for both inference data and calibration data) since data should be on host initially and it will be transposed to device before inference. If data type is not "cpu"(host), this tool will transpose it to "cpu" which may increases unnecessary overhead. +* User can also do post-training quantization leveraging TensorRT directly(need to provide calibration dataset). +* Not all op types are supported right now. At present, NNI supports Conv, Linear, Relu and MaxPool. More op types will be supported in the following release. + + +Prerequisite +------------ +CUDA version >= 11.0 + +TensorRT version >= 7.2 + +Note + +* If you haven't installed TensorRT before or use the old version, please refer to `TensorRT Installation Guide `__\ + +Usage +----- + +.. GENERATED FROM PYTHON SOURCE LINES 64-92 + +.. code-block:: default + + import torch + import torch.nn.functional as F + from torch.optim import SGD + from scripts.compression_mnist_model import TorchModel, device, trainer, evaluator, test_trt + + config_list = [{ + 'quant_types': ['input', 'weight'], + 'quant_bits': {'input': 8, 'weight': 8}, + 'op_types': ['Conv2d'] + }, { + 'quant_types': ['output'], + 'quant_bits': {'output': 8}, + 'op_types': ['ReLU'] + }, { + 'quant_types': ['input', 'weight'], + 'quant_bits': {'input': 8, 'weight': 8}, + 'op_names': ['fc1', 'fc2'] + }] + + model = TorchModel().to(device) + optimizer = SGD(model.parameters(), lr=0.01, momentum=0.5) + criterion = F.nll_loss + dummy_input = torch.rand(32, 1, 28, 28).to(device) + + from nni.algorithms.compression.pytorch.quantization import QAT_Quantizer + quantizer = QAT_Quantizer(model, config_list, optimizer, dummy_input) + quantizer.compress() + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + + TorchModel( + (conv1): QuantizerModuleWrapper( + (module): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1)) + ) + (conv2): QuantizerModuleWrapper( + (module): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1)) + ) + (fc1): QuantizerModuleWrapper( + (module): Linear(in_features=256, out_features=120, bias=True) + ) + (fc2): QuantizerModuleWrapper( + (module): Linear(in_features=120, out_features=84, bias=True) + ) + (fc3): Linear(in_features=84, out_features=10, bias=True) + (relu1): QuantizerModuleWrapper( + (module): ReLU() + ) + (relu2): QuantizerModuleWrapper( + (module): ReLU() + ) + (relu3): QuantizerModuleWrapper( + (module): ReLU() + ) + (relu4): QuantizerModuleWrapper( + (module): ReLU() + ) + (pool1): MaxPool2d(kernel_size=(2, 2), stride=(2, 2), padding=0, dilation=1, ceil_mode=False) + (pool2): MaxPool2d(kernel_size=(2, 2), stride=(2, 2), padding=0, dilation=1, ceil_mode=False) + ) + + + +.. GENERATED FROM PYTHON SOURCE LINES 93-94 + +finetuning the model by using QAT + +.. GENERATED FROM PYTHON SOURCE LINES 94-98 + +.. code-block:: default + + for epoch in range(3): + trainer(model, optimizer, criterion) + evaluator(model) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + Average test loss: 0.5386, Accuracy: 8619/10000 (86%) + Average test loss: 0.1553, Accuracy: 9521/10000 (95%) + Average test loss: 0.1001, Accuracy: 9686/10000 (97%) + + + + +.. GENERATED FROM PYTHON SOURCE LINES 99-100 + +export model and get calibration_config + +.. GENERATED FROM PYTHON SOURCE LINES 100-108 + +.. code-block:: default + + import os + os.makedirs('log', exist_ok=True) + model_path = "./log/mnist_model.pth" + calibration_path = "./log/mnist_calibration.pth" + calibration_config = quantizer.export_model(model_path, calibration_path) + + print("calibration_config: ", calibration_config) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + calibration_config: {'conv1': {'weight_bits': 8, 'weight_scale': tensor([0.0029], device='cuda:0'), 'weight_zero_point': tensor([98.], device='cuda:0'), 'input_bits': 8, 'tracked_min_input': -0.4242129623889923, 'tracked_max_input': 2.821486711502075}, 'conv2': {'weight_bits': 8, 'weight_scale': tensor([0.0017], device='cuda:0'), 'weight_zero_point': tensor([124.], device='cuda:0'), 'input_bits': 8, 'tracked_min_input': 0.0, 'tracked_max_input': 8.848002433776855}, 'fc1': {'weight_bits': 8, 'weight_scale': tensor([0.0010], device='cuda:0'), 'weight_zero_point': tensor([134.], device='cuda:0'), 'input_bits': 8, 'tracked_min_input': 0.0, 'tracked_max_input': 14.64758586883545}, 'fc2': {'weight_bits': 8, 'weight_scale': tensor([0.0013], device='cuda:0'), 'weight_zero_point': tensor([121.], device='cuda:0'), 'input_bits': 8, 'tracked_min_input': 0.0, 'tracked_max_input': 15.807988166809082}, 'relu1': {'output_bits': 8, 'tracked_min_output': 0.0, 'tracked_max_output': 9.041301727294922}, 'relu2': {'output_bits': 8, 'tracked_min_output': 0.0, 'tracked_max_output': 15.143928527832031}, 'relu3': {'output_bits': 8, 'tracked_min_output': 0.0, 'tracked_max_output': 16.151935577392578}, 'relu4': {'output_bits': 8, 'tracked_min_output': 0.0, 'tracked_max_output': 11.749024391174316}} + + + + +.. GENERATED FROM PYTHON SOURCE LINES 109-110 + +build tensorRT engine to make a real speedup + +.. GENERATED FROM PYTHON SOURCE LINES 110-117 + +.. code-block:: default + + + from nni.compression.pytorch.quantization_speedup import ModelSpeedupTensorRT + input_shape = (32, 1, 28, 28) + engine = ModelSpeedupTensorRT(model, input_shape, config=calibration_config, batchsize=32) + engine.compress() + test_trt(engine) + + + + + +.. rst-class:: sphx-glr-script-out + + Out: + + .. code-block:: none + + Loss: 0.10061546401977539 Accuracy: 96.83% + Inference elapsed_time (whole dataset): 0.04322671890258789s + + + + +.. GENERATED FROM PYTHON SOURCE LINES 118-169 + +Note that NNI also supports post-training quantization directly, please refer to complete examples for detail. + +For complete examples please refer to :githublink:`the code `. + +For more parameters about the class 'TensorRTModelSpeedUp', you can refer to :doc:`Model Compression API Reference <../reference/compression/quantization_speedup>`. + +Mnist test +^^^^^^^^^^ + +on one GTX2080 GPU, +input tensor: ``torch.randn(128, 1, 28, 28)`` + +.. list-table:: + :header-rows: 1 + :widths: auto + + * - quantization strategy + - Latency + - accuracy + * - all in 32bit + - 0.001199961 + - 96% + * - mixed precision(average bit 20.4) + - 0.000753688 + - 96% + * - all in 8bit + - 0.000229869 + - 93.7% + +Cifar10 resnet18 test (train one epoch) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +on one GTX2080 GPU, +input tensor: ``torch.randn(128, 3, 32, 32)`` + +.. list-table:: + :header-rows: 1 + :widths: auto + + * - quantization strategy + - Latency + - accuracy + * - all in 32bit + - 0.003286268 + - 54.21% + * - mixed precision(average bit 11.55) + - 0.001358022 + - 54.78% + * - all in 8bit + - 0.000859139 + - 52.81% + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** ( 1 minutes 4.509 seconds) + + +.. _sphx_glr_download_tutorials_quantization_speedup.py: + + +.. only :: html + + .. container:: sphx-glr-footer + :class: sphx-glr-footer-example + + + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: quantization_speedup.py ` + + + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: quantization_speedup.ipynb ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/source/tutorials/quantization_speedup_codeobj.pickle b/docs/source/tutorials/quantization_speedup_codeobj.pickle new file mode 100644 index 0000000000000000000000000000000000000000..756035ac58738e1d832ef08686a5cd4b7cf27759 Binary files /dev/null and b/docs/source/tutorials/quantization_speedup_codeobj.pickle differ diff --git a/docs/source/tutorials/sg_execution_times.rst b/docs/source/tutorials/sg_execution_times.rst index c7785ec1d52e166fdf8f98b42f41e8e57c2a9e99..59fe26c9c453caffaedd13a7ce9f7cc74a2cd954 100644 --- a/docs/source/tutorials/sg_execution_times.rst +++ b/docs/source/tutorials/sg_execution_times.rst @@ -5,10 +5,22 @@ Computation times ================= -**00:24.663** total execution time for **tutorials** files: +**01:04.509** total execution time for **tutorials** files: -+-----------------------------------------------------------------------------------+-----------+--------+ -| :ref:`sphx_glr_tutorials_nni_experiment.py` (``nni_experiment.py``) | 00:24.662 | 0.0 MB | -+-----------------------------------------------------------------------------------+-----------+--------+ -| :ref:`sphx_glr_tutorials_nas_quick_start_mnist.py` (``nas_quick_start_mnist.py``) | 00:00.002 | 0.0 MB | -+-----------------------------------------------------------------------------------+-----------+--------+ ++-----------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_tutorials_quantization_speedup.py` (``quantization_speedup.py``) | 01:04.509 | 0.0 MB | ++-----------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_tutorials_hello_nas.py` (``hello_nas.py``) | 00:00.000 | 0.0 MB | ++-----------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_tutorials_nasbench_as_dataset.py` (``nasbench_as_dataset.py``) | 00:00.000 | 0.0 MB | ++-----------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_tutorials_pruning_customize.py` (``pruning_customize.py``) | 00:00.000 | 0.0 MB | ++-----------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_tutorials_pruning_quick_start_mnist.py` (``pruning_quick_start_mnist.py``) | 00:00.000 | 0.0 MB | ++-----------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_tutorials_pruning_speedup.py` (``pruning_speedup.py``) | 00:00.000 | 0.0 MB | ++-----------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_tutorials_quantization_customize.py` (``quantization_customize.py``) | 00:00.000 | 0.0 MB | ++-----------------------------------------------------------------------------------------------------+-----------+--------+ +| :ref:`sphx_glr_tutorials_quantization_quick_start_mnist.py` (``quantization_quick_start_mnist.py``) | 00:00.000 | 0.0 MB | ++-----------------------------------------------------------------------------------------------------+-----------+--------+ diff --git a/docs/static/css/material_custom.css b/docs/static/css/material_custom.css index 749a56cfad7ffe1a11698dde64b5c65a5b11159b..ff08341e620eb3237f3bb22277e946913d1f4639 100644 --- a/docs/static/css/material_custom.css +++ b/docs/static/css/material_custom.css @@ -1,3 +1,27 @@ +/* Global font */ +body, input { + font-family: "Roboto", "Noto Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +code, kbd, pre { + font-family: "Roboto Mono", "Consolas", "Courier New", Courier, monospace; +} + +h1, h2, h3, h4, .md-header, .md-tabs, .md-hero { + font-family: "Google Sans", "Noto Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +/* Title font */ +@media only screen and (min-width: 45em) { + .md-header-nav__title { + font-weight: 500; + } +} + +.md-typeset h4, .md-typeset h5, .md-typeset h6 { + font-weight: 600; +} + /* viewcode link should have left padding */ span.viewcode-link { padding-left: 0.6rem; @@ -8,24 +32,55 @@ dt.sig-object { position: relative; background: #f4f5f7; padding: 0.5rem; - border-left: 0.2rem solid #ec407a; /* this should be matched with theme color. */ + border-left: 0.2rem solid var(--custom-color-accent); word-wrap: break-word; } +.class > dt.sig-object { + border-left: none; /* remove left border */ + border-top: 0.18rem solid var(--custom-color-accent); +} + +.function > dt.sig-object { + border-left: none; /* remove left border */ + border-top: 0.18rem solid var(--custom-color-accent); +} + +.exception > dt.sig-object { + border-left: none; /* remove left border */ + border-top: 0.18rem solid var(--custom-color-accent); +} + +/* Padding on parameter list is not needed */ +dl.field-list > dt { + padding-left: 0 !important; +} + +dl.field-list > dd { + margin-left: 1.5em; +} + +/* show headerlink when hover/focus */ +dt.sig-object:focus .headerlink, dt.sig-object:hover .headerlink { + -webkit-transform: translate(0); + transform: translate(0); + opacity: 1; +} + /* logo is too large */ a.md-logo img { padding: 3px; } -/* Add split for navigation */ +/* Split for navigation */ nav.md-tabs .md-tabs__item:not(:last-child) { padding-right: 0; } -nav.md-tabs .md-tabs__item:not(:last-child) .md-tabs__link:after { - content: "»"; - font-family: "Material Icons"; - padding-left: 0.6rem; +nav.md-tabs .md-tabs__arrow { + padding-left: .3rem; + font-size: inherit; + vertical-align: -10%; } /* hide the floating button generated by readthedocs */ @@ -44,11 +99,388 @@ nav.md-tabs .md-tabs__item:not(:last-child) .md-tabs__link:after { } /* toc style */ -.md-nav span.caption { +li.md-nav__item:not(:first-child) span.caption { margin-top: 1.25em; } +@media only screen and (min-width: 76.2em) { + .md-nav--primary .md-nav__title--site { + display: none; + } +} + +.md-nav__overview { + font-weight: 500; +} + +@media only screen and (max-width: 76.1875em) { + .md-nav__overview { + display: none; + } +} + +/* hide nav bar in some cases */ +.md-tabs.hidden { + display: none; +} + /* citation style */ .citation dt { padding-right: 1em; } + +/* inline code style */ +.md-typeset code { + padding-left: 0.07em; + padding-right: 0.07em; +} + +/* for release icon, on home page */ +.release-icon { + margin-left: 8px; + width: 40px; +} + +/* Similar to cardlink, but used in codesnippet in index page. see sphinx_gallery.css */ +.codesnippet-card-container { + display: flex; + flex-flow: wrap row; +} + +.codesnippet-card.admonition { + border-left: 0; + padding: 0; + margin: .5rem 1rem 1rem 0rem; + width: 100%; +} + +/* Controlling the cards in containers only */ +.codesnippet-card-container .codesnippet-card.admonition { + width: 47%; +} + +@media only screen and (max-width:59.9375em) { + .codesnippet-card-container .codesnippet-card.admonition { + width: 100%; + } +} + +.codesnippet-card .codesnippet-card-body { + min-height: 4rem; + position: relative; + padding: 0.9rem 0.9rem 3rem 0.9rem; +} + +.codesnippet-card .codesnippet-card-footer { + padding: 0.8rem 0.9rem; + border-top: 1px solid #ddd; + margin: 0 !important; + position: absolute; + bottom: 0; + width: 100%; +} + +.codesnippet-card a:not(:hover) { + color: rgba(0, 0, 0, .68); +} + +.codesnippet-card-title-container { + margin-top: 0.3rem; + position: relative; +} + +.codesnippet-card-title-container h4 { + padding-left: 2.3rem; + line-height: 1.6rem; + height: 1.6rem; + margin-top: 0; +} + +.codesnippet-card-icon { + position: absolute; + top: 0; + left: 0; +} + +.codesnippet-card-icon img { + max-width: 100%; + max-height: 100%; + /* horizontal and vertical center */ + /* https://stackoverflow.com/questions/7273338/how-to-vertically-align-an-image-inside-a-div */ + text-align: center; + vertical-align: middle; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + margin: auto; +} + +.codesnippet-card-icon { + width: 1.6rem; + height: 1.6rem; + padding: 0; +} + +.codesnippet-card-link { + position: relative; +} + +.codesnippet-card-link .material-icons { + position: absolute; + right: 0; +} + +/* fixes reference overlapping issue */ +/* This is originally defined to be negative in application_fixes.css */ +/* They did that to ensure the header doesn't disappear in jump links */ +/* We did this by using scroll-margin-top instead */ +dt:target { + margin-top: 0.15rem !important; + padding-top: 0.5rem !important; +} + +:target { + /* header height */ + scroll-margin-top: 3.5rem; +} + +/* fix code block style on mobile */ +@media only screen and (max-width: 44.9375em) { + .md-typeset pre { + margin: 1em -0.3em; + } +} + +/* Responsive nav bar */ +.md-source__fact { + padding: 0 !important; +} + +/* collapsible toctree */ +.md-nav--primary ul li { + padding-left: .8rem; +} + +.md-nav__item { + position: relative; +} + +.md-nav__expand > a > .md-nav__tocarrow { + transform: rotate(-90deg); + font-size: inherit; + transition: all 0.1s ease; + position: absolute; + left: .1rem; + top: .05rem; +} + +.md-nav__expand .md-nav__list { + display: none; +} + +.md-nav__expand--active > .md-nav__list { + display: block; +} + +.md-nav__expand--active > a > .md-nav__tocarrow { + transform: rotate(0); +} + +@media only screen and (max-width:76.1875em) { + .md-nav--primary .md-nav__link { + padding: .15rem .2rem .15rem .6rem; + } + .md-nav__expand > a > .md-nav__tocarrow { + left: 0; + top: .25rem; + } + .md-nav--primary span.md-nav__link.caption { + margin-top: 0.75em; + } + .md-nav--primary .md-nav__item .md-nav__list .md-nav__item { + padding-left: .3rem; + } + html .md-nav--primary .md-nav__title--site .md-nav__button { + height: auto; + font-size: inherit; + left: 0; + } + html .md-nav--primary .md-nav__title { + padding-top: 2rem; + padding-left: .6rem; + height: 4.6rem; + } + .md-nav--primary .md-nav__item, .md-nav--primary .md-nav__title { + font-size: .7rem; + line-height: 1.3; + } +} + +/* Increase TOC padding */ +.md-nav--primary ul li ul li { + padding-left: 0.8rem; +} + +/* Nav bar and heroes */ +@media only screen and (min-width:60em) { + .md-search__form, .md-search__input { + border-radius: .3rem; /* even rounder */ + } +} + +.md-header-nav__source, .md-source { + padding-right: 0 !important; +} + +.md-hero { + position: relative; +} + +.md-hero__background { + max-width: 73rem; + position: absolute; + bottom: -46px; + left: 0; + right: 0; + margin-left: auto; + margin-right: auto; + width: 100%; + z-index: 0; +} + +.md-hero__background img { + width: 100%; +} + +@media only screen and (max-width:59.9375em) { + .md-hero__background { + display: none; + } +} + +@media only screen and (max-width:76.1875em) { + .md-hero__background { + bottom: -5%; + top: auto; + } +} + +.md-hero__inner { + z-index: 1; + position: relative; + padding-right: 35%; +} + +@media only screen and (min-width:76.2em) { + .md-hero__inner { + padding-top: 2.4rem; + padding-bottom: 1.2rem; + } +} + +/* make title look larger */ +.md-typeset h1 { + margin: 0 0 1.5rem; + color: rgba(0,0,0,.85); + font-size: 1.5625rem; + line-height: 1.3; +} + +.md-typeset h1, .md-typeset h2, .md-typeset h3 { + font-weight: 400; + letter-spacing: 0; +} + +/* Enlarge table */ +.md-typeset table:not([class]) { + font-size: 0.7rem; + box-shadow: 0 2px 2px 0 rgb(0 0 0 / 8%), 0 1px 5px 0 rgb(0 0 0 / 7%), 0 3px 1px -2px rgb(0 0 0 / 14%); +} + +.md-typeset table:not([class]) th { + padding: .5rem .7rem; + background-color: #e6e7e8; + color: inherit; + font-weight: 500; +} + +.md-typeset table:not([class]) td { + padding: .4rem .7rem; +} + +/* On this page TOC */ +.md-sidebar--secondary .md-nav--secondary { + border-inline-start: 4px solid var(--custom-color-primary); +} + +.md-nav__link { + margin-top: 0.45em; +} + +/* Override style for copy button */ +button.copybtn { + opacity: 1; +} + +.o-tooltip--left:after { + transform: translateX(-5%) translateY(-125%); + padding: .4em; + font-size: .5rem; + font-weight: 600; + background: #5f6368; +} + +.o-tooltip--left:hover:after { + transform: translateX(-5%) translateY(-120%); +} + +/* Sphinx tabs */ +/* Copied from https://github.com/executablebooks/sphinx-tabs/blob/master/sphinx_tabs/static/tabs.css with modifications */ +.sphinx-tabs.container { + margin-bottom: 1rem; + border: 1px solid rgb(232, 234, 237); + border-radius: 8px; +} + +[role="tablist"] { + padding: .3rem 0 0 0; + border-bottom: 1px solid #a0b3bf; +} + +.sphinx-tabs-tab { + position: relative; + line-height: 2rem; + font-weight: 600; + padding: 0 1rem; + color: #80868b; +} + +.sphinx-tabs-tab[aria-selected="true"] { + color: #3f51b5; /* primary color */ + border-bottom: 2px solid #3f51b5; +} + +.sphinx-tabs-tab:focus { + z-index: 1; + outline-offset: 1px; +} + +.sphinx-tabs-panel { + position: relative; + padding: 1rem; +} + +.sphinx-tabs-panel.code-tab { + padding: 0; +} + +.sphinx-tabs-panel.code-tab .highlight { + margin: 0; + padding: .5rem; +} + +.sphinx-tab img { + margin-bottom: 2rem; +} diff --git a/docs/static/css/material_dropdown.css b/docs/static/css/material_dropdown.css index d329e0a3eb375117d94ecf642d67073e8ec752f4..52c9a6c5d077de7f453f01e485a86d745cc91777 100644 --- a/docs/static/css/material_dropdown.css +++ b/docs/static/css/material_dropdown.css @@ -1,10 +1,26 @@ /* https://codepen.io/mildrenben/pen/RPwQEY */ +@media only screen and (max-width:44.9375em) { + .drop { + display: none; + } +} + .drop { - width: 125px; + width: 5.3rem; vertical-align: middle; } +@media only screen and (min-width:60em) and (max-width:70em) { + .drop { + width: 4.7rem; + } + /* also narrow nav source width */ + .md-header-nav__source { + width: 10rem; + } +} + .drop button { color: inherit; font-weight: 700; diff --git a/docs/static/css/material_theme.css b/docs/static/css/material_theme.css new file mode 100644 index 0000000000000000000000000000000000000000..c8ee9b58a052dab936874bc77d75b4f73c051a8e --- /dev/null +++ b/docs/static/css/material_theme.css @@ -0,0 +1,97 @@ +/* Theme related customization */ +/* https://github.com/bashtage/sphinx-material/pull/122 */ + +/* first part */ +button[data-md-color-primary=custom] { + background-color: var(--custom-color-primary) +} + +[data-md-color-primary=custom] .md-typeset a { + color: var(--custom-color-primary) +} + +[data-md-color-primary=custom] .md-header, +[data-md-color-primary=custom] .md-hero { + background-color: var(--custom-color-primary) +} + +[data-md-color-primary=custom] .md-nav__link--active, +[data-md-color-primary=custom] .md-nav__link:active { + color: var(--custom-color-primary) +} + +[data-md-color-primary=custom] .md-nav__item--nested>.md-nav__link { + color: inherit +} + +[data-md-color-primary=custom] .md-nav__extra_link:active { + color: var(--custom-color-primary) +} + +[data-md-color-primary=custom] .md-nav__item--nested > .md-nav__extra_link { + color: inherit +} + +/* second part */ +button[data-md-color-accent=custom] { + background-color: var(--custom-color-accent) +} + +[data-md-color-accent=custom] .md-typeset a:active, +[data-md-color-accent=custom] .md-typeset a:hover { + color: var(--custom-color-accent) +} + +[data-md-color-accent=custom] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover, +[data-md-color-accent=custom] .md-typeset pre code::-webkit-scrollbar-thumb:hover { + background-color: var(--custom-color-accent) +} + +[data-md-color-accent=custom] .md-nav__link:focus, +[data-md-color-accent=custom] .md-nav__link:hover, +[data-md-color-accent=custom] .md-typeset .footnote li:hover .footnote-backref:hover, +[data-md-color-accent=custom] .md-typeset .footnote li:target .footnote-backref, +[data-md-color-accent=custom] .md-typeset .md-clipboard:active:before, +[data-md-color-accent=custom] .md-typeset .md-clipboard:hover:before, +[data-md-color-accent=custom] .md-typeset [id] .headerlink:focus, +[data-md-color-accent=custom] .md-typeset [id]:hover .headerlink:hover, +[data-md-color-accent=custom] .md-typeset [id]:target .headerlink { + color: var(--custom-color-accent) +} + +[data-md-color-accent=custom] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover { + background-color: var(--custom-color-accent) +} + +[data-md-color-accent=custom] .md-search-result__link:hover, +[data-md-color-accent=custom] .md-search-result__link[data-md-state=active] { + background-color: rgba(83, 109, 254, .1) +} + +[data-md-color-accent=custom] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover { + background-color: var(--custom-color-accent) +} + +[data-md-color-accent=custom] .md-source-file:hover:before { + background-color: var(--custom-color-accent) +} + +/* third part */ +@media only screen and (max-width:59.9375em) { + [data-md-color-primary=custom] .md-nav__source { + background-color: var(--custom-color-primary); + opacity: 0.9675; + } +} + +@media only screen and (max-width:76.1875em) { + html [data-md-color-primary=custom] .md-nav--primary .md-nav__title--site { + background-color: var(--custom-color-primary) + } +} + +@media only screen and (min-width:76.25em) { + [data-md-color-primary=custom] .md-tabs { + background-color: var(--custom-color-primary) + } +} diff --git a/docs/static/css/sphinx_gallery.css b/docs/static/css/sphinx_gallery.css index 5879dc9f29db4787eceac34a5a8afa3e42c9680b..fad00758f73fb36bd830e09945f54c55951b2afe 100644 --- a/docs/static/css/sphinx_gallery.css +++ b/docs/static/css/sphinx_gallery.css @@ -11,7 +11,7 @@ p.sphx-glr-script-out { } .sphx-glr-script-out .highlight pre { - background-color: #f2f3fa !important; + background-color: #f0f6fa !important; padding: .6rem !important; margin-bottom: 1.5rem; } @@ -26,6 +26,7 @@ div.sphx-glr-footer { .sphx-glr-download-link-note { margin-bottom: 1.5rem; + line-height: 2.5rem; } .notebook-action-div { @@ -37,7 +38,7 @@ div.sphx-glr-footer { .notebook-action-link:hover .notebook-action-div { /* match theme */ - border-bottom-color: #f50057; + border-bottom-color: var(--custom-color-accent); } .notebook-action-link img { @@ -83,6 +84,11 @@ div.sphx-glr-footer { font-size: 0.75rem; } +/* hide link */ +.card-link-anchor { + display: none; +} + .card-link-tag { margin-right: 0.4rem; background: #eeeff2; @@ -103,8 +109,8 @@ div.sphx-glr-footer { } .card-link-icon img { - max-width: 80%; - max-height: 80%; + max-width: 75%; + max-height: 75%; /* horizontal and vertical center */ /* https://stackoverflow.com/questions/7273338/how-to-vertically-align-an-image-inside-a-div */ text-align: center; @@ -119,7 +125,7 @@ div.sphx-glr-footer { /* link icon background color */ .card-link-icon.circle { - background-color: #283593; + background-color: #E8DCEE; border-radius: 50%; width: 4rem; height: 4rem; @@ -127,50 +133,18 @@ div.sphx-glr-footer { } /* pallette */ -.card-link-icon.red { - background-color: #C62828; -} - -.card-link-icon.pink { - background-color: #AD1457; +.card-link-icon.cyan { + background-color: #DDEFF2; } .card-link-icon.purple { - background-color: #8E24AA; -} - -.card-link-icon.deep-purple { - background-color: #512DA8; + background-color: #E8DCEE; } .card-link-icon.blue { - background-color: #1565C0; -} - -.card-link-icon.light-blue { - background-color: #0277BD; -} - -.card-link-icon.cyan { - background-color: #006064; -} - -.card-link-icon.teal { - background-color: #00796B; -} - -.card-link-icon.green { - background-color: #2E7D32; -} - -.card-link-icon.deep-orange { - background-color: #BF360C; -} - -.card-link-icon.brown { - background-color: #6D4C41; + background-color: #DBE8FC; } .card-link-icon.indigo { - background-color: #3949AB; + background-color: #E1E4F3; } diff --git a/docs/static/img/Comfort.png b/docs/static/img/Comfort.png deleted file mode 100644 index c42c69bbccb58f6e9d81139d8858467946821681..0000000000000000000000000000000000000000 Binary files a/docs/static/img/Comfort.png and /dev/null differ diff --git a/docs/static/img/Crying.png b/docs/static/img/Crying.png deleted file mode 100644 index 43d10426cc2f2dac4072e391d99f3498fb58f335..0000000000000000000000000000000000000000 Binary files a/docs/static/img/Crying.png and /dev/null differ diff --git a/docs/static/img/Cut.png b/docs/static/img/Cut.png deleted file mode 100644 index 83c4d37fdabaeab9d25730520d42a07426be63e8..0000000000000000000000000000000000000000 Binary files a/docs/static/img/Cut.png and /dev/null differ diff --git a/docs/static/img/Error.png b/docs/static/img/Error.png deleted file mode 100644 index 5184238ece55c1c82cf08020d255a9570824c409..0000000000000000000000000000000000000000 Binary files a/docs/static/img/Error.png and /dev/null differ diff --git a/docs/static/img/Holiday.png b/docs/static/img/Holiday.png deleted file mode 100644 index f4446ed8131386d9414acb1af8f8f3ba707294c5..0000000000000000000000000000000000000000 Binary files a/docs/static/img/Holiday.png and /dev/null differ diff --git a/docs/static/img/NoBug.png b/docs/static/img/NoBug.png deleted file mode 100644 index 9bf1266769f2bb870308d3917252952ca339928c..0000000000000000000000000000000000000000 Binary files a/docs/static/img/NoBug.png and /dev/null differ diff --git a/docs/static/img/Sign.png b/docs/static/img/Sign.png deleted file mode 100644 index a57fb2064d3c9ebb0226816ff197ff11a5e5d457..0000000000000000000000000000000000000000 Binary files a/docs/static/img/Sign.png and /dev/null differ diff --git a/docs/static/img/Sweat.png b/docs/static/img/Sweat.png deleted file mode 100644 index 642e5d6e55f9d637748dc3f1352d7d4b8748ab78..0000000000000000000000000000000000000000 Binary files a/docs/static/img/Sweat.png and /dev/null differ diff --git a/docs/static/img/Weaving.png b/docs/static/img/Weaving.png deleted file mode 100644 index 3845ce4cbc27b031be24abc65860d7f2f92bce54..0000000000000000000000000000000000000000 Binary files a/docs/static/img/Weaving.png and /dev/null differ diff --git a/docs/static/img/Working.png b/docs/static/img/Working.png deleted file mode 100644 index 47bc0cd49870cde1e71132c134457038ffddac05..0000000000000000000000000000000000000000 Binary files a/docs/static/img/Working.png and /dev/null differ diff --git a/docs/static/img/hero-background.svg b/docs/static/img/hero-background.svg new file mode 100644 index 0000000000000000000000000000000000000000..ab411cfc6eb1aa5a9d338256008505fb332f82df --- /dev/null +++ b/docs/static/img/hero-background.svg @@ -0,0 +1,672 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/static/img/home.svg b/docs/static/img/home.svg deleted file mode 100644 index 5360482f3260794c8aa9b037833954b9ebc61def..0000000000000000000000000000000000000000 --- a/docs/static/img/home.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/static/js/misc.js b/docs/static/js/misc.js new file mode 100644 index 0000000000000000000000000000000000000000..c78a3b176c1b903e057289c064112f66a9d5946e --- /dev/null +++ b/docs/static/js/misc.js @@ -0,0 +1,78 @@ +// Fix the hero text effect on large screens +function resetHeroHidden() { + const scrollAmount = window.scrollY; + if (window.matchMedia("only screen and (min-width: 76.25em)").matches) { + // only enable this on large screens + if (scrollAmount == 0) { + $(".md-hero").attr("data-md-state", ""); + } else { + $(".md-hero").attr("data-md-state", "hidden"); + } + } +} + +// https://github.com/bashtage/sphinx-material/blob/6e0ef822e58df57d6a9de5a58dc40c17fc34f557/sphinx_material/sphinx_material/static/javascripts/application.js#L1384 +$(window).on("scroll", resetHeroHidden); +$(window).on("resize", resetHeroHidden); +$(window).on("orientationchange", resetHeroHidden); + + +// Sidebar header +$(document).ready(function() { + let language = "en"; // default english + try { + language = READTHEDOCS_DATA["language"]; + } catch (e) {} + + const title = $(".md-sidebar--secondary .md-nav--secondary label.md-nav__title"); + if (language == "en") { + title.text("On this page"); + } else if (language == "zh") { + title.text("本页内容"); + } +}); + + +// Hide navigation bar when it's too short +// Hide TOC header when it coincides with page title +function hide_nav() { + const d = $('nav.md-tabs[data-md-component="tabs"]'); + if (d.find('li').length <= 1) { + d.addClass('hidden'); + } +} + +// Expand link +function expand_link() { + // on load, collapse all links without active on the inside + $(".md-nav__expand").filter(function (index) { + return $(".md-nav__link--active", this).length >= 1; + }).addClass("md-nav__expand--active"); + + function toggleExpand(event) { + event.preventDefault(); + + $(event.target) + .closest(".md-nav__expand") + .toggleClass("md-nav__expand--active"); + + return false; + } + + // bind click events + $(".md-nav__expand > a").click(toggleExpand); + $(".md-nav__expand > a > .md-nav__tocarrow").click(toggleExpand); +} + +// Propagate card link from another element +function propagate_card_link() { + $(".card-link-clickable").each(function() { + $(this).attr("href", $(this).next("a.reference").attr("href")); + }); +} + +$(document).ready(function() { + hide_nav(); + expand_link(); + propagate_card_link(); +}); diff --git a/docs/static/js/sphinx_gallery.js b/docs/static/js/sphinx_gallery.js index 4cb3ecda241ba9f4ab3f2deca4e19341a9a7d6aa..54262dac362d34ea79acd42b7d47edb500cb8b42 100644 --- a/docs/static/js/sphinx_gallery.js +++ b/docs/static/js/sphinx_gallery.js @@ -12,18 +12,18 @@ $(document).ready(function() { // the image links are stored in layout.html // to leverage jinja engine downloadNote.html(` - -
- -
Run in Google Colab
-
-
Download Notebook
+ +
+ +
Run in Google Colab
+
+
diff --git a/docs/static/js/version.js b/docs/static/js/version.js index 73e1ec7683d58d3e0c24bfbdefbceddf218f4241..58c605f69ded3cbeca4cd7b30214c0f6dd65fecb 100644 --- a/docs/static/js/version.js +++ b/docs/static/js/version.js @@ -1,46 +1,51 @@ -// Uncomment the following for debug -// READTHEDOCS_DATA = { -// "ad_free": false, -// "api_host": "https://readthedocs.org", -// "build_date": "2022-01-25T06:27:55Z", -// "builder": "sphinx", -// "canonical_url": null, -// "commit": "ca66e346", -// "docroot": "/docs/en_US/", -// "features": { "docsearch_disabled": false }, -// "global_analytics_code": "UA-17997319-1", -// "language": "en", -// "page": "Tutorial", -// "programming_language": "words", -// "project": "nni", -// "proxied_api_host": "/_", -// "source_suffix": ".rst", -// "subprojects": { "nni-zh": "https://nni.readthedocs.io/zh/stable/" }, -// "theme": "sphinx_material", -// "user_analytics_code": "UA-136029994-1", -// "version": "latest" -// }; - -// READTHEDOCS_VERSIONS = [ -// ["latest", "/en/latest/"], -// ["stable", "/en/stable/"], -// ["v2.6", "/en/v2.6/"], -// ["v2.5", "/en/v2.5/"], -// ["v2.4", "/en/v2.4/"], -// ["v2.3", "/en/v2.3/"] -// ]; -// The above code is injected by readthedocs in production. +try { + READTHEDOCS_DATA; +} catch (e) { + console.log('READTHEDOCS_DATA is undefined. In debug mode.'); + // mock info + READTHEDOCS_DATA = { + "ad_free": false, + "api_host": "https://readthedocs.org", + "build_date": "2022-01-25T06:27:55Z", + "builder": "sphinx", + "canonical_url": null, + "commit": "ca66e346", + "docroot": "/docs/en_US/", + "features": { "docsearch_disabled": false }, + "global_analytics_code": "UA-17997319-1", + "language": "en", + "page": "Tutorial", + "programming_language": "words", + "project": "nni", + "proxied_api_host": "/_", + "source_suffix": ".rst", + "subprojects": { "nni-zh": "https://nni.readthedocs.io/zh/stable/" }, + "theme": "sphinx_material", + "user_analytics_code": "UA-136029994-1", + "version": "latest" + }; + + READTHEDOCS_VERSIONS = [ + ["latest", "/en/latest/"], + ["stable", "/en/stable/"], + ["v2.6", "/en/v2.6/"], + ["v2.5", "/en/v2.5/"], + ["v2.4", "/en/v2.4/"], + ["v2.3", "/en/v2.3/"], + ["test-version", "/en/test-version"] + ]; + // The above code is injected by readthedocs in production. +} -function create_dropdown(button_text, items) { - const dropdown = document.createElement("div"); - dropdown.className = "md-flex__cell md-flex__cell--shrink drop"; +function create_dropdown(selector, button_text, items) { + const dropdown = $(selector); const button = document.createElement("button"); button.innerHTML = button_text; const content = document.createElement("ul"); // content.className = "dropdown-content md-hero"; - dropdown.appendChild(button); - dropdown.appendChild(content); + dropdown.append(button); + dropdown.append(content); for (const key in items) { if (items.hasOwnProperty(key)) { @@ -58,8 +63,8 @@ function create_dropdown(button_text, items) { $(button).click(function (e) { // first close all others. $(".drop").find(".active").removeClass("active"); - $(dropdown).find("ul").addClass("active"); - $(dropdown).find("button").addClass("active"); + dropdown.find("ul").addClass("active"); + dropdown.find("button").addClass("active"); e.stopPropagation(); }) $(document).click(function () { @@ -68,15 +73,16 @@ function create_dropdown(button_text, items) { return dropdown; } -function remove_version_dropdown() { - $(".navheader").children().last().remove(); -} - function add_version_dropdown() { - const prev_versions = Object.assign({}, ...READTHEDOCS_VERSIONS.map(([k, v]) => ({ [k]: v }))); + const prev_versions = Object.assign( + {}, + ...READTHEDOCS_VERSIONS + .filter(([k, v]) => (k === 'stable' || k == 'latest' || k.startsWith('v'))) + .map(([k, v]) => ({ [k]: v })) + ); const current_version = 'v: ' + READTHEDOCS_DATA["version"]; - $(".navheader").append(create_dropdown(current_version, prev_versions)); + create_dropdown(".drop.version", current_version, prev_versions); } function add_language_dropdown() { @@ -98,14 +104,13 @@ function add_language_dropdown() { return pathname.join('/'); } - $(".navheader").append(create_dropdown(language_dropdown[current_language], { + create_dropdown(".drop.language", language_dropdown[current_language], { [language_dropdown['en']]: get_dropdown_href('en'), [language_dropdown['zh']]: get_dropdown_href('zh') - })) + }); } $(document).ready(function () { - remove_version_dropdown(); add_language_dropdown(); add_version_dropdown(); }); diff --git a/docs/templates/autosummary/module.rst b/docs/templates/autosummary/module.rst new file mode 100644 index 0000000000000000000000000000000000000000..82a7a639e604e16d113ebe910ccf0644ac7ca571 --- /dev/null +++ b/docs/templates/autosummary/module.rst @@ -0,0 +1,68 @@ +.. Modified from https://raw.githubusercontent.com/sphinx-doc/sphinx/4.x/sphinx/ext/autosummary/templates/autosummary/module.rst + +{% if fullname == 'nni' %} +Python API Reference +==================== +{% else %} +{{ fullname | escape | underline }} +{% endif %} + +.. automodule:: {{ fullname }} + :noindex: + + {% block attributes %} + {% if attributes %} + .. rubric:: {{ _('Module Attributes') }} + + .. autosummary:: + {% for item in attributes %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block functions %} + {% if functions %} + .. rubric:: {{ _('Functions') }} + + .. autosummary:: + {% for item in functions %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block classes %} + {% if classes %} + .. rubric:: {{ _('Classes') }} + + .. autosummary:: + {% for item in classes %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block exceptions %} + {% if exceptions %} + .. rubric:: {{ _('Exceptions') }} + + .. autosummary:: + {% for item in exceptions %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + +{% block modules %} +{% if modules %} +.. rubric:: Modules + +.. autosummary:: + :toctree: + :recursive: +{% for item in modules %} + {{ item }} +{%- endfor %} +{% endif %} +{% endblock %} diff --git a/docs/templates/globaltoc.html b/docs/templates/globaltoc.html new file mode 100644 index 0000000000000000000000000000000000000000..ab4b41a53f8ec66eff68078fc81c43b76e7c1e9b --- /dev/null +++ b/docs/templates/globaltoc.html @@ -0,0 +1,36 @@ +{% set toctree = toctree(maxdepth=theme_globaltoc_depth|toint, collapse=theme_globaltoc_collapse|tobool, includehidden=theme_globaltoc_includehidden|tobool, titles_only=True) %} +{% if toctree and sidebars and 'globaltoc.html' in sidebars %} + {% set toctree_nodes = derender_toc(toctree, False) %} +
    +
  • + {{ _('Overview') }} +
  • + {%- for item in toctree_nodes recursive %} +
  • + {% if "caption" in item %} + {{ item.caption }} + {% else %} + {% if item.current %} + + + {% endif %} + + {% if item.children %} + + {% endif %} + {{ item.contents }} + + {% if item.current %} + {%- set sphinx_material_include_searchbox=False %} + {% include "localtoc.html" %} + {% endif %} + {%- set sphinx_material_include_searchbox=True %} + {%- if item.children -%} +
      {{ loop(item.children) }}
    + {%- endif %} + {% endif %} +
  • + {%- endfor %} +
+ {# TODO: Fallback to toc? #} +{% endif %} diff --git a/docs/templates/header.html b/docs/templates/header.html new file mode 100644 index 0000000000000000000000000000000000000000..859716a19d1b44e715cb807a32394e6090978db8 --- /dev/null +++ b/docs/templates/header.html @@ -0,0 +1,41 @@ +
+ +
diff --git a/docs/templates/hero.html b/docs/templates/hero.html new file mode 100644 index 0000000000000000000000000000000000000000..5d3272d2757d57f58ff1ea0c56efef40b4024f60 --- /dev/null +++ b/docs/templates/hero.html @@ -0,0 +1,11 @@ +{% if pagename in theme_heroes %} +{% set hero = theme_heroes[pagename] %} + +{% endif %} diff --git a/docs/templates/layout.html b/docs/templates/layout.html index 4de124e35f82435577714de2c25606a58e29d235..090fd4d448b6818b197c3ba15235b0f7fff16554 100644 --- a/docs/templates/layout.html +++ b/docs/templates/layout.html @@ -1,8 +1,23 @@ {% extends "!layout.html" %} +{#- SPECIFY PARTICULAR FONTS FOR HEADERS #} +{% block font %} + + +{% endblock %} + {#- TO INJECT INFORMATION FROM READTHEDOCS HERE #} {% block scripts %} {{ super() }} + + {#- CUSTOM THEME #} + + {% if versions %}