"src/vscode:/vscode.git/clone" did not exist on "812cd5c8de7800706a1d1e26c70ceca0f6ec1bbe"
Unverified Commit 7215fdd3 authored by Chi Song's avatar Chi Song Committed by GitHub
Browse files

Chinese translation (#2074)

parent 116fd9ad
...@@ -19,7 +19,7 @@ NNI 管理自动机器学习 (AutoML) 的 Experiment,**调度运行**由调优 ...@@ -19,7 +19,7 @@ NNI 管理自动机器学习 (AutoML) 的 Experiment,**调度运行**由调优
* 想要更容易**实现或试验新的自动机器学习算法**的研究员或数据科学家,包括:超参调优算法,神经网络搜索算法以及模型压缩算法。 * 想要更容易**实现或试验新的自动机器学习算法**的研究员或数据科学家,包括:超参调优算法,神经网络搜索算法以及模型压缩算法。
* 在机器学习平台中**支持自动机器学习** * 在机器学习平台中**支持自动机器学习**
### **NNI v1.3 已发布! &nbsp;[<img width="48" src="docs/img/release_icon.png" />](#nni-released-reminder)** ### **NNI v1.4 已发布! &nbsp;[<img width="48" src="docs/img/release_icon.png" />](#nni-released-reminder)**
## **NNI 功能一览** ## **NNI 功能一览**
...@@ -109,7 +109,7 @@ NNI 提供命令行工具以及友好的 WebUI 来管理训练的 Experiment。 ...@@ -109,7 +109,7 @@ NNI 提供命令行工具以及友好的 WebUI 来管理训练的 Experiment。
<li><a href="docs/zh_CN/Tuner/BuiltinTuner.md#TPE">TPE</a></li> <li><a href="docs/zh_CN/Tuner/BuiltinTuner.md#TPE">TPE</a></li>
<li><a href="docs/zh_CN/Tuner/BuiltinTuner.md#SMAC">SMAC</a></li> <li><a href="docs/zh_CN/Tuner/BuiltinTuner.md#SMAC">SMAC</a></li>
<li><a href="docs/zh_CN/Tuner/BuiltinTuner.md#MetisTuner">Metis Tuner</a></li> <li><a href="docs/zh_CN/Tuner/BuiltinTuner.md#MetisTuner">Metis Tuner</a></li>
<li><a href="docs/zh_CN/Tuner/BuiltinTuner.md#GPTuner">GP Tuner</a> </li> <li><a href="docs/zh_CN/Tuner/BuiltinTuner.md#GPTuner">GP Tuner</a></li>
</ul> </ul>
<b>基于强化学习</b> <b>基于强化学习</b>
<ul> <ul>
...@@ -119,10 +119,12 @@ NNI 提供命令行工具以及友好的 WebUI 来管理训练的 Experiment。 ...@@ -119,10 +119,12 @@ NNI 提供命令行工具以及友好的 WebUI 来管理训练的 Experiment。
<a href="docs/zh_CN/NAS/Overview.md">神经网络架构搜索</a> <a href="docs/zh_CN/NAS/Overview.md">神经网络架构搜索</a>
<ul> <ul>
<ul> <ul>
<li><a href="docs/zh_CN/NAS/Overview.md#enas">ENAS</a></li> <li><a href="docs/zh_CN/NAS/ENAS.md">ENAS</a></li>
<li><a href="docs/zh_CN/NAS/Overview.md#darts">DARTS</a></li> <li><a href="docs/zh_CN/NAS/DARTS.md">DARTS</a></li>
<li><a href="docs/zh_CN/NAS/Overview.md#p-darts">P-DARTS</a></li> <li><a href="docs/zh_CN/NAS/PDARTS.md">P-DARTS</a></li>
<li><a href="docs/zh_CN/NAS/Overview.md#cdarts">CDARTS</a></li> <li><a href="docs/zh_CN/NAS/CDARTS.md">CDARTS</a></li>
<li><a href="docs/zh_CN/NAS/SPOS.md">SPOS</a></li>
<li><a href="docs/zh_CN/NAS/Proxylessnas.md">ProxylessNAS</a></li>
<li><a href="docs/zh_CN/Tuner/BuiltinTuner.md#NetworkMorphism">Network Morphism</a> </li> <li><a href="docs/zh_CN/Tuner/BuiltinTuner.md#NetworkMorphism">Network Morphism</a> </li>
</ul> </ul>
</ul> </ul>
...@@ -219,7 +221,7 @@ Linux 和 macOS 下 NNI 系统需求[参考这里](https://nni.readthedocs.io/zh ...@@ -219,7 +221,7 @@ Linux 和 macOS 下 NNI 系统需求[参考这里](https://nni.readthedocs.io/zh
* 如果遇到任何权限问题,可添加 `--user` 在用户目录中安装 NNI。 * 如果遇到任何权限问题,可添加 `--user` 在用户目录中安装 NNI。
* 目前,Windows 上的 NNI 支持本机,远程和 OpenPAI 模式。 强烈推荐使用 Anaconda 或 Miniconda 在 Windows 上安装 NNI。 * 目前,Windows 上的 NNI 支持本机,远程和 OpenPAI 模式。 强烈推荐使用 Anaconda 或 Miniconda 在 Windows 上安装 NNI。
* 如果遇到如 `Segmentation fault` 等错误参考[常见问题](docs/zh_CN/Tutorial/FAQ.md)。 Windows 上的 FAQ 参考[在 Windows 上使用 NNI](docs/zh_CN/Tutorial/NniOnWindows.md) * 如果遇到如 `Segmentation fault` 等错误参考[常见问题](docs/zh_CN/Tutorial/FAQ.md)。 Windows 上的 FAQ 参考[在 Windows 上使用 NNI](docs/zh_CN/Tutorial/InstallationWin.md#faq)
### **验证安装** ### **验证安装**
...@@ -228,7 +230,7 @@ Linux 和 macOS 下 NNI 系统需求[参考这里](https://nni.readthedocs.io/zh ...@@ -228,7 +230,7 @@ Linux 和 macOS 下 NNI 系统需求[参考这里](https://nni.readthedocs.io/zh
* 通过克隆源代码下载示例。 * 通过克隆源代码下载示例。
```bash ```bash
git clone -b v1.3 https://github.com/Microsoft/nni.git git clone -b v1.4 https://github.com/Microsoft/nni.git
``` ```
* 运行 MNIST 示例。 * 运行 MNIST 示例。
...@@ -285,7 +287,7 @@ You can use these commands to get more information about the experiment ...@@ -285,7 +287,7 @@ You can use these commands to get more information about the experiment
* 要了解 NNI,请阅读 [NNI 概述](https://nni.readthedocs.io/zh/latest/Overview.html) * 要了解 NNI,请阅读 [NNI 概述](https://nni.readthedocs.io/zh/latest/Overview.html)
* 要熟悉如何使用 NNI,请阅读[文档](https://nni.readthedocs.io/zh/latest/index.html) * 要熟悉如何使用 NNI,请阅读[文档](https://nni.readthedocs.io/zh/latest/index.html)
* 要安装 NNI,请参阅[安装 NNI](docs/zh_CN/Tutorial/Installation.md) * 要安装并使用 NNI,参考[安装指南](https://nni.readthedocs.io/zh/latest/installation.html)
## **贡献** ## **贡献**
...@@ -303,22 +305,20 @@ You can use these commands to get more information about the experiment ...@@ -303,22 +305,20 @@ You can use these commands to get more information about the experiment
* 如果有使用上的问题,可先查看[常见问题解答](https://github.com/microsoft/nni/blob/master/docs/zh_CN/Tutorial/FAQ.md)。如果没能解决问题,可通过 [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) * 如果有使用上的问题,可先查看[常见问题解答](https://github.com/microsoft/nni/blob/master/docs/zh_CN/Tutorial/FAQ.md)。如果没能解决问题,可通过 [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.md) * [自定义 Tuner](docs/zh_CN/Tuner/CustomizeTuner.md)
* [实现定制的训练平台](docs/zh_CN/TrainingService/HowToImplementTrainingService.md) * [实现定制的训练平台](docs/zh_CN/TrainingService/HowToImplementTrainingService.md)
* [在 NNI 上实现新的 NAS Trainer](https://github.com/microsoft/nni/blob/master/docs/zh_CN/NAS/NasInterface.md#implement-a-new-nas-trainer-on-nni) * [在 NNI 上实现新的 NAS Trainer](docs/zh_CN/NAS/Advanced.md)
* [自定义 Advisor](docs/zh_CN/Tuner/CustomizeAdvisor.md) * [自定义 Advisor](docs/zh_CN/Tuner/CustomizeAdvisor.md)
## **其它代码库和参考** ## **其它代码库和参考**
经作者许可的一些 NNI 用法示例和相关文档。 经作者许可的一些 NNI 用法示例和相关文档。
* ### **外部代码库** * ### **外部代码库** ###
* 在 NNI 中运行 [ENAS](examples/tuners/enas_nni/README_zh_CN.md) * 在 NNI 中运行 [ENAS](examples/tuners/enas_nni/README_zh_CN.md)
* 在 NNI 中运行 [神经网络架构结构搜索](examples/trials/nas_cifar10/README_zh_CN.md) * 在 NNI 中运行 [神经网络架构结构搜索](examples/trials/nas_cifar10/README_zh_CN.md)
* [NNI 中的自动特征工程](examples/feature_engineering/auto-feature-engineering/README_zh_CN.md) * [NNI 中的自动特征工程](examples/feature_engineering/auto-feature-engineering/README_zh_CN.md)
* 使用 NNI 的 [矩阵分解超参调优](https://github.com/microsoft/recommenders/blob/master/notebooks/04_model_select_and_optimize/nni_surprise_svd.ipynb) * 使用 NNI 的 [矩阵分解超参调优](https://github.com/microsoft/recommenders/blob/master/notebooks/04_model_select_and_optimize/nni_surprise_svd.ipynb)
* [scikit-nni](https://github.com/ksachdeva/scikit-nni) 使用 NNI 为 scikit-learn 开发的超参搜索。 * [scikit-nni](https://github.com/ksachdeva/scikit-nni) 使用 NNI 为 scikit-learn 开发的超参搜索。
* ### **相关文章** * ### **相关文章** ###
* [超参数优化的对比](docs/zh_CN/CommunitySharings/HpoComparision.md) * [超参数优化的对比](docs/zh_CN/CommunitySharings/HpoComparision.md)
* [神经网络结构搜索的对比](docs/zh_CN/CommunitySharings/NasComparision.md) * [神经网络结构搜索的对比](docs/zh_CN/CommunitySharings/NasComparision.md)
* [并行化顺序算法:TPE](docs/zh_CN/CommunitySharings/ParallelizingTpeSearch.md) * [并行化顺序算法:TPE](docs/zh_CN/CommunitySharings/ParallelizingTpeSearch.md)
......
# 多阶段
## 多阶段 Experiment ## 多阶段 Experiment
通常,每个 Trial 任务只需要从 Tuner 获取一个配置(超参等),然后使用这个配置执行并报告结果,然后退出。 但有时,一个 Trial 任务可能需要从 Tuner 请求多次配置。 这是一个非常有用的功能。 例如: 通常,每个 Trial 任务只需要从 Tuner 获取一个配置(超参等),然后使用这个配置执行并报告结果,然后退出。 但有时,一个 Trial 任务可能需要从 Tuner 请求多次配置。 这是一个非常有用的功能。 例如:
......
# 内置 Assessor # 内置 Assessor
NNI 提供了先进的调优算法,使用上也很简单。 下面是内置 Assessor 的介绍 NNI 提供了先进的评估算法,使用上也很简单。 下面是内置 Assessor 的介绍
注意:点击 **Assessor 的名称**看到 Assessor 的安装需求,建议的场景以及示例。 算法的详细说明在每个 Assessor 建议场景最后。 注意:点击 **Assessor 的名称**了解每个 Assessor 的安装需求,建议的场景以及示例。 在每个 Assessor 建议场景最后,还有算法的详细说明
当前支持 Assessor: 当前支持以下 Assessor:
| Assessor | 算法简介 | | Assessor | 算法简介 |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
...@@ -27,7 +27,7 @@ NNI 提供了先进的调优算法,使用上也很简单。 下面是内置 As ...@@ -27,7 +27,7 @@ NNI 提供了先进的调优算法,使用上也很简单。 下面是内置 As
适用于各种性能曲线,可用到各种场景中来加速优化过程。 [详细说明](./MedianstopAssessor.md) 适用于各种性能曲线,可用到各种场景中来加速优化过程。 [详细说明](./MedianstopAssessor.md)
**参数** **classArgs 要求:**
* **optimize_mode** (*maximize 或 minimize, 可选, 默认值为 maximize*) - 如果为 'maximize', Assessor 会在结果小于期望值时**终止** Trial。 如果为 'minimize',Assessor 会在结果大于期望值时**终止** Trial。 * **optimize_mode** (*maximize 或 minimize, 可选, 默认值为 maximize*) - 如果为 'maximize', Assessor 会在结果小于期望值时**终止** Trial。 如果为 'minimize',Assessor 会在结果大于期望值时**终止** Trial。
* **start_step** (*int, 可选, 默认值为 0*) - 只有收到 start_step 个中间结果后,才开始判断是否一个 Trial 应该被终止。 * **start_step** (*int, 可选, 默认值为 0*) - 只有收到 start_step 个中间结果后,才开始判断是否一个 Trial 应该被终止。
...@@ -55,7 +55,7 @@ assessor: ...@@ -55,7 +55,7 @@ assessor:
适用于各种性能曲线,可用到各种场景中来加速优化过程。 更好的地方是,它能处理并评估性能类似的曲线。 [详细说明](./CurvefittingAssessor.md) 适用于各种性能曲线,可用到各种场景中来加速优化过程。 更好的地方是,它能处理并评估性能类似的曲线。 [详细说明](./CurvefittingAssessor.md)
**参数** **classArgs 要求:**
* **epoch_num** (*int, **必需***) - epoch 的总数。 需要此数据来决定需要预测点的总数。 * **epoch_num** (*int, **必需***) - epoch 的总数。 需要此数据来决定需要预测点的总数。
* **optimize_mode** (*maximize 或 minimize, 可选, 默认值为 maximize*) - 如果为 'maximize', Assessor 会在结果小于期望值时**终止** Trial。 如果为 'minimize',Assessor 会在结果大于期望值时**终止** Trial。 * **optimize_mode** (*maximize 或 minimize, 可选, 默认值为 maximize*) - 如果为 'maximize', Assessor 会在结果小于期望值时**终止** Trial。 如果为 'minimize',Assessor 会在结果大于期望值时**终止** Trial。
......
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
## 1. 介绍 ## 1. 介绍
Curve Fitting Assessor 是一个 LPA (learning, predicting, assessing,即学习、预测、评估) 的算法。 如果预测的Trial X 在 step S 比性能最好的 Trial 要差,就会提前终止它。 Curve Fitting Assessor 是一个 LPA (learning, predicting, assessing,即学习、预测、评估) 的算法。 如果预测的 Trial X 在 step S 比性能最好的 Trial 要差,就会提前终止它。
此算法中,使用了 12 曲线来拟合学习曲线,从[参考论文](http://aad.informatik.uni-freiburg.de/papers/15-IJCAI-Extrapolation_of_Learning_Curves.pdf)中选择了大量的参数曲线模型。 学习曲线的形状与先验知识是一致的:都是典型的递增的、饱和的函数。 此算法中用了 12 曲线来拟合学习曲线。 这组参数曲线模型来自于[参考论文](http://aad.informatik.uni-freiburg.de/papers/15-IJCAI-Extrapolation_of_Learning_Curves.pdf)。 学习曲线的形状与先验知识是一致的:都是典型的递增的、饱和的函数。
![](../../img/curvefitting_learning_curve.PNG) ![](../../img/curvefitting_learning_curve.PNG)
...@@ -12,7 +12,7 @@ Curve Fitting Assessor 是一个 LPA (learning, predicting, assessing,即学 ...@@ -12,7 +12,7 @@ Curve Fitting Assessor 是一个 LPA (learning, predicting, assessing,即学
![](../../img/curvefitting_f_comb.gif) ![](../../img/curvefitting_f_comb.gif)
合并后的参数向量 合并后的参数向量
![](../../img/curvefitting_expression_xi.gif) ![](../../img/curvefitting_expression_xi.gif)
...@@ -22,11 +22,11 @@ Curve Fitting Assessor 是一个 LPA (learning, predicting, assessing,即学 ...@@ -22,11 +22,11 @@ Curve Fitting Assessor 是一个 LPA (learning, predicting, assessing,即学
具体来说,该算法有学习、预测和评估三个阶段。 具体来说,该算法有学习、预测和评估三个阶段。
* 步骤 1:学习。 从当前 Trial 的历史中学习,并从贝叶斯角度决定 \xi 。 首先,使用最小二乘法 (`fit_theta` 实现) 来节省时间。 获得参数后,过滤曲线并移除异常点(由 `filter_curve` 实现)。 最后,使用 MCMC 采样方法 (`mcmc_sampling` 实现) 来调整每曲线的权重。 至此,确定了 \xi 中的所有参数。 * 步骤 1:学习。 从当前 Trial 的历史中学习,并从贝叶斯角度决定 \xi 。 首先,使用由 `fit_theta` 实现的最小二乘法。 获得参数后,过滤曲线并移除异常点(由 `filter_curve` 实现)。 最后,使用 MCMC 采样方法`mcmc_sampling` 实现来调整每曲线的权重。 至此,确定了 \xi 中的所有参数。
* 步骤 2:预测。 用 \xi 和混合模型公式,在目标位置(例如 epoch 的总数)来计算期望的最终结果精度(由 `f_comb` 实现) * 步骤 2:预测。 用 \xi 和混合模型公式,`f_comb` 实现了,在目标位置(例如 epoch 的总数)来计算期望的最终结果精度。
* 步骤 3:如果拟合结果没有收敛,预测结果会是 `None`,并返回 `AssessResult.Good`,待下次有了更多精确信息后再次预测。 此外,会通过 `predict()` 函数获得正数。如果该值大于 __历史最好结果__ * `THRESHOLD`(默认为 0.95),则返回 `AssessResult.Good`,否则返回 `AssessResult.Bad` * 步骤 3:如果拟合结果收敛,预测值将为 `None`。 在这种情况下,会返回 `AssessResult.Good/code> 来请求进一步的精度和预测信息。 此外,将从 <code>predict()` 函数获得正确值。 如果该值大于历史最好结果 * `THRESHOLD`默认为 0.95,则返回 `AssessResult.Good`,否则返回 `AssessResult.Bad`
下图显示了此算法在 MNIST Trial 历史数据上结果。其中绿点表示 Assessor 获得的数据,蓝点表示将来,但未知的数据,红色线条是 Curve fitting Assessor 的预测曲线。 下图显示了此算法在 MNIST Trial 历史数据上结果。其中绿点表示 Assessor 获得的数据,蓝点表示将来,但未知的数据,红色线条是 Curve fitting Assessor 的预测曲线。
...@@ -61,7 +61,7 @@ Curve Fitting Assessor 是一个 LPA (learning, predicting, assessing,即学 ...@@ -61,7 +61,7 @@ Curve Fitting Assessor 是一个 LPA (learning, predicting, assessing,即学
## 3. 文件结构 ## 3. 文件结构
Assessor 有大量的文件、函数和类。 这里只简单介绍最重要的文件: Assessor 有大量的文件、函数和类。 这里,会简要描述其中一部分。
* `curvefunctions.py` 包含了所有函数表达式和默认参数。 * `curvefunctions.py` 包含了所有函数表达式和默认参数。
* `modelfactory.py` 包括学习和预测部分,并实现了相应的计算部分。 * `modelfactory.py` 包括学习和预测部分,并实现了相应的计算部分。
......
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
## Median Stop ## Median Stop
Medianstop 是一种简单的提前终止 Trial 的策略,可参考[论文](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/46180.pdf)。 如果 Trial X 在步骤 S 的最好目标值低于所有已完成 Trial 前 S 个步骤目标平均值的中位数,这个 Trial 就会被提前停止。 Medianstop 是一种简单的提前终止策略,可参考[论文](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/46180.pdf)。 如果 Trial X 在步骤 S 的最好目标值低于所有已完成 Trial 前 S 个步骤目标平均值的中位数,这个 Trial 就会被提前停止。
\ No newline at end of file \ No newline at end of file
# 设计文档
## 概述
模型压缩框架有两个主要组件: `Pruner``module 的包装`
### Pruner
`Pruner` 用于:
1. 提供 `cal_mask` 方法来计算权重和偏差的掩码(mask)。
2. 根据配置,用 `module 的包装`来替换原始的 module。
3. 修改优化器,来在 `step` 方法被调用时,调用 `cal_mask`
### module 的包装
`module 的包装` 包含:
1. 原始的 module
2. `cal_mask` 使用的一些缓存
3. 新的 forward 方法,用于在运行原始的 forward 方法前应用掩码。
使用 `module 包装`的原因:
1. 计算掩码所需要的 `cal_mask` 方法需要一些缓存,这些缓存需要注册在 `module 包装`里,这样就不需要修改原始的 module。
2. 新的 `forward` 方法用来在原始 `forward` 调用前,将掩码应用到权重上。
## 工作原理
基本的 Pruner 用法:
```python
configure_list = [{
'sparsity': 0.7,
'op_types': ['BatchNorm2d'],
}]
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9, weight_decay=1e-4)
pruner = SlimPruner(model, configure_list, optimizer)
model = pruner.compress()
```
Pruner 接收模型,配置和优化器作为参数。 在 `__init__` 方法中,优化器的 `step` 方法会被一个会调用 `cal_mask` 的新的 `step` 方法替换。 同样,所有 module 都会检查它们是否被配置为需要剪枝。如果 module 需要被剪枝,就会用 `module 包装`来替换它。 之后,会返回新的模型和优化器,并进行训练。 `compress` 方法会计算默认的掩码。
## 实现新的剪枝算法
要实现新的剪枝算法,需要继承 `Pruner` 来实现新的类,并重载 `cal_mask` 方法。 `cal_mask` 会被 `optimizer.step` 方法调用。 `Pruner` 基类提供了上述的基本功能,如替换 module 和优化器。
基础的 Pruner 如下所示:
```python
class NewPruner(Pruner):
def __init__(self, model, config_list, optimizer)
super().__init__(model, config_list, optimizer)
# 进行初始化
def calc_mask(self, wrapper, **kwargs):
# 计算 weight_mask
wrapper.weight_mask = weight_mask
```
### 设置包装的属性
有时,`cal_mask` 需要保存一些状态数据,可以像 PyTorch 的 module 一样,使用 `set_wrappers_attribute` API 来注册属性。 这些缓存会注册到 `module 包装`中。 用户可以通过 `module 包装`来直接访问这些缓存。
```python
class NewPruner(Pruner):
def __init__(self, model, config_list, optimizer):
super().__init__(model, config_list, optimizer)
self.set_wrappers_attribute("if_calculated", False)
def calc_mask(self, wrapper):
# 计算 weight_mask
if wrapper.if_calculated:
pass
else:
wrapper.if_calculated = True
# 更新掩码
```
### 在 forward 时收集数据
有时,需要在 forward 方法中收集数据,例如,需要激活的平均值。 这时,可以为 module 增加定制的收集方法。
```python
class ActivationRankFilterPruner(Pruner):
def __init__(self, model, config_list, optimizer, activation='relu', statistics_batch_num=1):
super().__init__(model, config_list, optimizer)
self.set_wrappers_attribute("if_calculated", False)
self.set_wrappers_attribute("collected_activation", [])
self.statistics_batch_num = statistics_batch_num
def collector(module_, input_, output):
if len(module_.collected_activation) < self.statistics_batch_num:
module_.collected_activation.append(self.activation(output.detach().cpu()))
self.add_activation_collector(collector)
assert activation in ['relu', 'relu6']
if activation == 'relu':
self.activation = torch.nn.functional.relu
elif activation == 'relu6':
self.activation = torch.nn.functional.relu6
else:
self.activation = None
```
收集函数会在每次 forward 方法运行时调用。
还可这样来移除收集方法:
```python
collector_id = self.add_activation_collector(collector)
# ...
self.remove_activation_collector(collector_id)
```
### 多 GPU 支持
在多 GPU 训练中,缓存和参数会在每次 `forward` 方法被调用时,复制到多个 GPU 上。 如果缓存和参数要在 `forward` 更新,就需要通过`原地`更新来提高效率。 因为 `cal_mask` 会在 `optimizer.step` 方法中的调用,会在 `forward` 方法后才被调用,且只会发生在单 GPU 上,因此它天然的就支持多 GPU 的情况。
\ No newline at end of file
# 加速掩码的模型
*此功能还处于预览版。*
## 介绍
剪枝算法通常都用权重掩码来模拟实际的剪枝。 掩码可以用来检查某个剪枝(或稀疏)算法的模型性能,但还没有真正加速。 模型加速才是模型剪枝的最终目标。因此提供了此工具,来帮助基于用户提供的掩码(掩码来自于剪枝算法),将已有模型转换成小模型。
有两种剪枝算法。 一种是细粒度的剪枝,不改变权重形状,和输入输出的张量。 稀疏内核会被用来加速细粒度剪枝的层。 另一类是粗粒度的剪枝(例如,通道),通常,权重形状,输入输出张量会有所改变。 要加速这类剪枝算法,不需要使用系数内核,只需要用更小的层来替换。 由于开源社区中对稀疏内核的支持还比较有限,当前仅支持粗粒度剪枝,会在将来再支持细粒度的剪枝算法。
## 设计和实现
为了加速模型,被剪枝的层应该被替换掉,要么为粗粒度掩码使用较小的层,要么用稀疏内核来替换细粒度的掩码。 粗粒度掩码通常会改变权重的形状,或输入输出张量,因此,应该通过形状推断,来检查是否其它未被剪枝的层由于形状变化而需要改变形状。 因此,在设计中,主要有两个步骤:第一,做形状推理,找出所有应该替换的模块;第二,替换模块。 第一步需要模型的拓扑(即连接),我们使用了 `jit.trace` 来获取 PyTorch 的模型图。
对于每个模块,要准备四个函数,三个用于形状推理,一个用于模块替换。 三个形状推理函数是:给定权重形状推断输入/输出形状,给定输入形状推断权重/输出形状,给定输出形状推断权重/输入形状。 模块替换功能返回一个较小的新创建的模块。
## 用法
```python
from nni.compression.speedup.torch import ModelSpeedup
# model: 要加速的模型
# dummy_input: 模型的示输入,传给 `jit.trace`
# masks_file: 剪枝算法创建的掩码文件
m_speedup = ModelSpeedup(model, dummy_input.to(device), masks_file)
m_speedup.speedup_model()
dummy_input = dummy_input.to(device)
start = time.time()
out = model(dummy_input)
print('elapsed time: ', time.time() - start)
```
完整示例参考[这里](https://github.com/microsoft/nni/tree/master/examples/model_compress/model_speedup.py)
注意:当前实现仅用于 torch 1.3.1 和 torchvision 0.4.2
## 局限性
由于每个模块需要 4 个函数用于形状推理和模块替换,因此工作量较大,当前仅实现了示例所需的函数。 如果要加速自己的模型,但当前不支持,欢迎贡献。
对于 PyTorch,仅提供了替换模块,如果是在 `forward` 中的函数,当前不支持。 一种解决方案是将函数变为 PyTorch 模块。
## 示例的加速结果
实验代码可在[这里](https://github.com/microsoft/nni/tree/master/examples/model_compress/model_speedup.py)找到。
### slim Pruner 示例
在一块 V100 GPU 上, 输入张量:`torch.randn(64, 3, 32, 32)`
| 次数 | 掩码时延 | 加速后的时延 |
| -- | ------- | -------- |
| 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 示例
在 CPU 上, 输入张量:`torch.randn(64, 1, 28, 28)`, 方差较大
| 次数 | 掩码时延 | 加速后的时延 |
| --- | ------- | -------- |
| 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 示例
在一块 V100 GPU 上, 输入张量:`torch.randn(64, 3, 32, 32)`
| 次数 | 掩码时延 | 加速后的时延 |
| -- | ------- | -------- |
| 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 示例
在一块 V100 GPU 上, 输入张量:`torch.randn(64, 3, 32, 32)`
| 次数 | 掩码时延 | 加速后的时延 |
| -- | ------- | -------- |
| 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 |
# 使用 NNI 进行模型压缩 # 使用 NNI 进行模型压缩
随着更多层和节点大型神经网络的使用,降低其存储和计算成本变得至关重要,尤其是对于某些实时应用程序。 模型压缩可用于解决此问题。 随着更多层和节点大型神经网络的使用,降低其存储和计算成本变得至关重要,尤其是对于某些实时应用程序。 模型压缩可用于解决此问题。
我们很高兴的宣布,基于 NNI 的模型压缩工具发布了试用版本。该版本仍处于试验阶段,根据用户反馈进行改进。 诚挚邀请您使用、反馈,或有更多贡献。 我们很高兴的宣布,基于 NNI 的模型压缩工具发布了。该版本仍处于试验阶段,根据用户反馈进行改进。 诚挚邀请您使用、反馈,或有更多贡献。
NNI 提供了易于使用的工具包来帮助用户设计并使用压缩算法。 当前支持基于 PyTorch 的统一接口。 只需要添加几行代码即可压缩模型。 NNI 中也内置了一些流程的模型压缩算法。 用户还可以通过 NNI 强大的自动调参功能来找到最好的压缩后的模型,详见[自动模型压缩](./AutoCompression.md)。 另外,用户还能使用 NNI 的接口,轻松定制新的压缩算法,详见[教程](#customize-new-compression-algorithms) NNI 提供了易于使用的工具包来帮助用户设计并使用压缩算法。 当前支持基于 PyTorch 的统一接口。 只需要添加几行代码即可压缩模型。 NNI 中也内置了一些流程的模型压缩算法。 用户还可以通过 NNI 强大的自动调参功能来找到最好的压缩后的模型,详见[自动模型压缩](./AutoCompression.md)。 另外,用户还能使用 NNI 的接口,轻松定制新的压缩算法,详见[教程](#customize-new-compression-algorithms) 关于模型压缩框架如何工作的详情可参考[这里](./Framework.md)
模型压缩方面的综述可参考:[Recent Advances in Efficient Computation of Deep Convolutional Neural Networks](https://arxiv.org/pdf/1802.00939.pdf) 模型压缩方面的综述可参考:[Recent Advances in Efficient Computation of Deep Convolutional Neural Networks](https://arxiv.org/pdf/1802.00939.pdf)
...@@ -332,9 +332,9 @@ class YourQuantizer(Quantizer): ...@@ -332,9 +332,9 @@ class YourQuantizer(Quantizer):
如果不定制 `QuantGrad`,默认的 backward 为 Straight-Through Estimator。 _即将推出_... 如果不定制 `QuantGrad`,默认的 backward 为 Straight-Through Estimator。 _即将推出_...
## **参考和反馈** ## 参考和反馈
* 在 GitHub 中[提交此功能的 Bug](https://github.com/microsoft/nni/issues/new?template=bug-report.md) * 在 GitHub 中[提交此功能的 Bug](https://github.com/microsoft/nni/issues/new?template=bug-report.md)
* 在 GitHub 中[提交新功能或改进请求](https://github.com/microsoft/nni/issues/new?template=enhancement.md) * 在 GitHub 中[提交新功能或改进请求](https://github.com/microsoft/nni/issues/new?template=enhancement.md)
* 了解 NNI 中[特征工程的更多信息](https://github.com/microsoft/nni/blob/master/docs/zh_CN/FeatureEngineering/Overview.md) * 了解更多关于 [NNI 中特征工程](../FeatureEngineering/Overview.md)
* 了解 NNI 中[ NAS 的更多信息](https://github.com/microsoft/nni/blob/master/docs/zh_CN/NAS/Overview.md) * 了解更多关于 [NNI 中 NAS](../NAS/Overview.md)
* 了解如何[使用 NNI 进行超参调优](https://github.com/microsoft/nni/blob/master/docs/zh_CN/Tuner/BuiltinTuner.md) * 了解更多关于 [NNI 中的超参调优](../Tuner/BuiltinTuner.md)
...@@ -13,6 +13,8 @@ NNI Compressor 中的 Pruner ...@@ -13,6 +13,8 @@ NNI Compressor 中的 Pruner
* [具有激活等级的 Filter Pruners](#activationrankfilterpruner) * [具有激活等级的 Filter Pruners](#activationrankfilterpruner)
* [APoZ Rank Pruner](#activationapozrankfilterpruner) * [APoZ Rank Pruner](#activationapozrankfilterpruner)
* [Activation Mean Rank Pruner](#activationmeanrankfilterpruner) * [Activation Mean Rank Pruner](#activationmeanrankfilterpruner)
* [具有梯度等级的 Filter Pruners](#gradientrankfilterpruner)
* [Taylor FO On Weight Pruner](#taylorfoweightfilterpruner)
## Level Pruner ## Level Pruner
...@@ -335,3 +337,40 @@ pruner.compress() ...@@ -335,3 +337,40 @@ pruner.compress()
- **sparsity:** 卷积过滤器要修剪的百分比。 - **sparsity:** 卷积过滤器要修剪的百分比。
- **op_types:** 在 ActivationMeanRankFilterPruner 中仅支持 Conv2d。 - **op_types:** 在 ActivationMeanRankFilterPruner 中仅支持 Conv2d。
## GradientRankFilterPruner
GradientRankFilterPruner 是一系列的 Pruner,在卷积层梯度上,用最小的重要性标准修剪过滤器,来达到预设的网络稀疏度。
### TaylorFOWeightFilterPruner
其实现为一次性 Pruner,会根据权重的一阶泰勒展开式来对卷积层进行剪枝。 过滤器的估计重要性在论文 [Importance Estimation for Neural Network Pruning](http://jankautz.com/publications/Importance4NNPruning_CVPR19.pdf) 中有定义。 本文中提到的其他修剪标准将在以后的版本中支持。
>
![](../../img/importance_estimation_sum.png)
#### 用法
PyTorch 代码
```python
from nni.compression.torch import TaylorFOWeightFilterPruner
config_list = [{
'sparsity': 0.5,
'op_types': ['Conv2d']
}]
pruner = TaylorFOWeightFilterPruner(model, config_list, optimizer)
pruner.compress()
```
查看示例进一步了解
#### GradientWeightSumFilterPruner 的用户配置
- **sparsity:** 卷积过滤器要修剪的百分比。
- **op_types:** 当前 TaylorFOWeightFilterPruner 中仅支持 Conv2d。
 
\ No newline at end of file
# 模型压缩快速入门 # 模型压缩快速入门
NNI 为模型压缩提供了非常简单的 API。 压缩包括剪枝和量化算法。 它们的用法相同,这里通过 slim Pruner 来演示如何使用。 完整示例在[这里](https://github.com/microsoft/nni/blob/master/examples/model_compress/slim_torch_cifar10.py) NNI 为模型压缩提供了非常简单的 API。 压缩包括剪枝和量化算法。 它们的用法相同,这里通过 slim Pruner 来演示如何使用。
## 编写配置 ## 编写配置
...@@ -34,6 +34,8 @@ model = pruner.compress() ...@@ -34,6 +34,8 @@ model = pruner.compress()
pruner.export_model(model_path='pruned_vgg19_cifar10.pth', mask_path='mask_vgg19_cifar10.pth') pruner.export_model(model_path='pruned_vgg19_cifar10.pth', mask_path='mask_vgg19_cifar10.pth')
``` ```
模型的完整示例代码在[这里](https://github.com/microsoft/nni/blob/master/examples/model_compress/model_prune_torch.py)
## 加速模型 ## 加速模型
掩码实际上并不能加速模型。 要基于导出的掩码,来对模型加速,因此,NNI 提供了 API 来加速模型。 在模型上调用 `apply_compression_results` 后,模型会变得更小,推理延迟也会减小。 掩码实际上并不能加速模型。 要基于导出的掩码,来对模型加速,因此,NNI 提供了 API 来加速模型。 在模型上调用 `apply_compression_results` 后,模型会变得更小,推理延迟也会减小。
......
...@@ -31,7 +31,7 @@ for _ in range(epochs): ...@@ -31,7 +31,7 @@ for _ in range(epochs):
最后,Mutator 会提供叫做 `mutator.export()` 的方法来将模型的架构参数作为 dict 导出。 注意,当前 dict 是从 Mutable 键值到选择张量的映射。 为了存储到 JSON,用户需要将张量显式的转换为 Python 的 list。 最后,Mutator 会提供叫做 `mutator.export()` 的方法来将模型的架构参数作为 dict 导出。 注意,当前 dict 是从 Mutable 键值到选择张量的映射。 为了存储到 JSON,用户需要将张量显式的转换为 Python 的 list。
同时,NNI 提供了工具,能更容易地实现 Trainer。 参考 [Trainer](./NasReference.md#trainers) 了解详情。 同时,NNI 提供了工具,能更容易地实现 Trainer。 参考 [Trainer](./NasReference.md) 了解详情。
## 实现新的 Mutator ## 实现新的 Mutator
...@@ -94,7 +94,7 @@ class RandomMutator(Mutator): ...@@ -94,7 +94,7 @@ class RandomMutator(Mutator):
## 实现分布式 NAS Tuner ## 实现分布式 NAS Tuner
在学习编写 One-Shot NAS Tuner前,应先了解如何写出通用的 Tuner。 阅读[自定义 Tuner](../Tuner/CustomizeTuner.md) 的教程。 在学习编写分布式 NAS Tuner前,应先了解如何写出通用的 Tuner。 阅读[自定义 Tuner](../Tuner/CustomizeTuner.md) 的教程。
当调用 "[nnictl ss_gen](../Tutorial/Nnictl.md)" 时,会生成下面这样的搜索空间文件: 当调用 "[nnictl ss_gen](../Tutorial/Nnictl.md)" 时,会生成下面这样的搜索空间文件:
......
...@@ -46,16 +46,12 @@ bash run_retrain_cifar.sh ...@@ -46,16 +46,12 @@ bash run_retrain_cifar.sh
.. autoclass:: nni.nas.pytorch.cdarts.CdartsTrainer .. autoclass:: nni.nas.pytorch.cdarts.CdartsTrainer
:members: :members:
.. automethod:: __init__
.. autoclass:: nni.nas.pytorch.cdarts.RegularizedDartsMutator .. autoclass:: nni.nas.pytorch.cdarts.RegularizedDartsMutator
:members: :members:
.. autoclass:: nni.nas.pytorch.cdarts.DartsDiscreteMutator .. autoclass:: nni.nas.pytorch.cdarts.DartsDiscreteMutator
:members: :members:
.. automethod:: __init__
.. autoclass:: nni.nas.pytorch.cdarts.RegularizedMutatorParallel .. autoclass:: nni.nas.pytorch.cdarts.RegularizedMutatorParallel
:members: :members:
``` ```
...@@ -43,8 +43,10 @@ python3 retrain.py --arc-checkpoint ./checkpoints/epoch_49.json ...@@ -43,8 +43,10 @@ python3 retrain.py --arc-checkpoint ./checkpoints/epoch_49.json
.. autoclass:: nni.nas.pytorch.darts.DartsTrainer .. autoclass:: nni.nas.pytorch.darts.DartsTrainer
:members: :members:
.. automethod:: __init__
.. autoclass:: nni.nas.pytorch.darts.DartsMutator .. autoclass:: nni.nas.pytorch.darts.DartsMutator
:members: :members:
``` ```
## 局限性
* DARTS 不支持 DataParallel,若要支持 DistributedDataParallel,则需要定制。
...@@ -37,10 +37,6 @@ python3 search.py -h ...@@ -37,10 +37,6 @@ python3 search.py -h
.. autoclass:: nni.nas.pytorch.enas.EnasTrainer .. autoclass:: nni.nas.pytorch.enas.EnasTrainer
:members: :members:
.. automethod:: __init__
.. autoclass:: nni.nas.pytorch.enas.EnasMutator .. autoclass:: nni.nas.pytorch.enas.EnasMutator
:members: :members:
.. automethod:: __init__
``` ```
...@@ -70,17 +70,17 @@ Input Choice 可被视为可调用的模块,它接收张量数组,输出其 ...@@ -70,17 +70,17 @@ Input Choice 可被视为可调用的模块,它接收张量数组,输出其
`LayerChoice``InputChoice` 都是 **Mutable**。 Mutable 表示 "可变化的"。 与传统深度学习层、模型都是固定的不同,使用 Mutable 的模块,是一组可能选择的模型。 `LayerChoice``InputChoice` 都是 **Mutable**。 Mutable 表示 "可变化的"。 与传统深度学习层、模型都是固定的不同,使用 Mutable 的模块,是一组可能选择的模型。
用户可为每个 Mutable 指定 **key**。 默认情况下,NNI 会分配全局唯一的,但如果需要共享 Choice(例如,两个 `LayerChoice` 有同样的候选操作,希望共享同样的 Choice。即,如果一个选择了第 i 个操作,第二个也要选择第 i 个操作),那么就应该给它们相同的 key。 key 标记了此 Choice,并会在存储的检查点中使用。 如果要增加导出架构的可读性,可为每个 Mutable 的 key 指派名称。 高级用法参考 [Mutable](./NasReference.md#mutables) 用户可为每个 Mutable 指定 **key**。 默认情况下,NNI 会分配全局唯一的,但如果需要共享 Choice(例如,两个 `LayerChoice` 有同样的候选操作,希望共享同样的 Choice。即,如果一个选择了第 i 个操作,第二个也要选择第 i 个操作),那么就应该给它们相同的 key。 key 标记了此 Choice,并会在存储的检查点中使用。 如果要增加导出架构的可读性,可为每个 Mutable 的 key 指派名称。 高级用法参考 [Mutable](./NasReference.md)
## 使用搜索算法 ## 使用搜索算法
搜索空间的探索方式和 Trial 生成方式不同,至少有两种不同的方法用来搜索。 一种是分布式运行 NAS,可从头枚举运行所有架构。或者利用更多高级功能,如 [SMASH](https://arxiv.org/abs/1708.05344), [ENAS](https://arxiv.org/abs/1802.03268), [DARTS](https://arxiv.org/abs/1808.05377), [FBNet](https://arxiv.org/abs/1812.03443), [ProxylessNAS](https://arxiv.org/abs/1812.00332), [SPOS](https://arxiv.org/abs/1904.00420), [Single-Path NAS](https://arxiv.org/abs/1904.02877), [Understanding One-shot](http://proceedings.mlr.press/v80/bender18a) 以及 [GDAS](https://arxiv.org/abs/1910.04465)。 由于很多不同架构搜索起来成本较高,另一类方法,即 One-Shot NAS,在搜索空间中,构建包含有所有候选网络的超网络,每一步中选择一个或几个子网络来训练。 除了使用搜索空间外,还可以通过其他两种方式进行搜索。 一种是分布式运行 NAS,可从头枚举运行所有架构。或者利用更多高级功能,如 [SMASH](https://arxiv.org/abs/1708.05344), [ENAS](https://arxiv.org/abs/1802.03268), [DARTS](https://arxiv.org/abs/1808.05377), [FBNet](https://arxiv.org/abs/1812.03443), [ProxylessNAS](https://arxiv.org/abs/1812.00332), [SPOS](https://arxiv.org/abs/1904.00420), [Single-Path NAS](https://arxiv.org/abs/1904.02877), [Understanding One-shot](http://proceedings.mlr.press/v80/bender18a) 以及 [GDAS](https://arxiv.org/abs/1910.04465)。 由于很多不同架构搜索起来成本较高,另一类方法,即 One-Shot NAS,在搜索空间中,构建包含有所有候选网络的超网络,每一步中选择一个或几个子网络来训练。
当前,NNI 支持数种 One-Shot 方法。 例如,`DartsTrainer` 使用 SGD 来交替训练架构和模型权重,`ENASTrainer` [使用 Controller 来训练模型](https://arxiv.org/abs/1802.03268)。 新的、更高效的 NAS Trainer 在研究界不断的涌现出来。 当前,NNI 支持数种 One-Shot 方法。 例如,`DartsTrainer` 使用 SGD 来交替训练架构和模型权重,`ENASTrainer` [使用 Controller 来训练模型](https://arxiv.org/abs/1802.03268)。 新的、更高效的 NAS Trainer 在研究界不断的涌现出来,NNI 会在将来的版本中实现其中的一部分
### One-Shot NAS ### One-Shot NAS
每个 One-Shot NAS 都实现了 Trainer,可在每种算法说明中找到详细信息。 这是如何使用 `EnasTrainer` 的简单示例。 每个 One-Shot NAS 算法都实现了 Trainer,可在每种算法说明中找到详细信息。 这是如何使用 `EnasTrainer` 的简单示例。
```python ```python
# 此处与普通模型训练相同 # 此处与普通模型训练相同
...@@ -118,7 +118,7 @@ trainer.export(file="model_dir/final_architecture.json") # 将最终架构导 ...@@ -118,7 +118,7 @@ trainer.export(file="model_dir/final_architecture.json") # 将最终架构导
用户可直接通过 `python3 train.py` 开始训练,不需要使用 `nnictl`。 训练完成后,可通过 `trainer.export()` 导出找到的最好的模型。 用户可直接通过 `python3 train.py` 开始训练,不需要使用 `nnictl`。 训练完成后,可通过 `trainer.export()` 导出找到的最好的模型。
通常,Trainer 会有些可定制的参数,例如,损失函数,指标函数,优化器以及数据集。 这些功能可满足大部分需求,NNI 会尽力让内置 Trainer 能够处理更多的模型、任务和数据集。 但无法保证全面的支持。 例如,一些 Trainer 假设必须是分类任务;一些 Trainer 对 "Epoch" 的定义有所不同(例如,ENAS 的 epoch 表示一部分子步骤加上一些 Controller 的步骤);大多数 Trainer 不支持分布式训练,不会将模型通过 `DataParallel``DistributedDataParallel` 进行包装。 如果通过试用,想要在定制的应用中使用 Trainer,可能需要[自定义 Trainer](#extend-the-ability-of-one-shot-trainers) 通常,Trainer 会提供一些可以自定义的参数如,损失函数,指标函数,优化器以及数据集。 这些功能可满足大部分需求,NNI 会尽力让内置 Trainer 能够处理更多的模型、任务和数据集。 但无法保证全面的支持。 例如,一些 Trainer 假设必须是分类任务;一些 Trainer 对 "Epoch" 的定义有所不同(例如,ENAS 的 epoch 表示一部分子步骤加上一些 Controller 的步骤);大多数 Trainer 不支持分布式训练,不会将模型通过 `DataParallel``DistributedDataParallel` 进行包装。 如果通过试用,想要在定制的应用中使用 Trainer,可能需要[自定义 Trainer](#extend-the-ability-of-one-shot-trainers)
### 分布式 NAS ### 分布式 NAS
...@@ -136,7 +136,7 @@ acc = test(model) # 测试训练好的模型 ...@@ -136,7 +136,7 @@ acc = test(model) # 测试训练好的模型
nni.report_final_result(acc) # 报告所选架构的性能 nni.report_final_result(acc) # 报告所选架构的性能
``` ```
搜索空间应生成,并发送给 Tuner。 通过 NNI NAS API,搜索空间嵌入用户代码中,需要通过 "[nnictl ss_gen](../Tutorial/Nnictl.md)" 生成搜索空间文件。 然后,将生成的搜索空间文件路径填入 `config.yml``searchSpacePath``config.yml` 中的其它字段参考[教程](../Tutorial/QuickStart.md) 搜索空间应生成,并发送给 Tuner。 NNI NAS API 一样,搜索空间嵌入到了用户代码中。 用户可以使用 "[nnictl ss_gen](../Tutorial/Nnictl.md)" 生成搜索空间文件。 然后,将生成的搜索空间文件路径填入 `config.yml``searchSpacePath``config.yml` 中的其它字段参考[教程](../Tutorial/QuickStart.md)
可使用 [NNI Tuner](../Tuner/BuiltinTuner.md) 来搜索。 目前,只有 PPO Tuner 支持 NAS 搜索空间。 可使用 [NNI Tuner](../Tuner/BuiltinTuner.md) 来搜索。 目前,只有 PPO Tuner 支持 NAS 搜索空间。
...@@ -162,6 +162,6 @@ JSON 文件是从 Mutable key 到 Choice 的表示。 例如: ...@@ -162,6 +162,6 @@ JSON 文件是从 Mutable key 到 Choice 的表示。 例如:
} }
``` ```
应用后,模型会被固定,并准备好进行最终训练。 虽然它可能包含了更多的参数,但可作为单个模型来使用。 这各有利弊。 好的方面是,可以在搜索阶段直接读取来自超网络的检查点,并开始重新训练。 但是,这也造成模型有荣誉的参数,在计算模型所包含的参数数量时,可能会不准确。 更多深层次原因和解决方法可参考 [Trainer](./NasReference.md#retrain) 应用后,模型会被固定,并准备好进行最终训练。 虽然它可能包含了更多的参数,但可作为单个模型来使用。 这各有利弊。 好的方面是,可以在搜索阶段直接读取来自超网络的检查点,并开始重新训练。 但是,这也造成模型有冗余的参数,在计算模型所包含的参数数量时,可能会不准确。 更多深层次原因和解决方法可参考 [Trainer](./NasReference.md)
也可参考 [DARTS](./DARTS.md) 的重新训练代码。 也可参考 [DARTS](./DARTS.md) 的重新训练代码。
# NAS 参考
```eval_rst
.. contents::
```
## Mutable
```eval_rst
.. autoclass:: nni.nas.pytorch.mutables.Mutable
:members:
.. autoclass:: nni.nas.pytorch.mutables.LayerChoice
:members:
.. autoclass:: nni.nas.pytorch.mutables.InputChoice
:members:
.. autoclass:: nni.nas.pytorch.mutables.MutableScope
:members:
```
### 工具
```eval_rst
.. autofunction:: nni.nas.pytorch.utils.global_mutable_counting
```
## Mutator
```eval_rst
.. autoclass:: nni.nas.pytorch.base_mutator.BaseMutator
:members:
.. autoclass:: nni.nas.pytorch.mutator.Mutator
:members:
```
### Random Mutator
```eval_rst
.. autoclass:: nni.nas.pytorch.random.RandomMutator
:members:
```
### 工具
```eval_rst
.. autoclass:: nni.nas.pytorch.utils.StructuredMutableTreeNode
:members:
```
## Trainer
### Trainer
```eval_rst
.. autoclass:: nni.nas.pytorch.base_trainer.BaseTrainer
:members:
.. autoclass:: nni.nas.pytorch.trainer.Trainer
:members:
```
### 重新训练
```eval_rst
.. autofunction:: nni.nas.pytorch.fixed.apply_fixed_architecture
.. autoclass:: nni.nas.pytorch.fixed.FixedArchitecture
:members:
```
### 分布式 NAS
```eval_rst
.. autofunction:: nni.nas.pytorch.classic_nas.get_and_apply_next_architecture
.. autoclass:: nni.nas.pytorch.classic_nas.mutator.ClassicMutator
:members:
```
### 回调
```eval_rst
.. autoclass:: nni.nas.pytorch.callbacks.Callback
:members:
.. autoclass:: nni.nas.pytorch.callbacks.LRSchedulerCallback
:members:
.. autoclass:: nni.nas.pytorch.callbacks.ArchitectureCheckpoint
:members:
.. autoclass:: nni.nas.pytorch.callbacks.ModelCheckpoint
:members:
```
### 工具
```eval_rst
.. autoclass:: nni.nas.pytorch.utils.AverageMeterGroup
:members:
.. autoclass:: nni.nas.pytorch.utils.AverageMeter
:members:
.. autofunction:: nni.nas.pytorch.utils.to_device
```
# 神经网络结构搜索在 NNI 上的应用 # 神经网络结构搜索在 NNI 上的应用
自动化的神经网络架构(NAS)搜索在寻找更好的模型方面发挥着越来越重要的作用。 最近的研究工作证明了自动化 NAS 的可行性,并发现了一些超越手动设计和调整的模型。 代表算法有 [NASNet](https://arxiv.org/abs/1707.07012)[ENAS](https://arxiv.org/abs/1802.03268)[DARTS](https://arxiv.org/abs/1806.09055)[Network Morphism](https://arxiv.org/abs/1806.10282),以及 [Evolution](https://arxiv.org/abs/1703.01041) 等。 新的算法还在不断涌现。 自动化的神经网络架构(NAS)搜索在寻找更好的模型方面发挥着越来越重要的作用。 最近的研究工作证明了自动化 NAS 的可行性,并发现了一些超越手动设计和调整的模型。 代表算法有 [NASNet](https://arxiv.org/abs/1707.07012)[ENAS](https://arxiv.org/abs/1802.03268)[DARTS](https://arxiv.org/abs/1806.09055)[Network Morphism](https://arxiv.org/abs/1806.10282),以及 [Evolution](https://arxiv.org/abs/1703.01041) 等。 此外,新的创新不断涌现。
但是,要实现NAS算法需要花费大量的精力,并且很难在新算法中重用现有算法的代码。 为了促进 NAS 创新(例如,设计、实现新的 NAS 模型,并列比较不同的 NAS 模型),易于使用且灵活的编程接口非常重要。 但是,要实现NAS算法需要花费大量的精力,并且很难在新算法中重用现有算法的代码。 为了促进 NAS 创新(例如,设计、实现新的 NAS 模型,并列比较不同的 NAS 模型),易于使用且灵活的编程接口非常重要。
以此为动力,NNI 的目标是提供统一的体系结构,以加速NAS上的创新,并将最新的算法更快地应用于现实世界中的问题上。 以此为动力,NNI 的目标是提供统一的体系结构,以加速NAS上的创新,并将最新的算法更快地应用于现实世界中的问题上。
通过统一的接口,有两种方法来使用神经网络架构搜索。 [一种](#supported-one-shot-nas-algorithms)称为 one-shot NAS,基于搜索空间构建了一个超级网络,并使用 one-shot 训练来生成性能良好的子模型。 [第二种](#支持的分布式-nas-算法)是传统的搜索方法,搜索空间中每个子模型作为独立的 Trial 运行将性能结果发给 Tuner,由 Tuner 来生成新的子模型。 通过统一的接口,有两种方法来使用神经网络架构搜索。 [一种](#supported-one-shot-nas-algorithms)称为 one-shot NAS,基于搜索空间构建了一个超级网络,并使用 one-shot 训练来生成性能良好的子模型。 [第二种](#支持的分布式-nas-算法)是传统的搜索方法,搜索空间中每个子模型作为独立的 Trial 运行将性能结果发给 Tuner,由 Tuner 来生成新的子模型。
## 支持的 One-shot NAS 算法 ## 支持的 One-shot NAS 算法
NNI 现在支持以下 NAS 算法,并且正在添加更多算法。 用户可以重现算法或在自己的数据集上使用它。 鼓励用户使用 [NNI API](#use-nni-api) 实现其它算法,以使更多人受益。 NNI 目前支持下面列出的 NAS 算法,并且正在添加更多算法。 用户可以重现算法或在自己的数据集上使用它。 鼓励用户使用 [NNI API](#use-nni-api) 实现其它算法,以使更多人受益。
| 名称 | 算法简介 | | 名称 | 算法简介 |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
...@@ -33,8 +33,8 @@ One-shot 算法**不需要 nnictl,可单独运行**。 只实现了 PyTorch ...@@ -33,8 +33,8 @@ One-shot 算法**不需要 nnictl,可单独运行**。 只实现了 PyTorch
## 支持的分布式 NAS 算法 ## 支持的分布式 NAS 算法
| 名称 | 算法简介 | | 名称 | 算法简介 |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [SPOS](SPOS.md) | 论文 [Single Path One-Shot Neural Architecture Search with Uniform Sampling](https://arxiv.org/abs/1904.00420) 构造了一个采用统一的路径采样方法来训练简化的超网络,并使用进化算法来提高搜索神经网络结构的效率。 | | [SPOS 的第二阶段](SPOS.md) | 论文 [Single Path One-Shot Neural Architecture Search with Uniform Sampling](https://arxiv.org/abs/1904.00420) 构造了一个采用统一的路径采样方法来训练简化的超网络,并使用进化算法来提高搜索神经网络结构的效率。 |
```eval_rst ```eval_rst
.. 注意:SPOS 是一种两阶段算法,第一阶段是 one-shot,第二阶段是分布式的,利用第一阶段的结果作为检查点。 .. 注意:SPOS 是一种两阶段算法,第一阶段是 one-shot,第二阶段是分布式的,利用第一阶段的结果作为检查点。
......
...@@ -60,4 +60,4 @@ ProxylessNasMutator 还实现了可变量的前向逻辑 (即, LayerChoice)。 ...@@ -60,4 +60,4 @@ ProxylessNasMutator 还实现了可变量的前向逻辑 (即, LayerChoice)。
## 重现结果 ## 重现结果
进行中... 为了重现结果,首先运行了搜索过程。我们发现虽然需要跑许多 Epoch,但选择的架构会在头几个 Epoch 就收敛了。 这可能是由超参或实现造成的,正在分析中。 找到架构的测试精度为 top1: 72.31, top5: 90.26。
...@@ -29,11 +29,11 @@ class Net(nn.Module): ...@@ -29,11 +29,11 @@ class Net(nn.Module):
self.fc3 = nn.Linear(84, 10) self.fc3 = nn.Linear(84, 10)
``` ```
有关 `LayerChoice``InputChoice` 的详细描述可参考[指南](NasGuide.md) 有关 `LayerChoice``InputChoice` 的详细描述可参考[ NAS 指南](NasGuide.md)
## 选择 NAS Trainer ## 选择 NAS Trainer
实例化模型后,需要通过 NAS Trainer 来训练模型。 不同的 Trainer 会使用不同的方法来从指定的神经网络模块中搜索出最好的。 NNI 提供了流行的 NAS 训练方法,如 DARTS,ENAS。 以下以 `DartsTrainer` 为例。 在 Trainer 实例化后,调用`trainer.train()` 开始搜索。 实例化模型后,需要通过 NAS Trainer 来训练模型。 不同的 Trainer 会使用不同的方法来从指定的神经网络模块中搜索出最好的。 NNI 提供了几种流行的 NAS 训练方法,如 DARTS,ENAS。 以下以 `DartsTrainer` 为例。 在 Trainer 实例化后,调用`trainer.train()` 开始搜索。
```python ```python
trainer = DartsTrainer(net, trainer = DartsTrainer(net,
...@@ -54,11 +54,11 @@ trainer.train() ...@@ -54,11 +54,11 @@ trainer.train()
## NAS 可视化 ## NAS 可视化
正在开发 NAS 的可视化,并将很快发布。 正在研究 NAS 的可视化,并将很快发布此功能
## 重新训练导出的最佳模型 ## 重新训练导出的最佳模型
重新训练找到(导出)的网络架构非常容易。 第一步,实例化上面定义的模型。 第二步,在模型上调用 `apply_fixed_architecture`。 然后,模型会为找到(导出)的模型,可通过正常的训练方法来训练此模型。 重新训练找到(导出)的网络架构非常容易。 第一步,实例化上面定义的模型。 第二步,在模型上调用 `apply_fixed_architecture`。 然后,模型会为找到(导出的)模型。 之后,可以使用传统方法来训练此模型。
```python ```python
model = Net() model = Net()
......
...@@ -92,17 +92,11 @@ python scratch.py ...@@ -92,17 +92,11 @@ python scratch.py
.. autoclass:: nni.nas.pytorch.spos.SPOSEvolution .. autoclass:: nni.nas.pytorch.spos.SPOSEvolution
:members: :members:
.. automethod:: __init__
.. autoclass:: nni.nas.pytorch.spos.SPOSSupernetTrainer .. autoclass:: nni.nas.pytorch.spos.SPOSSupernetTrainer
:members: :members:
.. automethod:: __init__
.. autoclass:: nni.nas.pytorch.spos.SPOSSupernetTrainingMutator .. autoclass:: nni.nas.pytorch.spos.SPOSSupernetTrainingMutator
:members: :members:
.. automethod:: __init__
``` ```
## 已知的局限 ## 已知的局限
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment