"...git@developer.sourcefind.cn:wangsen/paddle_dbnet.git" did not exist on "959bde3c6618e20fb015a7f04d7ba5f856972c01"
Unverified Commit 392460ad authored by SparkSnail's avatar SparkSnail Committed by GitHub
Browse files

Merge pull request #225 from microsoft/master

merge master
parents 1a5c0172 4ed78edd
...@@ -69,7 +69,7 @@ Python 包使用 setuptools 安装,所以安装路径依赖于 Python 配置 ...@@ -69,7 +69,7 @@ Python 包使用 setuptools 安装,所以安装路径依赖于 Python 配置
| ------------------ | ------------------------------------------ | | ------------------ | ------------------------------------------ |
| `easy-install` | 安装依赖项,生成,安装 NNI,并编辑 `~/.bashrc` | | `easy-install` | 安装依赖项,生成,安装 NNI,并编辑 `~/.bashrc` |
| `dev-easy-install` | 安装依赖项,生成,将 NNI 作为符号链接来安装,并编辑 `~/.bashrc` | | `dev-easy-install` | 安装依赖项,生成,将 NNI 作为符号链接来安装,并编辑 `~/.bashrc` |
| `install` | 安装 Python 包,Node.js 模块,NNI 脚本和例 | | `install` | 安装 Python 包,Node.js 模块,NNI 脚本和例 |
| `dev-install` | 将 Python 和 Node.js 模块作为符号链接安装,然后安装 scripts | | `dev-install` | 将 Python 和 Node.js 模块作为符号链接安装,然后安装 scripts |
| `pip-install` | 安装依赖项,生成,安装 NNI,但不安装 Python 包 | | `pip-install` | 安装依赖项,生成,安装 NNI,但不安装 Python 包 |
......
...@@ -19,7 +19,7 @@ NNI 管理自动机器学习 (AutoML) 的 Experiment,**调度运行**由调优 ...@@ -19,7 +19,7 @@ NNI 管理自动机器学习 (AutoML) 的 Experiment,**调度运行**由调优
* 想要更容易**实现或试验新的自动机器学习算法**的研究员或数据科学家,包括:超参调优算法,神经网络搜索算法以及模型压缩算法。 * 想要更容易**实现或试验新的自动机器学习算法**的研究员或数据科学家,包括:超参调优算法,神经网络搜索算法以及模型压缩算法。
* 在机器学习平台中**支持自动机器学习** * 在机器学习平台中**支持自动机器学习**
### **NNI v1.2 已发布! &nbsp;[<img width="48" src="docs/img/release_icon.png" />](#nni-released-reminder)** ### **NNI v1.3 已发布! &nbsp;[<img width="48" src="docs/img/release_icon.png" />](#nni-released-reminder)**
## **NNI 功能一览** ## **NNI 功能一览**
...@@ -224,7 +224,7 @@ Linux 和 MacOS ...@@ -224,7 +224,7 @@ Linux 和 MacOS
*`python >= 3.5` 的环境中运行命令: `git``wget`,确保安装了这两个组件。 *`python >= 3.5` 的环境中运行命令: `git``wget`,确保安装了这两个组件。
```bash ```bash
git clone -b v1.2 https://github.com/Microsoft/nni.git git clone -b v1.3 https://github.com/Microsoft/nni.git
cd nni cd nni
source install.sh source install.sh
``` ```
...@@ -234,7 +234,7 @@ Windows ...@@ -234,7 +234,7 @@ Windows
*`python >=3.5` 的环境中运行命令: `git``PowerShell`,确保安装了这两个组件。 *`python >=3.5` 的环境中运行命令: `git``PowerShell`,确保安装了这两个组件。
```bash ```bash
git clone -b v1.2 https://github.com/Microsoft/nni.git git clone -b v1.3 https://github.com/Microsoft/nni.git
cd nni cd nni
powershell -ExecutionPolicy Bypass -file install.ps1 powershell -ExecutionPolicy Bypass -file install.ps1
``` ```
...@@ -250,7 +250,7 @@ Windows 上参考 [Windows 上使用 NNI](docs/zh_CN/Tutorial/NniOnWindows.md) ...@@ -250,7 +250,7 @@ Windows 上参考 [Windows 上使用 NNI](docs/zh_CN/Tutorial/NniOnWindows.md)
* 通过克隆源代码下载示例。 * 通过克隆源代码下载示例。
```bash ```bash
git clone -b v1.2 https://github.com/Microsoft/nni.git git clone -b v1.3 https://github.com/Microsoft/nni.git
``` ```
Linux 和 MacOS Linux 和 MacOS
...@@ -326,7 +326,7 @@ You can use these commands to get more information about the experiment ...@@ -326,7 +326,7 @@ You can use these commands to get more information about the experiment
* [如何调试](docs/zh_CN/Tutorial/HowToDebug.md) * [如何调试](docs/zh_CN/Tutorial/HowToDebug.md)
* [自定义 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/en_US/NAS/NasInterface.md#implement-a-new-nas-trainer-on-nni) * [在 NNI 上实现新的 NAS Trainer](https://github.com/microsoft/nni/blob/master/docs/zh_CN/NAS/NasInterface.md#implement-a-new-nas-trainer-on-nni)
* [自定义 Advisor](docs/zh_CN/Tuner/CustomizeAdvisor.md) * [自定义 Advisor](docs/zh_CN/Tuner/CustomizeAdvisor.md)
## **其它代码库和参考** ## **其它代码库和参考**
...@@ -349,6 +349,7 @@ You can use these commands to get more information about the experiment ...@@ -349,6 +349,7 @@ You can use these commands to get more information about the experiment
* [使用 NNI 为 SPTAG 自动调参](docs/zh_CN/CommunitySharings/SptagAutoTune.md) * [使用 NNI 为 SPTAG 自动调参](docs/zh_CN/CommunitySharings/SptagAutoTune.md)
* [使用 NNI 为 scikit-learn 查找超参](https://towardsdatascience.com/find-thy-hyper-parameters-for-scikit-learn-pipelines-using-microsoft-nni-f1015b1224c1) * [使用 NNI 为 scikit-learn 查找超参](https://towardsdatascience.com/find-thy-hyper-parameters-for-scikit-learn-pipelines-using-microsoft-nni-f1015b1224c1)
* **博客** - [AutoML 工具(Advisor,NNI 与 Google Vizier)的对比](http://gaocegege.com/Blog/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/katib-new#%E6%80%BB%E7%BB%93%E4%B8%8E%E5%88%86%E6%9E%90) 作者:[@gaocegege](https://github.com/gaocegege) - kubeflow/katib 的设计与实现的总结与分析章节 * **博客** - [AutoML 工具(Advisor,NNI 与 Google Vizier)的对比](http://gaocegege.com/Blog/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/katib-new#%E6%80%BB%E7%BB%93%E4%B8%8E%E5%88%86%E6%9E%90) 作者:[@gaocegege](https://github.com/gaocegege) - kubeflow/katib 的设计与实现的总结与分析章节
* **Blog (中文)** - [NNI 2019 新功能汇总](https://mp.weixin.qq.com/s/7_KRT-rRojQbNuJzkjFMuA) by @squirrelsc
## **反馈** ## **反馈**
......
...@@ -20,7 +20,7 @@ nnictl create --config ./config.yml ...@@ -20,7 +20,7 @@ nnictl create --config ./config.yml
This example uses the dataset of digits, which is made up of 1797 8x8 images, and each image is a hand-written digit, the goal is to classify these images into 10 classes. This example uses the dataset of digits, which is made up of 1797 8x8 images, and each image is a hand-written digit, the goal is to classify these images into 10 classes.
In this example, we use SVC as the model, and choose some parameters of this model, including `"C", "keral", "degree", "gamma" and "coef0"`. For more information of these parameters, please [refer](https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html). In this example, we use SVC as the model, and choose some parameters of this model, including `"C", "kernel", "degree", "gamma" and "coef0"`. For more information of these parameters, please [refer](https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html).
### 2.2 regression ### 2.2 regression
...@@ -64,7 +64,7 @@ It is easy to use NNI in your scikit-learn code, there are only a few steps. ...@@ -64,7 +64,7 @@ It is easy to use NNI in your scikit-learn code, there are only a few steps.
```json ```json
{ {
"C": {"_type":"uniform","_value":[0.1, 1]}, "C": {"_type":"uniform","_value":[0.1, 1]},
"keral": {"_type":"choice","_value":["linear", "rbf", "poly", "sigmoid"]}, "kernel": {"_type":"choice","_value":["linear", "rbf", "poly", "sigmoid"]},
"degree": {"_type":"choice","_value":[1, 2, 3, 4]}, "degree": {"_type":"choice","_value":[1, 2, 3, 4]},
"gamma": {"_type":"uniform","_value":[0.01, 0.1]}, "gamma": {"_type":"uniform","_value":[0.01, 0.1]},
"coef0 ": {"_type":"uniform","_value":[0.01, 0.1]} "coef0 ": {"_type":"uniform","_value":[0.01, 0.1]}
...@@ -76,7 +76,7 @@ It is easy to use NNI in your scikit-learn code, there are only a few steps. ...@@ -76,7 +76,7 @@ It is easy to use NNI in your scikit-learn code, there are only a few steps.
```python ```python
params = { params = {
'C': 1.0, 'C': 1.0,
'keral': 'linear', 'kernel': 'linear',
'degree': 3, 'degree': 3,
'gamma': 0.01, 'gamma': 0.01,
'coef0': 0.01 'coef0': 0.01
......
# 高级神经网络架构搜索教程
目前,许多 NAS(Neural Architecture Search,神经网络架构搜索)算法都在 Trial 上使用了 **权重共享(weight sharing)** 的方法来加速训练过程。 例如,[ENAS](https://arxiv.org/abs/1802.03268) 与以前的 [NASNet](https://arxiv.org/abs/1707.07012) 算法相比,通过'*子模型间的参数共享(parameter sharing between child models)*'提高了 1000 倍的效率。 而例如 [DARTS](https://arxiv.org/abs/1806.09055), [Network Morphism](https://arxiv.org/abs/1806.10282), 和 [Evolution](https://arxiv.org/abs/1703.01041) 等算法也利用或者隐式的利用了权重共享。
本教程介绍了如何使用权重共享。
## 权重共享
推荐通过 NFS (Network File System)进行权重共享,它是轻量、相对高效的多机共享文件方案。 欢迎社区来共享更多高效的技术。
### 通过 NFS 文件使用权重共享
使用 NFS 配置(见下文),Trial 代码可以通过读写文件来共享模型权重。 建议使用 Tuner 的存储路径:
```yaml
tuner:
codeDir: path/to/customer_tuner
classFileName: customer_tuner.py
className: CustomerTuner
classArgs:
...
save_dir_root: /nfs/storage/path/
```
并让 Tuner 来决定在什么路径读写权重文件,通过 `nni.get_next_parameters()` 来获取路径:
<img src="https://user-images.githubusercontent.com/23273522/51817667-93ebf080-2306-11e9-8395-b18b322062bc.png" alt="drawing" width="700" />
例如,在 Tensorflow 中:
```python
# 保存 models
saver = tf.train.Saver()
saver.save(sess, os.path.join(params['save_path'], 'model.ckpt'))
# 读取 models
tf.init_from_checkpoint(params['restore_path'])
```
超参中的 `'save_path'``'restore_path'` 可以通过 Tuner 来管理。
### NFS 配置
NFS 使用了客户端/服务器架构。通过一个 NFS 服务器来提供物理存储,远程计算机上的 Trial 使用 NFS 客户端来读写文件,操作上和本地文件相同。
#### NFS 服务器
如果有足够的存储空间,并能够让 NNI 的 Trial 通过**远程机器**来连接,NFS 服务可以安装在任何计算机上。 通常,可以选择一台远程服务器作为 NFS 服务。
在 Ubuntu 上,可通过 `apt-get` 安装 NFS 服务:
```bash
sudo apt-get install nfs-kernel-server
```
假设 `/tmp/nni/shared` 是物理存储位置,然后运行:
```bash
mkdir -p /tmp/nni/shared
sudo echo "/tmp/nni/shared *(rw,sync,no_subtree_check,no_root_squash)" >> /etc/exports
sudo service nfs-kernel-server restart
```
可以通过命令 `sudo showmount -e localhost` 来检查上述目录是否通过 NFS 成功导出了
#### NFS 客户端
为了通过 NFS 访问远程共享文件,需要安装 NFS 客户端。 例如,在 Ubuntu 上运行:
```bash
sudo apt-get install nfs-common
```
然后创建并装载上共享目录:
```bash
mkdir -p /mnt/nfs/nni/
sudo mount -t nfs 10.10.10.10:/tmp/nni/shared /mnt/nfs/nni
```
实际使用时,IP `10.10.10.10` 需要替换为 NFS 服务器的真实地址。
## Trial 依赖控制的异步 Dispatcher 模式
多机间启用权重的 Trial,一般是通过**先写后读**的方式来保持一致性。 子节点在父节点的 Trial 完成训练前,不应该读取父节点模型。 要解决这个问题,要通过 `multiThread: true` 来启用**异步调度模式**。在 `config.yml` 中,每次收到 `NEW_TRIAL` 请求,分派一个新的 Trial 时,Tuner 线程可以决定是否阻塞当前线程。 例如:
```python
def generate_parameters(self, parameter_id):
self.thread_lock.acquire()
indiv = # 新 Trial 的配置
self.events[parameter_id] = threading.Event()
self.thread_lock.release()
if indiv.parent_id is not None:
self.events[indiv.parent_id].wait()
def receive_trial_result(self, parameter_id, parameters, reward):
self.thread_lock.acquire()
# 处理 Trial 结果的配置
self.thread_lock.release()
self.events[parameter_id].set()
```
## 样例
详细内容参考:[简单的参数共享样例](https://github.com/Microsoft/nni/tree/master/test/async_sharing_test)。 基于已有的 [ga_squad](https://github.com/Microsoft/nni/tree/master/examples/trials/ga_squad) 样例,还提供了新的 [样例](https://github.com/Microsoft/nni/tree/master/examples/trials/weight_sharing/ga_squad)
\ No newline at end of file
# 神经网络架构搜索的 NNI 编程接口(NAS)
** 这是**实验性的功能**。 目前,仅实现了通用的 NAS 编程接口。 在随后的版本中会支持权重共享。*
自动化的神经网络架构(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 模型),易于使用且灵活的编程接口非常重要。
<a name="ProgInterface"></a>
## 编程接口
在两种场景下需要用于设计和搜索模型的新的编程接口。 1) 在设计神经网络时,层、子模型或连接有多个可能,并且不确定哪一个或哪种组合表现最好。 如果有一种简单的方法来表达想要尝试的候选层、子模型,将会很有价值。 2) 研究自动化 NAS 时,需要统一的方式来表达神经网络架构的搜索空间, 并在不改变 Trial 代码的情况下来使用不同的搜索算法。
本文基于 [NNI Annotation](../Tutorial/AnnotationSpec.md) 实现了简单灵活的编程接口 。 通过以下示例来详细说明。
### 示例:为层选择运算符
在设计此模型时,第四层的运算符有多个可能的选择,会让模型有更好的表现。 如图所示,在模型代码中可以对第四层使用 Annotation。 此 Annotation 中,共有五个字段:
![](../../img/example_layerchoice.png)
* **layer_choice**:它是函数调用的 list,每个函数都要在代码或导入的库中实现。 函数的输入参数格式为:`def XXX (input, arg2, arg3, ...)`,其中输入是包含了两个元素的 list。 其中一个是 `fixed_inputs` 的 list,另一个是 `optional_inputs` 中选择输入的 list。 `conv``pool` 是函数示例。 对于 list 中的函数调用,无需写出第一个参数(即 input)。 注意,只会从这些函数调用中选择一个来执行。
* **fixed_inputs** :它是变量的 list,可以是前一层输出的张量。 也可以是此层之前的另一个 `nni.mutable_layer``layer_output`,或此层之前的其它 Python 变量。 list 中的所有变量将被输入 `layer_choice` 中选择的函数(作为输入 list 的第一个元素)。
* **optional_inputs** :它是变量的 list,可以是前一层的输出张量。 也可以是此层之前的另一个 `nni.mutable_layer``layer_output`,或此层之前的其它 Python 变量。 只有 `optional_input_size` 变量被输入 `layer_choice` 到所选的函数 (作为输入 list 的第二个元素)。
* **optional_input_size** :它表示从 `input_candidates` 中选择多少个输入。 它可以是一个数字,也可以是一个范围。 范围 [1, 3] 表示选择 1、2 或 3 个输入。
* **layer_output** :表示输出的名称。本例中,表示 `layer_choice` 选择的函数的返回值。 这是一个变量名,可以在随后的 Python 代码或 `nni.mutable_layer` 中使用。
此示例有两种写 Annotation 的方法。 对于上面的示例,输入函数的形式是 `[[], [out3]]` 。 对于下面的示例,输入的形式是 `[[out3], []]`
**调试**`nnictl trial codegen` 命令可帮助调试 NAS 编程接口。 如果 Experiment `YYY` 中的 Trial 的 `XXX` 出错了,可以运行 `nnictl trial codegen YYY --trial_id XXX` 在当前目录下生成这个 Trial 的可执行代码。 通过运行此代码,可以不需要 NNI 就能调试 Trial 失败的原因。 此命令会编译 Trial 代码,并用实际选择的层次和输入来替换 NNI 的 NAS 代码。
### 示例:为层选择输入的连接
设计层的连接对于制作高性能模型至关重要。 通过此接口,可选择一个层可以采用哪些连接来作为输入。 可以从一组连接中选择几个。 下面的示例从三个候选输入中为 `concat` 这个函数选择两个输入 。 `concat` 还会使用 `fixed_inputs` 获取其上一层的输出 。
![](../../img/example_connectchoice.png)
### 示例:同时选择运算符和连接
此示例从三个运算符中选择一个,并为其选择两个连接作为输入。 由于输入会有多个变量,,在函数的开头需要调用 `concat`
![](../../img/example_combined.png)
### 示例:[ENAS](https://arxiv.org/abs/1802.03268) 宏搜索空间
为了证明编程接口带来的便利,使用该接口来实现 “ENAS + 宏搜索空间” 的 Trial 代码。 左图是 ENAS 论文中的宏搜索空间。
![](../../img/example_enas.png)
## 统一的 NAS 搜索空间说明
通过上面的 Annotation 更新 Trial 代码后,即在代码中隐式指定了神经网络架构的搜索空间。 基于该代码,NNI 将自动生成一个搜索空间文件,可作为调优算法的输入。 搜索空间文件遵循以下 JSON 格式。
```javascript
{
"mutable_1": {
"_type": "mutable_layer",
"_value": {
"layer_1": {
"layer_choice": ["conv(ch=128)", "pool", "identity"],
"optional_inputs": ["out1", "out2", "out3"],
"optional_input_size": 2
},
"layer_2": {
...
}
}
}
}
```
相应生成的神经网络结构(由调优算法生成)如下:
```javascript
{
"mutable_1": {
"layer_1": {
"chosen_layer": "pool",
"chosen_inputs": ["out1", "out3"]
},
"layer_2": {
...
}
}
}
```
通过对搜索空间格式和体系结构选择 (choice) 表达式的说明,可以自由地在 NNI 上实现神经体系结构搜索的各种或通用的调优算法。 接下来的工作会提供一个通用的 NAS 算法。
## 支持 One-Shot NAS
One-Shot NAS 是流行的,能在有限的时间和资源预算内找到较好的神经网络结构的方法。 本质上,它会基于搜索空间来构建完整的图,并使用梯度下降最终找到最佳子图。 它有不同的训练方法,如:[training subgraphs (per mini-batch)](https://arxiv.org/abs/1802.03268)[training full graph through dropout](http://proceedings.mlr.press/v80/bender18a/bender18a.pdf),以及 [training with architecture weights (regularization)](https://arxiv.org/abs/1806.09055)
如上所示,NNI 支持通用的 NAS。 从用户角度来看,One-Shot NAS 和 NAS 具有相同的搜索空间规范,因此,它们可以使用相同的编程接口,只是在训练模式上有所不同。 NNI 提供了四种训练模式:
***classic_mode***: [上文](#ProgInterface)对此模式有相应的描述,每个子图是一个 Trial 任务。 要使用此模式,需要启用 NNI Annotation,并在 Experiment 配置文件中为 NAS 指定一个 Tuner。 [这里](https://github.com/microsoft/nni/tree/master/examples/trials/mnist-nas)是如何实现 Trial 和配置文件的例子。 [这里](https://github.com/microsoft/nni/tree/master/examples/tuners/random_nas_tuner)是一个简单的 NAS Tuner。
***enas_mode***: 参考 [ENAS 论文](https://arxiv.org/abs/1802.03268)的训练方法。 它基于神经网络架构搜索空间来构建全图,每个 mini-batch 只激活一个子图。 [详细说明](#ENASMode)。 (当前仅支持 TensorFlow)。
要使用 enas_mode,需要在配置的 `trial` 部分增加如下字段。
```diff
trial:
command: 运行 Trial 的命令
codeDir: Trial 代码的目录
gpuNum: 每个 Trial 所需要的 GPU 数量
+ #choice: classic_mode, enas_mode, oneshot_mode
+ nasMode: enas_mode
```
与 classic_mode 类似,在 enas_mode 中,需要为 NAS 指定 Tuner,其会从 Tuner(或者论文中的术语:Controller)中接收子图。 由于 Trial 任务要从 Tuner 中接收多个子图,每个子图用于一个 mini-batch,需要在 Trial 代码中增加两行来接收下一个子图(`nni.training_update`),并返回当前子图的结果。 示例如下:
```python
for _ in range(num):
# 接收并启用一个新的子图
"""@nni.training_update(tf=tf, session=self.session)"""
loss, _ = self.session.run([loss_op, train_op])
# 返回这个 mini-batch 的损失值
"""@nni.report_final_result(loss)"""
```
在这里,`nni.training_update`用来在全图上进行更新。 在 enas_mode 中,更新表示接收一个子图,并在下一个 mini-batch 中启用它。 在 darts_mode 中,更新表示训练架构权重(参考 darts_mode 中的详细说明)。 在 enas_mode 中,需要将导入的 TensorFlow 包传入 `tf`,并将会话传入 `session`
***oneshot_mode***: 遵循[论文](http://proceedings.mlr.press/v80/bender18a/bender18a.pdf)中的训练方法。 与 enas_mode 通过训练大量子图来训练全图有所不同,oneshot_mode 中构建了全图,并将 dropout 添加到候选的输入以及候选的输出操作中。 然后像其它深度学习模型一样进行训练。 [详细说明](#OneshotMode)。 (当前仅支持 TensorFlow)。
要使用 oneshot_mode,需要在配置的 `trial` 部分增加如下字段。 在此模式中,不需要使用 Tuner,只需要在配置文件中添加任意一个Tuner。 此外,也不需要增加 `nni.training_update`,因为在训练过程中不需要更新。
```diff
trial:
command: 运行 Trial 的命令
codeDir: Trial 代码的目录
gpuNum: 每个 Trial 所需要的 GPU 数量
+ #choice: classic_mode, enas_mode, oneshot_mode
+ nasMode: oneshot_mode
```
***darts_mode***: 参考 [论文](https://arxiv.org/abs/1806.09055)中的训练方法。 与 oneshot_mode 类似。 有两个不同之处,首先 darts_mode 只将架构权重添加到候选操作的输出中,另外是交错的来训练模型权重和架构权重。 [详细说明](#DartsMode)
要使用 darts_mode,需要在配置的 `trial` 部分增加如下字段。 在此模式中,不需要使用 Tuner,只需要在配置文件中添加任意一个Tuner。
```diff
trial:
command: 运行 Trial 的命令
codeDir: Trial 代码的目录
gpuNum: 每个 Trial 所需要的 GPU 数量
+ #choice: classic_mode, enas_mode, oneshot_mode
+ nasMode: darts_mode
```
在使用 darts_mode 时,需要按照如下所示调用 `nni.training_update`,来更新架构权重。 更新架构权重时,和训练数据一样也需要`损失值`(即, `feed_dict`)。
```python
for _ in range(num):
# 训练架构权重
"""@nni.training_update(tf=tf, session=self.session, loss=loss, feed_dict=feed_dict)"""
loss, _ = self.session.run([loss_op, train_op])
```
**注意**:对于 enas_mode、oneshot_mode、以及 darts_mode,NNI 仅能在训练阶段时有用。 NNI 不处理它们的推理阶段。 对于 enas_mode,推理阶段需要通过 Controller 来生成新的子图。 对于 oneshot_mode,推理阶段会随机采样生成新的子图,并选择其中好的子图。 对于 darts_mode,推理过程会根据架构权重来修剪掉一些候选的操作。
<a name="ENASMode"></a>
### enas_mode
在 enas_mode 中,编译后的 Trial 代码会构建完整的图形(而不是子图),会接收所选择的架构,并在完整的图形上对此体系结构进行小型的批处理训练,然后再请求另一个架构。 通过 [NNI 多阶段 Experiment](./MultiPhase.md) 来支持。
具体来说,使用 TensorFlow 的 Trial,通过 TensorFlow 变量来作为信号,并使用 TensorFlow 的条件函数来控制搜索空间(全图)来提高灵活性。这意味着根据这些信号,可以变为不同的多个子图。 [这里](https://github.com/microsoft/nni/tree/master/examples/trials/mnist-nas/enas_mode)是 enas_mode 的示例。
<a name="OneshotMode"></a>
### oneshot_mode
下图展示了 Dropout 通过 `nni.mutable_layers` 添加在全图的位置,输入的是 1-k 个候选输入,4 个操作是候选的操作。
![](../../img/oneshot_mode.png)
[论文](http://proceedings.mlr.press/v80/bender18a/bender18a.pdf)中的建议,应该为每层的输入实现 Dropout 方法。 当 0 < r < 1 是模型超参的取值范围(默认值为 0.01),k 是某层可选超参的数量,Dropout 比率设为 r^(1/k)。 fan-in 越高,每个输入被丢弃的可能性越大。 但某层丢弃所有可选输入的概率是常数,与 fan-in 无关。 假设 r = 0.05。 如果某层有 k = 2 个可选的输入,每个输入都会以独立的 0.051/2 ≈ 0.22 的概率被丢弃,也就是说有 0.78 的概率被保留。 如果某层有 k = 7 个可选的输入,每个输入都会以独立的 0.051/7 ≈ 0.65 的概率被丢弃,也就是说有 0.35 的概率被保留。 在这两种情况下,丢弃所有可选输入的概率是 5%。 候选操作的输出会通过同样的方法被丢弃。 [这里](https://github.com/microsoft/nni/tree/master/examples/trials/mnist-nas/oneshot_mode)是 oneshot_mode 的示例。
<a name="DartsMode"></a>
### darts_mode
下图显示了通过 `nni.mutable_layers` 在全图中为某层加入架构权重,每个候选操作的输出会乘以架构权重。
![](../../img/darts_mode.png)
`nni.training_update` 中,TensorFlow 的 MomentumOptimizer 通过传递的 `loss``feed_dict` 来训练架构权重。 [这里](https://github.com/microsoft/nni/tree/master/examples/trials/mnist-nas/darts_mode)是 darts_mode 的示例。
### [**待实现**] One-Shot NAS 的多 Trial 任务。
One-Shot NAS 通常只有一个带有完整图的 Trial 任务。 但是,同时运行多个 Trial 任务会很有用。 例如,在 enas_mode 中,多个 Trial 任务可以共享全图的权重来加速模型训练或收敛。 一些 One-Shot 不够稳定,运行多个 Trial 任务可以提升找到更好模型的概率。
NNI 原生支持运行多个 Trial 任务。 下图显示了 NNI 上如何运行多个 Trial 任务。
![](../../img/one-shot_training.png)
=============================================================
## NNI 上 NAS 的系统设计
### Experiment 执行的基本流程
NNI 的 Annotation 编译器会将 Trial 代码转换为可以接收架构选择并构建相应模型(如图)的代码。 NAS 的搜索空间可以看作是一个完整的图(在这里,完整的图意味着允许所有提供的操作符和连接来构建图),调优算法所选择的是其子图。 默认情况下,编译时 Trial 代码仅构建并执行子图。
![](../../img/nas_on_nni.png)
上图显示了 Trial 代码如何在 NNI 上运行。 `nnictl` 处理 Trial 代码,并生成搜索空间文件和编译后的 Trial 代码。 前者会输入 Tuner,后者会在 Trial 代码运行时使用。
[使用 NAS 的简单示例](https://github.com/microsoft/nni/tree/master/examples/trials/mnist-nas)
### [**待实现**] 权重共享
在所选择的架构(即 Trial)之间共享权重可以加速模型搜索。 例如,适当地继承已完成 Trial 的权重可加速新 Trial 的收敛。 One-shot NAS(例如,ENAS,Darts)更为激进,不同架构(即子图)的训练会在完整图中共享相同的权重。
![](../../img/nas_weight_share.png)
权重分配(转移)在加速 NAS 中有关键作用,而找到有效的权重共享方式仍是热门的研究课题。 NNI 提供了一个键值存储,用于存储和加载权重。 Tuner 和 Trial 使用 KV 客户端库来访问存储。
NNI 上的权重共享示例。
## 通用的 NAS 调优算法
与超参数调优一样,NAS 也需要相对通用的算法。 通用编程接口使其更容易。 这是 NAS 上[基于 PPO 算法的 RL Tuner](https://github.com/microsoft/nni/tree/master/src/sdk/pynni/nni/ppo_tuner)。 期待社区努力设计和实施更好的 NAS 调优算法。
## [**待实现**] 导出最佳神经网络架构和代码
Experiment 完成后,可通过 `nnictl experiment export --code` 来导出用最好的神经网络结构和 Trial 代码。
## 结论和未来的工作
如本文所示,不同的 NAS 算法和执行模式,可通过相同的编程接口来支持。
在这一领域有许多系统和机器学习方向的有趣的研究主题。
\ No newline at end of file
...@@ -13,9 +13,9 @@ NNI 提供了先进的调优算法,使用上也很简单。 下面是内置 As ...@@ -13,9 +13,9 @@ NNI 提供了先进的调优算法,使用上也很简单。 下面是内置 As
## 用法 ## 用法
要使用 NNI 内置的 Assessor,需要在 `config.yml` 文件中添加 **builtinAssessorName****classArgs**。 这一节会介绍推荐的场景、参数等详细用法以及例。 要使用 NNI 内置的 Assessor,需要在 `config.yml` 文件中添加 **builtinAssessorName****classArgs**。 这一节会介绍推荐的场景、参数等详细用法以及例。
注意:参考例中的格式来创建新的 `config.yml` 文件。 注意:参考例中的格式来创建新的 `config.yml` 文件。
<a name="MedianStop"></a> <a name="MedianStop"></a>
...@@ -32,7 +32,7 @@ NNI 提供了先进的调优算法,使用上也很简单。 下面是内置 As ...@@ -32,7 +32,7 @@ NNI 提供了先进的调优算法,使用上也很简单。 下面是内置 As
* **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 应该被终止。
**使用例:** **使用例:**
```yaml ```yaml
# config.yml # config.yml
...@@ -63,7 +63,7 @@ assessor: ...@@ -63,7 +63,7 @@ assessor:
* **threshold** (*float, 可选, 默认值为 0.95*) - 用来确定提前终止较差结果的阈值。 例如,如果 threshold = 0.95, optimize_mode = maximize,最好的历史结果是 0.9,那么会在 Trial 的预测值低于 0.95 * 0.9 = 0.855 时停止。 * **threshold** (*float, 可选, 默认值为 0.95*) - 用来确定提前终止较差结果的阈值。 例如,如果 threshold = 0.95, optimize_mode = maximize,最好的历史结果是 0.9,那么会在 Trial 的预测值低于 0.95 * 0.9 = 0.855 时停止。
* **gap** (*int, 可选, 默认值为 1*) - Assessor 两次评估之间的间隔次数。 例如:如果 gap = 2, start_step = 6,就会评估第 6, 8, 10, 12... 个中间结果。 * **gap** (*int, 可选, 默认值为 1*) - Assessor 两次评估之间的间隔次数。 例如:如果 gap = 2, start_step = 6,就会评估第 6, 8, 10, 12... 个中间结果。
**使用例:** **使用例:**
```yaml ```yaml
# config.yml # config.yml
......
...@@ -54,7 +54,9 @@ assessor: ...@@ -54,7 +54,9 @@ assessor:
注意在 **2** 中, `trial_history` 对象与 Trial 通过 `report_intermediate_result` 函数返回给 Assessor 的对象完全一致。 注意在 **2** 中, `trial_history` 对象与 Trial 通过 `report_intermediate_result` 函数返回给 Assessor 的对象完全一致。
更多样例,可参考: Assessor 的工作目录是`<home>/nni/experiments/<experiment_id>/log` 可从环境变量 `NNI_LOG_DIRECTORY` 中获取。
更多示例,可参考:
> * [medianstop-assessor](https://github.com/Microsoft/nni/tree/master/src/sdk/pynni/nni/medianstop_assessor) > * [medianstop-assessor](https://github.com/Microsoft/nni/tree/master/src/sdk/pynni/nni/medianstop_assessor)
> * [curvefitting-assessor](https://github.com/Microsoft/nni/tree/master/src/sdk/pynni/nni/curvefitting_assessor) > * [curvefitting-assessor](https://github.com/Microsoft/nni/tree/master/src/sdk/pynni/nni/curvefitting_assessor)
\ No newline at end of file
# Compressor # 使用 NNI 进行模型压缩
随着更多层和节点大型神经网络的使用,降低其存储和计算成本变得至关重要,尤其是对于某些实时应用程序。 模型压缩可用于解决此问题。
我们很高兴的宣布,基于 NNI 的模型压缩工具发布了 Alpha 版本。该版本仍处于试验阶段,根据用户反馈会进行改进。 诚挚邀请您使用、反馈,或更多贡献。 我们很高兴的宣布,基于 NNI 的模型压缩工具发布了试用版本。该版本仍处于试验阶段,根据用户反馈会进行改进。 诚挚邀请您使用、反馈,或更多贡献。
NNI 提供了易于使用的工具包来帮助用户设计并使用压缩算法。 其使用了统一的接口来支持 TensorFlow 和 PyTorch。 只需要添加几行代码即可压缩模型。 NNI 中也内置了一些流程的模型压缩算法。 用户还可以通过 NNI 强大的自动调参功能来找到最好的压缩后的模型,详见[自动模型压缩](./AutoCompression.md)。 另外,用户还能使用 NNI 的接口,轻松定制新的压缩算法,详见[教程](#customize-new-compression-algorithms) NNI 提供了易于使用的工具包来帮助用户设计并使用压缩算法。 当前支持基于 PyTorch 的统一接口。 只需要添加几行代码即可压缩模型。 NNI 中也内置了一些流程的模型压缩算法。 用户还可以通过 NNI 强大的自动调参功能来找到最好的压缩后的模型,详见[自动模型压缩](./AutoCompression.md)。 另外,用户还能使用 NNI 的接口,轻松定制新的压缩算法,详见[教程](#customize-new-compression-algorithms)
模型压缩方面的综述可参考:[Recent Advances in Efficient Computation of Deep Convolutional Neural Networks](https://arxiv.org/pdf/1802.00939.pdf)
## 支持的算法 ## 支持的算法
...@@ -10,22 +13,31 @@ NNI 提供了几种压缩算法,包括剪枝和量化算法: ...@@ -10,22 +13,31 @@ NNI 提供了几种压缩算法,包括剪枝和量化算法:
**剪枝** **剪枝**
剪枝算法通过删除冗余权重或层通道来压缩原始网络,从而降低模型复杂性并解决过拟合问题。
| 名称 | 算法简介 | | 名称 | 算法简介 |
| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| [Level Pruner](./Pruner.md#level-pruner) | 根据权重的绝对值,来按比例修剪权重。 | | [Level Pruner](./Pruner.md#level-pruner) | 根据权重的绝对值,来按比例修剪权重。 |
| [AGP Pruner](./Pruner.md#agp-pruner) | 自动的逐步剪枝(是否剪枝的判断:基于对模型剪枝的效果)[参考论文](https://arxiv.org/abs/1710.01878) | | [AGP Pruner](./Pruner.md#agp-pruner) | 自动的逐步剪枝(是否剪枝的判断:基于对模型剪枝的效果)[参考论文](https://arxiv.org/abs/1710.01878) |
| [L1Filter Pruner](./Pruner.md#l1filter-pruner) | 剪除卷积层中最不重要的过滤器 (PRUNING FILTERS FOR EFFICIENT CONVNETS)[参考论文](https://arxiv.org/abs/1608.08710) |
| [Slim Pruner](./Pruner.md#slim-pruner) | 通过修剪 BN 层中的缩放因子来修剪卷积层中的通道 (Learning Efficient Convolutional Networks through Network Slimming)[参考论文](https://arxiv.org/abs/1708.06519) |
| [Lottery Ticket Pruner](./Pruner.md#agp-pruner) | "The Lottery Ticket Hypothesis: Finding Sparse, Trainable Neural Networks" 提出的剪枝过程。 它会反复修剪模型。 [参考论文](https://arxiv.org/abs/1803.03635) | | [Lottery Ticket Pruner](./Pruner.md#agp-pruner) | "The Lottery Ticket Hypothesis: Finding Sparse, Trainable Neural Networks" 提出的剪枝过程。 它会反复修剪模型。 [参考论文](https://arxiv.org/abs/1803.03635) |
| [FPGM Pruner](./Pruner.md#fpgm-pruner) | Filter Pruning via Geometric Median for Deep Convolutional Neural Networks Acceleration [参考论文](https://arxiv.org/pdf/1811.00250.pdf) | | [FPGM Pruner](./Pruner.md#fpgm-pruner) | Filter Pruning via Geometric Median for Deep Convolutional Neural Networks Acceleration [参考论文](https://arxiv.org/pdf/1811.00250.pdf) |
| [L1Filter Pruner](./Pruner.md#l1filter-pruner) | 在卷积层中具有最小 L1 权重规范的剪枝过滤器(用于 Efficient Convnets 的剪枝过滤器) [参考论文](https://arxiv.org/abs/1608.08710) |
| [L2Filter Pruner](./Pruner.md#l2filter-pruner) | 在卷积层中具有最小 L2 权重规范的剪枝过滤器 |
| [ActivationAPoZRankFilterPruner](./Pruner.md#ActivationAPoZRankFilterPruner) | 基于指标 APoZ(平均百分比零)的剪枝过滤器,该指标测量(卷积)图层激活中零的百分比。 [参考论文](https://arxiv.org/abs/1607.03250) |
| [ActivationMeanRankFilterPruner](./Pruner.md#ActivationMeanRankFilterPruner) | 基于计算输出激活最小平均值指标的剪枝过滤器 |
| [Slim Pruner](./Pruner.md#slim-pruner) | 通过修剪 BN 层中的缩放因子来修剪卷积层中的通道 (Learning Efficient Convolutional Networks through Network Slimming) [参考论文](https://arxiv.org/abs/1708.06519) |
**量化** **量化**
量化算法通过减少表示权重或激活所需的精度位数来压缩原始网络,这可以减少计算和推理时间。
| 名称 | 算法简介 | | 名称 | 算法简介 |
| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Naive Quantizer](./Quantizer.md#naive-quantizer) | 默认将权重量化为 8 位 | | [Naive Quantizer](./Quantizer.md#naive-quantizer) | 默认将权重量化为 8 位 |
| [QAT Quantizer](./Quantizer.md#qat-quantizer) | 为 Efficient Integer-Arithmetic-Only Inference 量化并训练神经网络。 [参考论文](http://openaccess.thecvf.com/content_cvpr_2018/papers/Jacob_Quantization_and_Training_CVPR_2018_paper.pdf) | | [QAT Quantizer](./Quantizer.md#qat-quantizer) | 为 Efficient Integer-Arithmetic-Only Inference 量化并训练神经网络。 [参考论文](http://openaccess.thecvf.com/content_cvpr_2018/papers/Jacob_Quantization_and_Training_CVPR_2018_paper.pdf) |
| [DoReFa Quantizer](./Quantizer.md#dorefa-quantizer) | DoReFa-Net: 通过低位宽的梯度算法来训练低位宽的卷积神经网络。 [参考论文](https://arxiv.org/abs/1606.06160) | | [DoReFa Quantizer](./Quantizer.md#dorefa-quantizer) | DoReFa-Net: 通过低位宽的梯度算法来训练低位宽的卷积神经网络。 [参考论文](https://arxiv.org/abs/1606.06160) |
| [BNN Quantizer](./Quantizer.md#BNN-Quantizer) | 二进制神经网络:使用权重和激活限制为 +1 或 -1 的深度神经网络。 [参考论文](https://arxiv.org/abs/1602.02830) |
## 内置压缩算法的用法 ## 内置压缩算法的用法
...@@ -57,17 +69,46 @@ pruner.compress() ...@@ -57,17 +69,46 @@ pruner.compress()
实例化压缩算法时,会传入 `config_list`。 配置说明如下。 实例化压缩算法时,会传入 `config_list`。 配置说明如下。
### 压缩算法中的用户配置 ### 压缩算法中的用户配置
压缩模型时,用户可能希望指定稀疏率,为不同类型的操作指定不同的比例,排除某些类型的操作,或仅压缩某类操作。 配置规范可用于表达此类需求。 可将其视为一个 Python 的 `list` 对象,其中每个元素都是一个 `dict` 对象。
压缩模型时,用户可能希望指定稀疏率,为不同类型的操作指定不同的比例,排除某些类型的操作,或仅压缩某类操作。 配置规范可用于表达此类需求。 可将其视为一个 Python 的 `list` 对象,其中每个元素都是一个 `dict` 对象。 在每个 `dict` 中,有一些 NNI 压缩算法支持的键值: `list` 中的 `dict` 会依次被应用,也就是说,如果一个操作出现在两个配置里,后面的 `dict` 会覆盖前面的配置。
#### 通用键值
在每个 `dict` 中,有一些 NNI 压缩算法支持的键值:
* __op_types__:指定要压缩的操作类型。 'default' 表示使用算法的默认设置。 * __op_types__:指定要压缩的操作类型。 'default' 表示使用算法的默认设置。
* __op_names__:指定需要压缩的操作的名称。 如果没有设置此字段,操作符不会通过名称筛选。 * __op_names__:指定需要压缩的操作的名称。 如果没有设置此字段,操作符不会通过名称筛选。
* __exclude__:默认为 False。 如果此字段为 True,表示要通过类型和名称,将一些操作从压缩中排除。 * __exclude__:默认为 False。 如果此字段为 True,表示要通过类型和名称,将一些操作从压缩中排除。
`dict` 还有一些其它键值,由特定的压缩算法所使用。 例如: #### 量化算法的键值
**如果使用量化算法,则需要设置更多键值。 如果使用剪枝算法,则可以忽略这些键值**
`list` 中的 `dict` 会依次被应用,也就是说,如果一个操作出现在两个配置里,后面的 `dict` 会覆盖前面的配置。 * __quant_types__ : 字符串列表。
要应用量化的类型,当前支持 "权重","输入","输出"。 "权重"是指将量化操作应用到 module 的权重参数上。 "输入" 是指对 module 的 forward 方法的输入应用量化操作。 "输出"是指将量化运法应用于模块 forward 方法的输出,在某些论文中,这种方法称为"激活"。
* __quant_bits__ : int 或 dict {str : int}
量化的位宽,键是量化类型,值是量化位宽度,例如:
```
{
quant_bits: {
'weight': 8,
'output': 4,
},
}
```
当值为 int 类型时,所有量化类型使用相同的位宽。 例如:
```
{
quant_bits: 8, # 权重和输出的位宽都为 8 bits
}
```
#### 为每个压缩算法指定的其他键
`dict` 还有一些其它键值,由特定的压缩算法所使用。 例如, [Level Pruner](./Pruner.md#level-pruner) 需要 `sparsity` 键,用于指定修剪的量。
#### 示例
配置的简单示例如下: 配置的简单示例如下:
```python ```python
...@@ -178,11 +219,9 @@ class YourPruner(nni.compression.tensorflow.Pruner): ...@@ -178,11 +219,9 @@ class YourPruner(nni.compression.tensorflow.Pruner):
定制量化算法的接口与剪枝算法类似。 唯一的不同是使用 `quantize_weight` 替换了 `calc_mask``quantize_weight` 直接返回量化后的权重,而不是 mask。这是因为对于量化算法,量化后的权重不能通过应用 mask 来获得。 定制量化算法的接口与剪枝算法类似。 唯一的不同是使用 `quantize_weight` 替换了 `calc_mask``quantize_weight` 直接返回量化后的权重,而不是 mask。这是因为对于量化算法,量化后的权重不能通过应用 mask 来获得。
```python ```python
# TensorFlow 中定制 Quantizer。 from nni.compression.torch.compressor import Quantizer
# PyTorch 的 Quantizer,只需将
# nni.compression.tensorflow.Quantizer 替换为 class YourQuantizer(Quantizer):
# nni.compression.torch.Quantizer
class YourQuantizer(nni.compression.tensorflow.Quantizer):
def __init__(self, model, config_list): def __init__(self, model, config_list):
""" """
建议使用 NNI 定义的规范来配置 建议使用 NNI 定义的规范来配置
...@@ -231,27 +270,71 @@ class YourQuantizer(nni.compression.tensorflow.Quantizer): ...@@ -231,27 +270,71 @@ class YourQuantizer(nni.compression.tensorflow.Quantizer):
Parameters Parameters
---------- ----------
inputs : Tensor inputs : Tensor
需要量化的输入 需要量化的张量
config : dict config : dict
输入量化的配置 输入量化的配置
""" """
# 实现生成 `new_input` # 生成 `new_input` 的代码
return new_input return new_input
# Pytorch 版本不需要 sess 参数 def update_epoch(self, epoch_num):
def update_epoch(self, epoch_num, sess):
pass pass
# Pytorch 版本不需要 sess 参数 def step(self):
def step(self, sess):
""" """
根据需要可基于 bind_model 方法中的模型或权重进行操作 Can do some processing based on the model or weights binded
in the func bind_model
""" """
pass pass
``` ```
#### 定制 backward 函数
有时,量化操作必须自定义 backward 函数,例如 [Straight-Through Estimator](https://stackoverflow.com/questions/38361314/the-concept-of-straight-through-estimator-ste),可如下定制 backward 函数:
```python
from nni.compression.torch.compressor import Quantizer, QuantGrad, QuantType
class ClipGrad(QuantGrad):
@staticmethod
def quant_backward(tensor, grad_output, quant_type):
"""
此方法应被子类重载来提供定制的 backward 函数,
默认实现是 Straight-Through Estimator
Parameters
----------
tensor : Tensor
量化操作的输入
grad_output : Tensor
量化操作输出的梯度
quant_type : QuantType
量化类型,可为 `QuantType.QUANT_INPUT`, `QuantType.QUANT_WEIGHT`, `QuantType.QUANT_OUTPUT`,
可为不同的类型定义不同的行为。
Returns
-------
tensor
量化输入的梯度
"""
# 对于 quant_output 函数,如果张量的绝对值大于 1,则将梯度设置为 0
if quant_type == QuantType.QUANT_OUTPUT:
grad_output[torch.abs(tensor) > 1] = 0
return grad_output
class YourQuantizer(Quantizer):
def __init__(self, model, config_list):
super().__init__(model, config_list)
# 定制 backward 函数来重载默认的 backward 函数
self.quant_grad = ClipGrad
```
### 使用用户自定义的压缩算法 如果不定制 `QuantGrad`,默认的 backward 为 Straight-Through Estimator。 _即将推出_...
__[TODO]__ ... ## **参考和反馈**
* 在 GitHub 中[提交此功能的 Bug](https://github.com/microsoft/nni/issues/new?template=bug-report.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 中[ NAS 的更多信息](https://github.com/microsoft/nni/blob/master/docs/zh_CN/NAS/Overview.md)
* 了解如何[使用 NNI 进行超参数调优](https://github.com/microsoft/nni/blob/master/docs/zh_CN/Tuner/BuiltinTuner.md)
NNI Compressor 中的 Pruner NNI Compressor 中的 Pruner
=== ===
支持的剪枝算法
* [Level Pruner](#level-pruner)
* [AGP Pruner](#agp-pruner)
* [Lottery Ticket 假设](#lottery-ticket-hypothesis)
* [Slim Pruner](#slim-pruner)
* [具有权重等级的 Filter Pruners](#weightrankfilterpruner)
* [FPGM Pruner](#fpgm-pruner)
* [L1Filter Pruner](#l1filter-pruner)
* [L2Filter Pruner](#l2filter-pruner)
* [具有激活等级的 Filter Pruners](#activationrankfilterpruner)
* [APoZ Rank Pruner](#activationapozrankfilterpruner)
* [Activation Mean Rank Pruner](#activationmeanrankfilterpruner)
## Level Pruner ## Level Pruner
这是个基本的一次性 Pruner:可设置目标稀疏度(以分数表示,0.6 表示会剪除 60%)。 这是个基本的一次性 Pruner:可设置目标稀疏度(以分数表示,0.6 表示会剪除 60%)。
...@@ -10,7 +23,7 @@ NNI Compressor 中的 Pruner ...@@ -10,7 +23,7 @@ NNI Compressor 中的 Pruner
### 用法 ### 用法
TensorFlow 代码 TensorFlow 代码
``` ```python
from nni.compression.tensorflow import LevelPruner from nni.compression.tensorflow import LevelPruner
config_list = [{ 'sparsity': 0.8, 'op_types': ['default'] }] config_list = [{ 'sparsity': 0.8, 'op_types': ['default'] }]
pruner = LevelPruner(model_graph, config_list) pruner = LevelPruner(model_graph, config_list)
...@@ -18,7 +31,7 @@ pruner.compress() ...@@ -18,7 +31,7 @@ pruner.compress()
``` ```
PyTorch 代码 PyTorch 代码
``` ```python
from nni.compression.torch import LevelPruner from nni.compression.torch import LevelPruner
config_list = [{ 'sparsity': 0.8, 'op_types': ['default'] }] config_list = [{ 'sparsity': 0.8, 'op_types': ['default'] }]
pruner = LevelPruner(model, config_list) pruner = LevelPruner(model, config_list)
...@@ -37,8 +50,6 @@ pruner.compress() ...@@ -37,8 +50,6 @@ pruner.compress()
### 用法 ### 用法
通过下列代码,可以在 10 个 Epoch 中将权重稀疏度从 0% 剪枝到 80%。 通过下列代码,可以在 10 个 Epoch 中将权重稀疏度从 0% 剪枝到 80%。
首先,导入 Pruner 来为模型添加遮盖。
TensorFlow 代码 TensorFlow 代码
```python ```python
from nni.compression.tensorflow import AGP_Pruner from nni.compression.tensorflow import AGP_Pruner
...@@ -68,7 +79,7 @@ pruner = AGP_Pruner(model, config_list) ...@@ -68,7 +79,7 @@ pruner = AGP_Pruner(model, config_list)
pruner.compress() pruner.compress()
``` ```
其次,在训练代码中每完成一个 Epoch,更新一下 Epoch 数值。 在训练代码中每完成一个 Epoch,更新一下 Epoch 数值。
TensorFlow 代码 TensorFlow 代码
```python ```python
...@@ -130,12 +141,45 @@ for _ in pruner.get_prune_iterations(): ...@@ -130,12 +141,45 @@ for _ in pruner.get_prune_iterations():
* **sparsity:** 压缩完成后的最终稀疏度。 * **sparsity:** 压缩完成后的最终稀疏度。
*** ***
## FPGM Pruner
## Slim Pruner
这是一次性的 Pruner,在 ['Learning Efficient Convolutional Networks through Network Slimming'](https://arxiv.org/pdf/1708.06519.pdf) 中提出,作者 Zhuang Liu, Jianguo Li, Zhiqiang Shen, Gao Huang, Shoumeng Yan 以及 Changshui Zhang。
![](../../img/slim_pruner.png)
> Slim Pruner **会遮盖卷据层通道之后 BN 层对应的缩放因子**,训练时在缩放因子上的 L1 正规化应在批量正规化 (BN) 层之后来做。BN 层的缩放因子在修剪时,是**全局排序的**,因此稀疏模型能自动找到给定的稀疏度。
### 用法
PyTorch 代码
```python
from nni.compression.torch import SlimPruner
config_list = [{ 'sparsity': 0.8, 'op_types': ['BatchNorm2d'] }]
pruner = SlimPruner(model, config_list)
pruner.compress()
```
#### Slim Pruner 的用户配置
- **sparsity:**,指定压缩的稀疏度。
- **op_types:** 在 Slim Pruner 中仅支持 BatchNorm2d。
## WeightRankFilterPruner
WeightRankFilterPruner 是一系列的 Pruner,在卷积层权重上,用最小的重要性标准修剪过滤器,来达到预设的网络稀疏度。
### FPGM Pruner
这是一种一次性的 Pruner,FPGM Pruner 是论文 [Filter Pruning via Geometric Median for Deep Convolutional Neural Networks Acceleration](https://arxiv.org/pdf/1811.00250.pdf) 的实现 这是一种一次性的 Pruner,FPGM Pruner 是论文 [Filter Pruning via Geometric Median for Deep Convolutional Neural Networks Acceleration](https://arxiv.org/pdf/1811.00250.pdf) 的实现
具有最小几何中位数的 FPGMPruner 修剪过滤器
![](../../img/fpgm_fig1.png)
> 以前的方法使用 “smaller-norm-less-important” 准则来修剪卷积神经网络中规范值较小的。 本文中,分析了基于规范的准则,并指出其所依赖的两个条件不能总是满足:(1) 过滤器的规范偏差应该较大;(2) 过滤器的最小规范化值应该很小。 为了解决此问题,提出了新的过滤器修建方法,即 Filter Pruning via Geometric Median (FPGM),可不考虑这两个要求来压缩模型。 与以前的方法不同,FPGM 通过修剪冗余的,而不是相关性更小的部分来压缩 CNN 模型。 > 以前的方法使用 “smaller-norm-less-important” 准则来修剪卷积神经网络中规范值较小的。 本文中,分析了基于规范的准则,并指出其所依赖的两个条件不能总是满足:(1) 过滤器的规范偏差应该较大;(2) 过滤器的最小规范化值应该很小。 为了解决此问题,提出了新的过滤器修建方法,即 Filter Pruning via Geometric Median (FPGM),可不考虑这两个要求来压缩模型。 与以前的方法不同,FPGM 通过修剪冗余的,而不是相关性更小的部分来压缩 CNN 模型。
### 用法 #### 用法
首先,导入 Pruner 来为模型添加遮盖。
TensorFlow 代码 TensorFlow 代码
```python ```python
...@@ -159,7 +203,7 @@ pruner.compress() ...@@ -159,7 +203,7 @@ pruner.compress()
``` ```
注意:FPGM Pruner 用于修剪深度神经网络中的卷积层,因此 `op_types` 字段仅支持卷积层。 注意:FPGM Pruner 用于修剪深度神经网络中的卷积层,因此 `op_types` 字段仅支持卷积层。
另外,需要在每个 epoch 开始的地方添加下列代码来更新 epoch 的编号。 需要在每个 epoch 开始的地方添加下列代码来更新 epoch 的编号。
TensorFlow 代码 TensorFlow 代码
```python ```python
...@@ -176,9 +220,9 @@ pruner.update_epoch(epoch) ...@@ -176,9 +220,9 @@ pruner.update_epoch(epoch)
*** ***
## L1Filter Pruner ### L1Filter Pruner
这是一种一次性的 Pruner,由 ['PRUNING FILTERS FOR EFFICIENT CONVNETS'](https://arxiv.org/abs/1608.08710) 提出,作者 Hao Li, Asim Kadav, Igor Durdanovic, Hanan Samet 和 Hans Peter Graf。 这是一种一次性的 Pruner,由 ['PRUNING FILTERS FOR EFFICIENT CONVNETS'](https://arxiv.org/abs/1608.08710) 提出,作者 Hao Li, Asim Kadav, Igor Durdanovic, Hanan Samet 和 Hans Peter Graf。 [重现的实验结果](l1filterpruner.md)
![](../../img/l1filter_pruner.png) ![](../../img/l1filter_pruner.png)
...@@ -191,7 +235,11 @@ pruner.update_epoch(epoch) ...@@ -191,7 +235,11 @@ pruner.update_epoch(epoch)
> 3. 修剪 ![](http://latex.codecogs.com/gif.latex?m) 具有最小求和值及其相应特征图的筛选器。 在 下一个卷积层中,被剪除的特征图所对应的内核也被移除。 > 3. 修剪 ![](http://latex.codecogs.com/gif.latex?m) 具有最小求和值及其相应特征图的筛选器。 在 下一个卷积层中,被剪除的特征图所对应的内核也被移除。
> 4. 为第 ![](http://latex.codecogs.com/gif.latex?i) 和 ![](http://latex.codecogs.com/gif.latex?i+1) 层创建新的内核举证,并保留剩余的内核 权重,并复制到新模型中。 > 4. 为第 ![](http://latex.codecogs.com/gif.latex?i) 和 ![](http://latex.codecogs.com/gif.latex?i+1) 层创建新的内核举证,并保留剩余的内核 权重,并复制到新模型中。
``` #### 用法
PyTorch 代码
```python
from nni.compression.torch import L1FilterPruner from nni.compression.torch import L1FilterPruner
config_list = [{ 'sparsity': 0.8, 'op_types': ['Conv2d'] }] config_list = [{ 'sparsity': 0.8, 'op_types': ['Conv2d'] }]
pruner = L1FilterPruner(model, config_list) pruner = L1FilterPruner(model, config_list)
...@@ -201,28 +249,91 @@ pruner.compress() ...@@ -201,28 +249,91 @@ pruner.compress()
#### L1Filter Pruner 的用户配置 #### L1Filter Pruner 的用户配置
- **sparsity:**,指定压缩的稀疏度。 - **sparsity:**,指定压缩的稀疏度。
- **op_types:** 在 L1Filter Pruner 中仅支持 Conv2d。 - **op_types:** 在 L1Filter Pruner 中仅支持 Conv1d 和 Conv2d。
## Slim Pruner ***
这是一次性的 Pruner,在 ['Learning Efficient Convolutional Networks through Network Slimming'](https://arxiv.org/pdf/1708.06519.pdf) 中提出,作者 Zhuang Liu, Jianguo Li, Zhiqiang Shen, Gao Huang, Shoumeng Yan 以及 Changshui Zhang。 ### L2Filter Pruner
![](../../img/slim_pruner.png) 这是一种结构化剪枝算法,用于修剪权重的最小 L2 规范筛选器。 它被实现为一次性修剪器。
> Slim Pruner **会遮盖卷据层通道之后 BN 层对应的缩放因子**,训练时在缩放因子上的 L1 正规化应在批量正规化 (BN) 层之后来做。BN 层的缩放因子在修剪时,是**全局排序的**,因此稀疏模型能自动找到给定的稀疏度。 #### 用法
### 用法 PyTorch 代码
```python
from nni.compression.torch import L2FilterPruner
config_list = [{ 'sparsity': 0.8, 'op_types': ['Conv2d'] }]
pruner = L2FilterPruner(model, config_list)
pruner.compress()
```
#### L2Filter Pruner 的用户配置
- **sparsity:**,指定压缩的稀疏度。
- **op_types:** 在 L2Filter Pruner 中仅支持 Conv1d 和 Conv2d。
## ActivationRankFilterPruner
ActivationRankFilterPruner 是一系列的 Pruner,从卷积层激活的输出,用最小的重要性标准修剪过滤器,来达到预设的网络稀疏度。
### ActivationAPoZRankFilterPruner
我们将其实现为一次性剪枝器,它基于 `APoZ` 修剪卷积层,参考论文 [Network Trimming: A Data-Driven Neuron Pruning Approach towards Efficient Deep Architectures](https://arxiv.org/abs/1607.03250)。 基于迭代剪枝的 `APoZ` 将在以后的版本中支持。
APoZ 定义为:
![](../../img/apoz.png)
#### 用法
PyTorch 代码 PyTorch 代码
```python
from nni.compression.torch import ActivationAPoZRankFilterPruner
config_list = [{
'sparsity': 0.5,
'op_types': ['Conv2d']
}]
pruner = ActivationAPoZRankFilterPruner(model, config_list, statistics_batch_num=1)
pruner.compress()
``` ```
from nni.compression.torch import SlimPruner
config_list = [{ 'sparsity': 0.8, 'op_types': ['BatchNorm2d'] }] 注意:ActivationAPoZRankFilterPruner 用于修剪深度神经网络中的卷积层,因此 `op_types` 字段仅支持卷积层。
pruner = SlimPruner(model, config_list)
查看示例进一步了解
#### ActivationAPoZRankFilterPruner 的用户配置
- **sparsity:** 卷积过滤器要修剪的百分比。
- **op_types:** 在 ActivationAPoZRankFilterPruner 中仅支持 Conv2d。
***
### ActivationMeanRankFilterPruner
其实现为一次性修剪器,基于 `平均激活` 准则来修剪卷积层,在论文 [Pruning Convolutional Neural Networks for Resource Efficient Inference](https://arxiv.org/abs/1611.06440) 的 2.2 节中有说明。 本文中提到的其他修剪标准将在以后的版本中支持。
#### 用法
PyTorch 代码
```python
from nni.compression.torch import ActivationMeanRankFilterPruner
config_list = [{
'sparsity': 0.5,
'op_types': ['Conv2d']
}]
pruner = ActivationMeanRankFilterPruner(model, config_list)
pruner.compress() pruner.compress()
``` ```
#### Slim Pruner 的用户配置 注意:ActivationMeanRankFilterPruner 用于修剪深度神经网络中的卷积层,因此 `op_types` 字段仅支持卷积层。
- **sparsity:**,指定压缩的稀疏度。 查看示例进一步了解
- **op_types:** 在 Slim Pruner 中仅支持 BatchNorm2d。
#### ActivationMeanRankFilterPruner 的用户配置
- **sparsity:** 卷积过滤器要修剪的百分比。
- **op_types:** 在 ActivationMeanRankFilterPruner 中仅支持 Conv2d。
***
\ No newline at end of file
NNI Compressor 中的 Quantizer NNI Compressor 中的 Quantizer
=== ===
## Naive Quantizer ## Naive Quantizer
Naive Quantizer 将 Quantizer 权重默认设置为 8 位,可用它来测试量化算法。 Naive Quantizer 将 Quantizer 权重默认设置为 8 位,可用它来测试量化算法。
### 用法 ### 用法
Tensorflow tensorflow ```python nni.compression.tensorflow.NaiveQuantizer(model_graph).compress()
```python
nni.compressors.tensorflow.NaiveQuantizer(model_graph).compress()
``` ```
PyTorch pytorch
```python ```python nni.compression.torch.NaiveQuantizer(model).compress()
nni.compressors.torch.NaiveQuantizer(model).compress()
``` ```
*** ***
...@@ -27,7 +23,7 @@ nni.compressors.torch.NaiveQuantizer(model).compress() ...@@ -27,7 +23,7 @@ nni.compressors.torch.NaiveQuantizer(model).compress()
PyTorch 代码 PyTorch 代码
```python ```python
from nni.compressors.torch import QAT_Quantizer from nni.compression.torch import QAT_Quantizer
model = Mnist() model = Mnist()
config_list = [{ config_list = [{
...@@ -49,9 +45,13 @@ quantizer.compress() ...@@ -49,9 +45,13 @@ quantizer.compress()
查看示例进一步了解 查看示例进一步了解
#### QAT Quantizer 的用户配置 #### QAT Quantizer 的用户配置
* **quant_types:**: 字符串列表 要应用的量化类型,当前支持 'weight', 'input', 'output' 压缩算法所需的常见配置可在[通用配置](./Overview.md#User-configuration-for-a-compression-algorithm)中找到。
* **quant_bits:** int 或 {str : int} 的 dict 量化的位长,主键是量化类型,键值为长度,例如。 {'weight', 8}, 当类型为 int 时,所有量化类型都用同样的位长
* **quant_start_step:** int 在运行到某步骤前,对模型禁用量化。这让网络在进入更稳定的 状态后再激活量化,这样不会配除掉一些分数显著的值,默认为 0 此算法所需的配置:
* **quant_start_step:** int
在运行到某步骤前,对模型禁用量化。这让网络在进入更稳定的 状态后再激活量化,这样不会配除掉一些分数显著的值,默认为 0
### 注意 ### 注意
当前不支持批处理规范化折叠。 当前不支持批处理规范化折叠。
...@@ -63,17 +63,14 @@ quantizer.compress() ...@@ -63,17 +63,14 @@ quantizer.compress()
### 用法 ### 用法
要实现 DoReFa Quantizer,在训练代码前加入以下代码。 要实现 DoReFa Quantizer,在训练代码前加入以下代码。
TensorFlow 代码
```python
from nni.compressors.tensorflow import DoReFaQuantizer
config_list = [{ 'q_bits': 8, 'op_types': 'default' }]
quantizer = DoReFaQuantizer(tf.get_default_graph(), config_list)
quantizer.compress()
```
PyTorch 代码 PyTorch 代码
```python ```python
from nni.compressors.torch import DoReFaQuantizer from nni.compression.torch import DoReFaQuantizer
config_list = [{ 'q_bits': 8, 'op_types': 'default' }] config_list = [{
'quant_types': ['weight'],
'quant_bits': 8,
'op_types': 'default'
}]
quantizer = DoReFaQuantizer(model, config_list) quantizer = DoReFaQuantizer(model, config_list)
quantizer.compress() quantizer.compress()
``` ```
...@@ -81,4 +78,52 @@ quantizer.compress() ...@@ -81,4 +78,52 @@ quantizer.compress()
查看示例进一步了解 查看示例进一步了解
#### DoReFa Quantizer 的用户配置 #### DoReFa Quantizer 的用户配置
* **q_bits:** 指定需要被量化的位数。 压缩算法所需的常见配置可在[通用配置](./Overview.md#User-configuration-for-a-compression-algorithm)中找到。
此算法所需的配置:
## BNN Quantizer
在 [Binarized Neural Networks: Training Deep Neural Networks with Weights and Activations Constrained to +1 or -1](https://arxiv.org/abs/1602.02830) 中,
> 引入了一种训练二进制神经网络(BNN)的方法 - 神经网络在运行时使用二进制权重。 在训练时,二进制权重和激活用于计算参数梯度。 在 forward 过程中,BNN 会大大减少内存大小和访问,并将大多数算术运算替换为按位计算,可显著提高能源效率。
### 用法
PyTorch 代码
```python
from nni.compression.torch import BNNQuantizer
model = VGG_Cifar10(num_classes=10)
configure_list = [{
'quant_bits': 1,
'quant_types': ['weight'],
'op_types': ['Conv2d', 'Linear'],
'op_names': ['features.0', 'features.3', 'features.7', 'features.10', 'features.14', 'features.17', 'classifier.0', 'classifier.3']
}, {
'quant_bits': 1,
'quant_types': ['output'],
'op_types': ['Hardtanh'],
'op_names': ['features.6', 'features.9', 'features.13', 'features.16', 'features.20', 'classifier.2', 'classifier.5']
}]
quantizer = BNNQuantizer(model, configure_list)
model = quantizer.compress()
```
可以查看示例 [examples/model_compress/BNN_quantizer_cifar10.py](https://github.com/microsoft/nni/tree/master/examples/model_compress/BNN_quantizer_cifar10.py) 了解更多信息。
#### BNN Quantizer 的用户配置
压缩算法所需的常见配置可在[通用配置](./Overview.md#User-configuration-for-a-compression-algorithm)中找到。
此算法所需的配置:
### 实验
我们实现了 [Binarized Neural Networks: Training Deep Neural Networks with Weights and Activations Constrained to +1 or -1](https://arxiv.org/abs/1602.02830) 中的一个实验,对 CIFAR-10 上的 **VGGNet** 进行了量化操作。 我们的实验结果如下:
| 模型 | 精度 |
| ------ | ------ |
| VGGNet | 86.93% |
实验代码可在 [examples/model_compress/BNN_quantizer_cifar10.py](https://github.com/microsoft/nni/tree/master/examples/model_compress/BNN_quantizer_cifar10.py)
\ No newline at end of file
NNI Compressor 中的 L1FilterPruner NN I 上的 L1FilterPruner
=== ===
## 1. 介绍 ## 介绍
L1FilterPruner 是在卷积层中用来修剪过滤器的通用剪枝算法。 L1FilterPruner 是在卷积层中用来修剪过滤器的通用剪枝算法。
...@@ -18,25 +18,9 @@ L1FilterPruner 是在卷积层中用来修剪过滤器的通用剪枝算法。 ...@@ -18,25 +18,9 @@ L1FilterPruner 是在卷积层中用来修剪过滤器的通用剪枝算法。
> 3. 修剪 ![](http://latex.codecogs.com/gif.latex?m) 具有最小求和值及其相应特征图的筛选器。 在 下一个卷积层中,被剪除的特征图所对应的内核也被移除。 > 3. 修剪 ![](http://latex.codecogs.com/gif.latex?m) 具有最小求和值及其相应特征图的筛选器。 在 下一个卷积层中,被剪除的特征图所对应的内核也被移除。
> 4. 为第 ![](http://latex.codecogs.com/gif.latex?i) 和 ![](http://latex.codecogs.com/gif.latex?i+1) 层创建新的内核举证,并保留剩余的内核 权重,并复制到新模型中。 > 4. 为第 ![](http://latex.codecogs.com/gif.latex?i) 和 ![](http://latex.codecogs.com/gif.latex?i+1) 层创建新的内核举证,并保留剩余的内核 权重,并复制到新模型中。
## 2. 用法 ## 实验
PyTorch 代码 我们通过 **L1FilterPruner** 实现了 ['PRUNING FILTERS FOR EFFICIENT CONVNETS'](https://arxiv.org/abs/1608.08710) 中的一项实验, 即论文中,在 CIFAR-10 数据集上修剪 **VGG-16****VGG-16-pruned-A**,其中大约剪除了 $64\%$ 的参数。 我们的实验结果如下:
```
from nni.compression.torch import L1FilterPruner
config_list = [{ 'sparsity': 0.8, 'op_types': ['Conv2d'], 'op_names': ['conv1', 'conv2'] }]
pruner = L1FilterPruner(model, config_list)
pruner.compress()
```
#### L1Filter Pruner 的用户配置
- **sparsity:**,指定压缩的稀疏度。
- **op_types:** 在 L1Filter Pruner 中仅支持 Conv2d。
## 3. 实验
我们实现了 ['PRUNING FILTERS FOR EFFICIENT CONVNETS'](https://arxiv.org/abs/1608.08710) 中的一项实验, 即论文中,在 CIFAR-10 数据集上修剪 **VGG-16****VGG-16-pruned-A**,其中大约剪除了 $64\%$ 的参数。 我们的实验结果如下:
| 模型 | 错误率(论文/我们的) | 参数量 | 剪除率 | | 模型 | 错误率(论文/我们的) | 参数量 | 剪除率 |
| --------------- | ----------- | -------- | ----- | | --------------- | ----------- | -------- | ----- |
......
# 特征工程 # NNI 中的特征工程
我们很高兴的宣布,基于 NNI 的特征工程工具发布了 Alpha 版本。该版本仍处于试验阶段,根据使用反馈会进行改进。 诚挚邀请您使用、反馈,或更多贡献。 我们很高兴的宣布,基于 NNI 的特征工程工具发布了试用版本。该版本仍处于试验阶段,根据使用反馈会进行改进。 诚挚邀请您使用、反馈,或更多贡献。
当前支持以下特征选择器: 当前支持以下特征选择器:
- [GradientFeatureSelector](./GradientFeatureSelector.md) - [GradientFeatureSelector](./GradientFeatureSelector.md)
...@@ -254,3 +254,10 @@ print("Pipeline Score: ", pipeline.score(X_train, y_train)) ...@@ -254,3 +254,10 @@ print("Pipeline Score: ", pipeline.score(X_train, y_train))
此基准测试可在[这里](https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/)下载 此基准测试可在[这里](https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/)下载
代码参考 `/examples/feature_engineering/gradient_feature_selector/benchmark_test.py` 代码参考 `/examples/feature_engineering/gradient_feature_selector/benchmark_test.py`
## **参考和反馈**
* 在 GitHub 中[提交此功能的 Bug](https://github.com/microsoft/nni/issues/new?template=bug-report.md)
* 在 GitHub 中[提交新功能或改进请求](https://github.com/microsoft/nni/issues/new?template=enhancement.md)
* 了解 NNI 中[神经网络结构搜索的更多信息](https://github.com/microsoft/nni/blob/master/docs/zh_CN/NAS/Overview.md)
* 了解 NNI 中[模型自动压缩的更多信息](https://github.com/microsoft/nni/blob/master/docs/zh_CN/Compressor/Overview.md)
* 了解如何[使用 NNI 进行超参数调优](https://github.com/microsoft/nni/blob/master/docs/zh_CN/Tuner/BuiltinTuner.md)
...@@ -105,3 +105,10 @@ python3 retrain.py --arc-checkpoint ../pdarts/checkpoints/epoch_2.json ...@@ -105,3 +105,10 @@ python3 retrain.py --arc-checkpoint ../pdarts/checkpoints/epoch_2.json
2. 在神经网络上应用 NAS 时,需要统一的方式来表达架构的搜索空间,这样不必为不同的搜索算法来更改代码。 2. 在神经网络上应用 NAS 时,需要统一的方式来表达架构的搜索空间,这样不必为不同的搜索算法来更改代码。
NNI 提出的 API 在[这里](https://github.com/microsoft/nni/tree/master/src/sdk/pynni/nni/nas/pytorch)[这里](https://github.com/microsoft/nni/tree/master/examples/nas/darts)包含了基于此 API 的 NAS 实现示例。 NNI 提出的 API 在[这里](https://github.com/microsoft/nni/tree/master/src/sdk/pynni/nni/nas/pytorch)[这里](https://github.com/microsoft/nni/tree/master/examples/nas/darts)包含了基于此 API 的 NAS 实现示例。
## **参考和反馈**
* 在 GitHub 中[提交此功能的 Bug](https://github.com/microsoft/nni/issues/new?template=bug-report.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 中[模型自动压缩的更多信息](https://github.com/microsoft/nni/blob/master/docs/zh_CN/Compressor/Overview.md)
* 了解如何[使用 NNI 进行超参数调优](https://github.com/microsoft/nni/blob/master/docs/zh_CN/Tuner/BuiltinTuner.md)
# P-DARTS
## 示例
[示例代码](https://github.com/microsoft/nni/tree/master/examples/nas/pdarts)
```bash
#如果未克隆 NNI 代码。 如果代码已被克隆,请忽略此行并直接进入代码目录。
git clone https://github.com/Microsoft/nni.git
# 搜索最好的架构
cd examples/nas/pdarts
python3 search.py
# 训练最好的架构,过程与 darts 相同。
cd ../darts
python3 retrain.py --arc-checkpoint ../pdarts/checkpoints/epoch_2.json
```
# 单路径 One-Shot (SPOS)
## 介绍
[Single Path One-Shot Neural Architecture Search with Uniform Sampling](https://arxiv.org/abs/1904.00420) 中提出的 one-shot NAS 方法,通过构造简化的通过统一路径采样方法训练的超网络来解决 One-Shot 模型训练的问题。这样所有架构(及其权重)都得到了完全且平等的训练。 然后,采用进化算法无需任何微调即可有效的搜索出性能最佳的体系结构。
在 NNI 上的实现基于 [官方 Repo](https://github.com/megvii-model/SinglePathOneShot). 实现了一个训练超级网络的 Trainer,以及一个利用 NNI 框架能力来加速进化搜索阶段的进化 Tuner。 还展示了
## 示例
此示例是论文中的搜索空间,使用 flops 限制来执行统一的采样方法。
[示例代码](https://github.com/microsoft/nni/tree/master/examples/nas/spos)
### 必需组件
由于使用了 DALI 来加速 ImageNet 的数据读取,需要 NVIDIA DALI >= 0.16。 [安装指南](https://docs.nvidia.com/deeplearning/sdk/dali-developer-guide/docs/installation.html)
[这里](https://1drv.ms/u/s!Am_mmG2-KsrnajesvSdfsq_cN48?e=aHVppN) ( [Megvii](https://github.com/megvii-model) 维护) 下载 flops 查找表。 将 `op_flops_dict.pkl``checkpoint-150000.pth.tar` (如果不需要重新训练超网络) 放到 `data` 目录中。
准备标准格式的 ImageNet (参考[这里的脚本](https://gist.github.com/BIGBALLON/8a71d225eff18d88e469e6ea9b39cef4))。 将其链接到 `data/imagenet` 会更方便。
准备好后,应具有以下代码结构:
```
spos
├── architecture_final.json
├── blocks.py
├── config_search.yml
├── data
│ ├── imagenet
│ │ ├── train
│ │ └── val
│ └── op_flops_dict.pkl
├── dataloader.py
├── network.py
├── readme.md
├── scratch.py
├── supernet.py
├── tester.py
├── tuner.py
└── utils.py
```
### 步骤 1. 训练超网络
```
python supernet.py
```
会将检查点导出到 `checkpoints` 目录中,为下一步做准备。
注意:数据加载的官方 Repo [与通常的方法有所不同](https://github.com/megvii-model/SinglePathOneShot/issues/5),使用了 BGR 张量,以及 0 到 255 之间的值来与自己的深度学习框架对齐。 选项 `--spos-preprocessing` 会模拟原始的使用行为,并能使用预训练的检查点。
### 步骤 2. 进化搜索
单路径 One-Shot 利用进化算法来搜索最佳架构。 tester 负责通过训练图像的子集来测试采样的体系结构,重新计算所有批处理规范,并在完整的验证集上评估架构。
为了使 Tuner 识别 flops 限制并能计算 flops,在 `tuner.py` 中创建了新的 `EvolutionWithFlops` Tuner,其继承于 SDK 中的 tuner。
要为 NNI 框架准备好搜索空间,首先运行
```
nnictl ss_gen -t "python tester.py"
```
将生成 `nni_auto_gen_search_space.json` 文件,这是搜索空间的序列化形式。
默认情况下,它将使用前面下载的 `checkpoint-150000.pth.tar`。 如果要使用从自行训练的检查点,在 `config_search.yml` 中的命令上指定 `---checkpoint`
然后使用进化 Tuner 搜索。
```
nnictl create --config config_search.yml
```
从每个 Epoch 导出的最终架构可在 Tuner 工作目录下的 `checkpoints` 中找到,默认值为 `$HOME/nni/experiments/your_experiment_id/log`
### 步骤 3. 从头开始训练
```
python scratch.py
```
默认情况下,它将使用 `architecture_final.json`. 该体系结构由官方仓库提供(转换成了 NNI 格式)。 通过 `--fixed-arc` 选项,可使用任何结构(例如,步骤 2 中找到的结构)。
## 参考
### PyTorch
```eval_rst
.. autoclass:: nni.nas.pytorch.spos.SPOSEvolution
:members:
.. automethod:: __init__
.. autoclass:: nni.nas.pytorch.spos.SPOSSupernetTrainer
:members:
.. automethod:: __init__
.. autoclass:: nni.nas.pytorch.spos.SPOSSupernetTrainingMutator
:members:
.. automethod:: __init__
```
## 已知的局限
* 仅支持 Block 搜索。 尚不支持通道搜索。
* 仅提供 GPU 版本。
## 当前重现结果
重现中。 由于官方版本和原始论文之间的不同,我们将当前结果与官方 Repo(我们运行的结果)和论文进行了比较。
* 进化阶段几乎与官方 Repo 一致。 进化算法显示出了收敛趋势,在搜索结束时达到约 65% 的精度。 但此结果与论文不一致。 详情参考[此 issue](https://github.com/megvii-model/SinglePathOneShot/issues/6)
* 重新训练阶段未匹配。 我们的重新训练代码,使用了作者发布的架构,获得了 72.14% 的准确率,与官方发布的 73.61%,和原始论文中的 74.3% 有一定差距。
...@@ -37,7 +37,7 @@ Experiment 的运行过程为:Tuner 接收搜索空间并生成配置。 这 ...@@ -37,7 +37,7 @@ Experiment 的运行过程为:Tuner 接收搜索空间并生成配置。 这
> >
> 第二步:[改动模型代码](TrialExample/Trials.md) > 第二步:[改动模型代码](TrialExample/Trials.md)
> >
> 第三步:[>定义 Experiment 配置](Tutorial/ExperimentConfig.md) > 第三步:[定义 Experiment 配置](Tutorial/ExperimentConfig.md)
<p align="center"> <p align="center">
<img src="https://user-images.githubusercontent.com/23273522/51816627-5d13db80-2302-11e9-8f3e-627e260203d5.jpg" alt="绘图"/> <img src="https://user-images.githubusercontent.com/23273522/51816627-5d13db80-2302-11e9-8f3e-627e260203d5.jpg" alt="绘图"/>
......
...@@ -246,7 +246,7 @@ ...@@ -246,7 +246,7 @@
* 修复了在某些极端条件下,不能正确存储任务的取消状态。 * 修复了在某些极端条件下,不能正确存储任务的取消状态。
* 修复在使用 SMAC Tuner 时,解析搜索空间的错误。 * 修复在使用 SMAC Tuner 时,解析搜索空间的错误。
* 修复 CIFAR-10 例中的 broken pipe 问题。 * 修复 CIFAR-10 例中的 broken pipe 问题。
* 为本地训练和 NNI 管理器添加单元测试。 * 为本地训练和 NNI 管理器添加单元测试。
* 为远程服务器、OpenPAI 和 Kubeflow 训练平台在 Azure 中增加集成测试。 * 为远程服务器、OpenPAI 和 Kubeflow 训练平台在 Azure 中增加集成测试。
* 在 OpenPAI 客户端中支持 Pylon 路径。 * 在 OpenPAI 客户端中支持 Pylon 路径。
...@@ -284,7 +284,7 @@ ...@@ -284,7 +284,7 @@
* [FrameworkController 训练平台](TrainingService/FrameworkControllerMode.md):支持使用在 Kubernetes 上使用 FrameworkController 运行。 * [FrameworkController 训练平台](TrainingService/FrameworkControllerMode.md):支持使用在 Kubernetes 上使用 FrameworkController 运行。
* FrameworkController 是 Kubernetes 上非常通用的控制器(Controller),能用来运行基于各种机器学习框架的分布式作业,如 TensorFlow,Pytorch, MXNet 等。 * FrameworkController 是 Kubernetes 上非常通用的控制器(Controller),能用来运行基于各种机器学习框架的分布式作业,如 TensorFlow,Pytorch, MXNet 等。
* NNI 为作业定义了统一而简单的规范。 * NNI 为作业定义了统一而简单的规范。
* 如何使用 FrameworkController 的 MNIST 例。 * 如何使用 FrameworkController 的 MNIST 例。
#### 改进用户体验 #### 改进用户体验
...@@ -324,7 +324,7 @@ ...@@ -324,7 +324,7 @@
### 新示例 ### 新示例
* [FashionMnist](https://github.com/microsoft/nni/tree/master/examples/trials/network_morphism),使用 network morphism Tuner * [FashionMnist](https://github.com/microsoft/nni/tree/master/examples/trials/network_morphism),使用 network morphism Tuner
* 使用 PyTorch 的[分布式 MNIST ](https://github.com/microsoft/nni/tree/master/examples/trials/mnist-distributed-pytorch) * 使用 PyTorch 的[分布式 MNIST ](https://github.com/microsoft/nni/tree/master/examples/trials/mnist-distributed-pytorch)
## 发布 0.4 - 12/6/2018 ## 发布 0.4 - 12/6/2018
...@@ -332,7 +332,7 @@ ...@@ -332,7 +332,7 @@
* [Kubeflow 训练平台](TrainingService/KubeflowMode.md) * [Kubeflow 训练平台](TrainingService/KubeflowMode.md)
* 支持 tf-operator * 支持 tf-operator
* 使用 Kubeflow 的[分布式 Trial ](https://github.com/microsoft/nni/tree/master/examples/trials/mnist-distributed/dist_mnist.py) * 使用 Kubeflow 的[分布式 Trial ](https://github.com/microsoft/nni/tree/master/examples/trials/mnist-distributed/dist_mnist.py)
* [遍历搜索 Tuner](Tuner/GridsearchTuner.md) * [遍历搜索 Tuner](Tuner/GridsearchTuner.md)
* [Hyperband Tuner](Tuner/HyperbandAdvisor.md) * [Hyperband Tuner](Tuner/HyperbandAdvisor.md)
* 支持在 MAC 上运行 NNI Experiment * 支持在 MAC 上运行 NNI Experiment
...@@ -372,7 +372,7 @@ ...@@ -372,7 +372,7 @@
### API 的新功能和更新 ### API 的新功能和更新
* <span style="color:red"><strong>不兼容的改动</strong></span>:nn.get_parameters() 改为 nni.get_next_parameter。 所有以前版本的例将无法在 v0.3 上运行,需要重新克隆 NNI 代码库获取新例。 如果在自己的代码中使用了 NNI,也需要相应的更新。 * <span style="color:red"><strong>不兼容的改动</strong></span>:nn.get_parameters() 改为 nni.get_next_parameter。 所有以前版本的例将无法在 v0.3 上运行,需要重新克隆 NNI 代码库获取新例。 如果在自己的代码中使用了 NNI,也需要相应的更新。
* 新 API **nni.get_sequence_id()**。 每个 Trial 任务都会被分配一个唯一的序列数字,可通过 nni.get_sequence_id() API 来获取。 * 新 API **nni.get_sequence_id()**。 每个 Trial 任务都会被分配一个唯一的序列数字,可通过 nni.get_sequence_id() API 来获取。
...@@ -400,9 +400,9 @@ ...@@ -400,9 +400,9 @@
docker pull msranni/nni:latest docker pull msranni/nni:latest
``` ```
* 新的 Trial 例:[NNI Sklearn ](https://github.com/microsoft/nni/tree/master/examples/trials/sklearn) * 新的 Trial 例:[NNI Sklearn ](https://github.com/microsoft/nni/tree/master/examples/trials/sklearn)
* 新的竞赛例:[Kaggle Competition TGS Salt](https://github.com/microsoft/nni/tree/master/examples/trials/kaggle-tgs-salt) * 新的竞赛例:[Kaggle Competition TGS Salt](https://github.com/microsoft/nni/tree/master/examples/trials/kaggle-tgs-salt)
### 其它 ### 其它
...@@ -420,7 +420,7 @@ ...@@ -420,7 +420,7 @@
* [SMAC](https://www.cs.ubc.ca/~hutter/papers/10-TR-SMAC.pdf) 基于 Sequential Model-Based Optimization (SMBO). 它会利用使用过的结果好的模型(高斯随机过程模型),并将随机森林引入到 SMBO 中,来处理分类参数。 NNI 的 SMAC 通过包装 [SMAC3](https://github.com/automl/SMAC3) 来支持。 * [SMAC](https://www.cs.ubc.ca/~hutter/papers/10-TR-SMAC.pdf) 基于 Sequential Model-Based Optimization (SMBO). 它会利用使用过的结果好的模型(高斯随机过程模型),并将随机森林引入到 SMBO 中,来处理分类参数。 NNI 的 SMAC 通过包装 [SMAC3](https://github.com/automl/SMAC3) 来支持。
* 支持将 NNI 安装在 [conda](https://conda.io/docs/index.html) 和 Python 虚拟环境中。 * 支持将 NNI 安装在 [conda](https://conda.io/docs/index.html) 和 Python 虚拟环境中。
* 其它 * 其它
* 更新 ga squad 例与相关文档 * 更新 ga squad 例与相关文档
* 用户体验改善及 Bug 修复 * 用户体验改善及 Bug 修复
## 发布 0.1.0 - 9/10/2018 (首个版本) ## 发布 0.1.0 - 9/10/2018 (首个版本)
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
参考[Kubeflow 训练平台](KubeflowMode.md)的设计,FrameworkController 训练平台与其类似。 参考[Kubeflow 训练平台](KubeflowMode.md)的设计,FrameworkController 训练平台与其类似。
## ##
FrameworkController 配置文件的格式如下: FrameworkController 配置文件的格式如下:
...@@ -93,7 +93,7 @@ frameworkcontrollerConfig: ...@@ -93,7 +93,7 @@ frameworkcontrollerConfig:
注意:如果用 FrameworkController 模式运行,需要在 YAML 文件中显式设置 `trainingServicePlatform: frameworkcontroller` 注意:如果用 FrameworkController 模式运行,需要在 YAML 文件中显式设置 `trainingServicePlatform: frameworkcontroller`
FrameworkController 模式的 Trial 配置格式,是 FrameworkController 官方配置的简化版。参考 [frameworkcontroller 的 tensorflow ](https://github.com/Microsoft/frameworkcontroller/blob/master/example/framework/scenario/tensorflow/cpu/tensorflowdistributedtrainingwithcpu.yaml) 了解详情。 FrameworkController 模式的 Trial 配置格式,是 FrameworkController 官方配置的简化版。参考 [frameworkcontroller 的 tensorflow ](https://github.com/Microsoft/frameworkcontroller/blob/master/example/framework/scenario/tensorflow/cpu/tensorflowdistributedtrainingwithcpu.yaml) 了解详情。
frameworkcontroller 模式中的 Trial 配置使用以下主键: frameworkcontroller 模式中的 Trial 配置使用以下主键:
......
# **教程:使用 NNI API 在本地创建和运行 Experiment** # **教程:使用 NNI API 在本地创建和运行 Experiment**
本教程会使用 [~/examples/trials/mnist-tfv1] 例来解释如何在本地使用 NNI API 来创建并运行 Experiment。 本教程会使用 [~/examples/trials/mnist-tfv1] 例来解释如何在本地使用 NNI API 来创建并运行 Experiment。
> 在开始前 > 在开始前
...@@ -78,9 +78,9 @@ ...@@ -78,9 +78,9 @@
**准备 Trial** **准备 Trial**
> 在克隆代码后,可以在 ~/nni/examples 中找到一些例,运行 `ls examples/trials` 查看所有 Trial 例。 > 在克隆代码后,可以在 ~/nni/examples 中找到一些例,运行 `ls examples/trials` 查看所有 Trial 例。
先从 NNI 提供的简单 Trial 例,如 MNIST 开始。 NNI 例在代码目录的 examples 中,运行 `ls ~/nni/examples/trials` 可以看到所有 Experiment 的例。 执行下面的命令可轻松运行 NNI 的 mnist 例: 先从 NNI 提供的简单 Trial 例,如 MNIST 开始。 NNI 例在代码目录的 examples 中,运行 `ls ~/nni/examples/trials` 可以看到所有 Experiment 的例。 执行下面的命令可轻松运行 NNI 的 mnist 例:
python ~/nni/examples/trials/mnist-annotation/mnist.py python ~/nni/examples/trials/mnist-annotation/mnist.py
...@@ -97,7 +97,7 @@ ...@@ -97,7 +97,7 @@
*builtinTunerName* 用来指定 NNI 中的 Tuner,*classArgs* 是传入到 Tuner的参数(内置 Tuner 在[这里](../Tuner/BuiltinTuner.md)),*optimization_mode* 表明需要最大化还是最小化 Trial 的结果。 *builtinTunerName* 用来指定 NNI 中的 Tuner,*classArgs* 是传入到 Tuner的参数(内置 Tuner 在[这里](../Tuner/BuiltinTuner.md)),*optimization_mode* 表明需要最大化还是最小化 Trial 的结果。
**准备配置文件**:实现 Trial 的代码,并选择或实现自定义的 Tuner 后,就要准备 YAML 配置文件了。 NNI 为每个 Trial 例都提供了演示的配置文件,用命令`cat ~/nni/examples/trials/mnist-annotation/config.yml` 来查看其内容。 大致内容如下: **准备配置文件**:实现 Trial 的代码,并选择或实现自定义的 Tuner 后,就要准备 YAML 配置文件了。 NNI 为每个 Trial 例都提供了演示的配置文件,用命令`cat ~/nni/examples/trials/mnist-annotation/config.yml` 来查看其内容。 大致内容如下:
```yaml ```yaml
authorName: your_name authorName: your_name
......
...@@ -36,10 +36,13 @@ trial: ...@@ -36,10 +36,13 @@ trial:
cpuNum: 1 cpuNum: 1
memoryMB: 8196 memoryMB: 8196
image: msranni/nni:latest image: msranni/nni:latest
# 配置访问的 OpenPAI 集群 virtualCluster: default
nniManagerNFSMountPath: /home/user/mnt
containerNFSMountPath: /mnt/data/user
# 配置要访问的 OpenPAI 集群
paiConfig: paiConfig:
userName: your_pai_nni_user userName: your_pai_nni_user
passWord: your_pai_password token: your_pai_token
host: 10.1.1.1 host: 10.1.1.1
``` ```
...@@ -56,56 +59,12 @@ paiConfig: ...@@ -56,56 +59,12 @@ paiConfig:
* [Docker Hub](https://hub.docker.com/) 上有预制的 NNI Docker 映像 [nnimsra/nni](https://hub.docker.com/r/msranni/nni/)。 它包含了用来启动 NNI Experiment 所依赖的所有 Python 包,Node 模块和 JavaScript。 生成此 Docker 映像的文件在[这里](https://github.com/Microsoft/nni/tree/master/deployment/docker/Dockerfile)。 可以直接使用此映像,或参考它来生成自己的映像。 * [Docker Hub](https://hub.docker.com/) 上有预制的 NNI Docker 映像 [nnimsra/nni](https://hub.docker.com/r/msranni/nni/)。 它包含了用来启动 NNI Experiment 所依赖的所有 Python 包,Node 模块和 JavaScript。 生成此 Docker 映像的文件在[这里](https://github.com/Microsoft/nni/tree/master/deployment/docker/Dockerfile)。 可以直接使用此映像,或参考它来生成自己的映像。
* virtualCluster * virtualCluster
* 可选。 设置 OpenPAI 的 virtualCluster,即虚拟集群。 如果未设置此参数,将使用默认(default)虚拟集群。 * 可选。 设置 OpenPAI 的 virtualCluster,即虚拟集群。 如果未设置此参数,将使用默认(default)虚拟集群。
* shmMB * nniManagerNFSMountPath
* 可选。 设置 OpenPAI 的 shmMB,即 Docker 中的共享内存。 * 必填。 在 nniManager 计算机上设置挂载的路径。
* authFile * containerNFSMountPath
* 可选。在使用 pai 模式时,为私有 Docker 仓库设置认证文件,[见参考文档](https://github.com/microsoft/pai/blob/2ea69b45faa018662bc164ed7733f6fdbb4c42b3/docs/faq.md#q-how-to-use-private-docker-registry-job-image-when-submitting-an-openpai-job)。提供 authFile 的本地路径即可, NNI 会上传此文件。 * 必填。 在 OpenPAI 的容器中设置挂载路径。
* paiStoragePlugin
* portList * 必填。 设置 PAI 中使用的存储插件的名称。
* 可选。 设置 OpenPAI 的 portList。指定了容器中使用的端口列表,[参考文档](https://github.com/microsoft/pai/blob/b2324866d0280a2d22958717ea6025740f71b9f0/docs/job_tutorial.md#specification)
示例如下:
portList:
- label: test
beginAt: 8080
portNumber: 2
假设需要在 MNIST 示例中使用端口来运行 TensorBoard。 第一步是编写 `mnist.py` 的包装脚本 `launch_pai.sh`
```bash
export TENSORBOARD_PORT=PAI_PORT_LIST_${PAI_CURRENT_TASK_ROLE_NAME}_0_tensorboard
tensorboard --logdir . --port ${!TENSORBOARD_PORT} &
python3 mnist.py
```
portList 的配置部分如下:
```yaml
trial:
command: bash launch_pai.sh
portList:
- label: tensorboard
beginAt: 0
portNumber: 1
```
NNI 支持 OpenPAI 中的两种认证授权方法,即密码和 Token,[参考](https://github.com/microsoft/pai/blob/b6bd2ab1c8890f91b7ac5859743274d2aa923c22/docs/rest-server/API.md#2-authentication)。 认证在 `paiConfig` 字段中配置。
密码认证的 `paiConfig` 配置如下:
paiConfig:
userName: your_pai_nni_user
passWord: your_pai_password
host: 10.1.1.1
Token 认证的 `paiConfig` 配置如下:
paiConfig:
userName: your_pai_nni_user
token: your_pai_token
host: 10.1.1.1
完成并保存 NNI Experiment 配置文件后(例如可保存为:exp_pai.yml),运行以下命令: 完成并保存 NNI Experiment 配置文件后(例如可保存为:exp_pai.yml),运行以下命令:
...@@ -126,9 +85,7 @@ Token 认证的 `paiConfig` 配置如下: ...@@ -126,9 +85,7 @@ Token 认证的 `paiConfig` 配置如下:
## 数据管理 ## 数据管理
如果训练数据集不大,可放在 codeDir 中,NNI会将其上传到 HDFS,或者构建 Docker 映像来包含数据。 如果数据集非常大,则不可放在 codeDir 中,可参考此[指南](https://github.com/microsoft/pai/blob/master/docs/user/storage.md)来将数据目录挂载到容器中。 使用 NNI 启动 Experiment 前,应在 nniManager 计算机中设置相应的挂载数据的路径。 OpenPAI 有自己的存储(NFS、AzureBlob ...),在 PAI 中使用的存储将在启动作业时挂载到容器中。 应通过 `paiStoragePlugin` 字段选择 OpenPAI 中的存储类型。 然后,应将存储挂载到 nniManager 计算机上,并在配置文件中设置 `nniManagerNFSMountPath`,NNI会生成 bash 文件并将 `codeDir` 中的数据拷贝到 `nniManagerNFSMountPath` 文件夹中,然后启动 Trial 任务。 `nniManagerNFSMountPath` 中的数据会同步到 OpenPAI 存储中,并挂载到 OpenPAI 的容器中。 容器中的数据路径在 `containerNFSMountPath` 设置,NNI 将进入该文件夹,运行脚本启动 Trial 任务。
如果要将 Trial 的其它输出保存到 HDFS 上,如模型文件等,需要在 Trial 代码中使用 `NNI_OUTPUT_DIR` 来保存输出文件。NNI 的 SDK 会将文件从 Trial 容器的 `NNI_OUTPUT_DIR` 复制到 HDFS 上,目标路径为:`hdfs://host:port/{username}/nni/{experiments}/{experimentId}/trials/{trialId}/nnioutput`
## 版本校验 ## 版本校验
......
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