Unverified Commit 91d9a797 authored by Yuge Zhang's avatar Yuge Zhang Committed by GitHub
Browse files

Adopt symbolic links in Chinese documentation (#4345)


Co-authored-by: default avatarjiahangxu <jiahangxu@microsoft.com>
parent 0e0ee86d
"""
This is to keep Chinese doc update to English doc. Should be run regularly.
The files in whitelist will be kept unchanged, as they will be translated manually.
Under docs, run
python tools/chineselink.py
"""
import hashlib
import os
import shutil
import sys
from pathlib import Path
def walk(path):
for p in Path(path).iterdir():
if p.is_dir():
yield from walk(p)
continue
yield p
# Keeps files as discussed in
# https://github.com/microsoft/nni/issues/4298
# Not the recommended way of sphinx though: https://docs.readthedocs.io/en/stable/guides/manage-translations-sphinx.html
whitelist = [
'_templates/index.html', # I think no one ever remembers to update this file. Might need to rethink about this.
'Overview.rst',
'installation.rst',
'Tutorial/InstallationLinux.rst',
'Tutorial/InstallationWin.rst',
'Tutorial/QuickStart.rst',
'TrialExample/Trials.rst',
'Tutorial/WebUI.rst',
'NAS/QuickStart.rst',
'Compression/Overview.rst',
'Compression/QuickStart.rst',
]
for path in whitelist:
assert (Path('zh_CN') / path).exists(), path
content_tables = []
for path in walk(Path('en_US')):
if path.suffix == '.rst':
is_content_table = False
for line in path.open('r').readlines():
if is_content_table:
if not line.startswith(' ') and line.strip():
is_content_table = False
if 'toctree::' in line:
is_content_table = True
if is_content_table:
content_tables.append(path.relative_to('en_US').as_posix())
print('Whitelist:' ,content_tables)
whitelist += content_tables
pipeline_mode = len(sys.argv) > 1 and sys.argv[1] == 'check'
failed_files = []
def need_to_translate(source, target):
if not target.exists():
failed_files.append('(missing) ' + target.as_posix())
if pipeline_mode:
return
shutil.copyfile(source, target)
if target.suffix == '.html':
return # FIXME I don't know how to process html
target_checksum = hashlib.sha256(path.open('rb').read()).hexdigest()[:32]
checksum = target.open('r').readline().strip()[3:]
if checksum != target_checksum:
failed_files.append('(out-of-date) ' + target.as_posix())
if pipeline_mode:
return
contents = target.open('r').readlines()
firstline = '.. ' + target_checksum + '\n'
if contents[0].startswith('.. '):
contents = [firstline] + contents[1:]
else:
contents = [firstline, '\n'] + contents
target.open('w').writelines(contents)
for path in walk(Path('en_US')):
relative_path = path.relative_to('en_US')
if relative_path.as_posix().startswith('_build'):
continue
if path.suffix in ('.html', '.md', '.rst'):
target_path = (Path('zh_CN') / relative_path)
if relative_path.as_posix() in whitelist:
# whitelist files. should be translated
need_to_translate(path, target_path)
print(f'Skipped linking for {path} as it is in whitelist.')
else:
target_path.parent.mkdir(exist_ok=True)
link_path = path
for _ in range(len(list(Path(relative_path).parents))):
link_path = Path('..') / link_path
if not target_path.is_symlink() or os.readlink(target_path) != link_path.as_posix():
failed_files.append('(invalid link) ' + target_path.as_posix())
if not pipeline_mode:
target_path.unlink(missing_ok=True)
target_path.symlink_to(link_path)
# delete redundant files
for path in walk(Path('zh_CN')):
if path.suffix in ('.html', '.md', '.rst'):
relative_path = path.relative_to('zh_CN')
if not (Path('en_US') / relative_path).exists():
failed_files.append('(redundant) ' + path.as_posix())
if not pipeline_mode:
print(f'Deleting {path}')
path.unlink()
if pipeline_mode and failed_files:
raise ValueError(
'The following files are not up-to-date. Please run "python3 tools/chineselink.py" under docs folder '
'to refresh them and update their corresponding translation.\n' + '\n'.join([' ' + line for line in failed_files]))
if failed_files:
print('Updated files:', failed_files)
.. role:: raw-html(raw)
:format: html
内置 Assessor
==================
NNI 提供了先进的评估算法,使用上也很简单。 下面是内置 Assessor 的介绍。
注意:点击 **Assessor 的名称** 可了解每个 Assessor 的安装需求,建议的场景以及示例。在每个 Assessor 建议场景最后,还有算法的详细说明。
当前支持以下 Assessor:
.. list-table::
:header-rows: 1
:widths: auto
* - Assessor
- 算法简介
* - `Medianstop <#MedianStop>`__
- Medianstop 是一个简单的提前终止算法。 如果尝试 X 的在步骤 S 的最好目标值比所有已完成尝试的步骤 S 的中位数值明显低,就会停止运行尝试 X。 `参考论文 <https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/46180.pdf>`__
* - `Curvefitting <#Curvefitting>`__
- 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>`__
用法
--------------------------
要使用 NNI 内置的 Assessor,需要在 ``config.yml`` 文件中添加 **builtinAssessorName** 和 **classArgs**。 这一节会介绍推荐的场景、参数等详细用法以及示例。
注意:参考示例中的格式来创建新的 ``config.yml`` 文件。
:raw-html:`<a name="MedianStop"></a>`
Median Stop Assessor
^^^^^^^^^^^^^^^^^^^^
..
名称:**Medianstop**
**建议场景**
适用于各种性能曲线,可用到各种场景中来加速优化过程。 `详细说明 <./MedianstopAssessor.rst>`__
**classArgs 要求:**
* **optimize_mode** ( *maximize 或 minimize,可选默认值是maximize* )。如果为 'maximize',Assessor 会在结果小于期望值时 **中止** Trial。如果为 'minimize',Assessor 会在结果大于期望值时 **终止** Trial。
* **start_step** ( *int,可选,默认值为 0* )。只有收到 start_step 个中间结果后,才开始判断是否一个 Trial 应该被终止。
**使用示例:**
.. code-block:: yaml
# config.yml
assessor:
builtinAssessorName: Medianstop
classArgs:
optimize_mode: maximize
start_step: 5
:raw-html:`<br>`
:raw-html:`<a name="Curvefitting"></a>`
Curve Fitting Assessor
^^^^^^^^^^^^^^^^^^^^^^
..
名称:**Curvefitting**
**建议场景**
适用于各种性能曲线,可用到各种场景中来加速优化过程。 更好的是,它能够处理并评估性能类似的曲线。 `详细说明 <./CurvefittingAssessor.rst>`__
**注意**,根据原始论文,仅支持递增函数。 因此,此 Assessor 仅可用于最大化优化指标的场景。 例如,它可用于准确度,但不能用于损失值。
**classArgs 要求:**
* **epoch_num** ( *int,必需* ),epoch 的总数。需要此数据来决定需要预测点的总数。
* **start_step** ( *int,可选,默认值为 6* )。只有收到 start_step 个中间结果后,才开始判断是否一个 Trial 应该被终止。
* **threshold** ( *float,可选,默认值为 0.95* ),用来确定提前终止较差结果的阈值。例如,如果 threshold = 0.95,最好的历史结果是 0.9,那么会在 Trial 的预测值低于 0.95 * 0.9 = 0.855 时停止。
* **gap** ( *int,可选,默认值为 1* ),Assessor 两次评估之间的间隔次数。例如:如果 gap = 2, start_step = 6,就会评估第 6, 8, 10, 12... 个中间结果。
**使用示例:**
.. code-block:: yaml
# config.yml
assessor:
builtinAssessorName: Curvefitting
classArgs:
epoch_num: 20
start_step: 6
threshold: 0.95
gap: 1
../../en_US/Assessor/BuiltinAssessor.rst
\ No newline at end of file
NNI 中的 Curve Fitting Assessor
===============================
介绍
------------
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>`__。 学习曲线的形状与先验知识是一致的:都是典型的递增的、饱和的函数。
.. image:: ../../img/curvefitting_learning_curve.PNG
:target: ../../img/curvefitting_learning_curve.PNG
:alt: learning_curve
所有学习曲线模型被合并到了单个,更强大的模型中。 合并的模型通过加权线性混合:
.. image:: ../../img/curvefitting_f_comb.gif
:target: ../../img/curvefitting_f_comb.gif
:alt: f_comb
合并后的新参数向量
.. image:: ../../img/curvefitting_expression_xi.gif
:target: ../../img/curvefitting_expression_xi.gif
:alt: expression_xi
假设增加一个高斯噪声,且噪声参数初始化为最大似然估计。
通过学习历史数据来确定新的组合参数向量的最大概率值。 用这样的方法来预测后面的 Trial 性能,并停止不好的 Trial 来节省计算资源。
具体来说,该算法有学习、预测和评估三个阶段。
*
步骤 1:学习。 从当前 Trial 的历史中学习,并从贝叶斯角度决定 \xi 。 首先,使用由 ``fit_theta`` 实现的最小二乘法。 获得参数后,过滤曲线并移除异常点(由 ``filter_curve`` 实现)。 最后,使用 MCMC 采样方法。 由 ``mcmc_sampling`` 实现,来调整每条曲线的权重。 至此,确定了 \xi 中的所有参数。
*
步骤 2:预测。 用 \xi 和混合模型公式,由 ``f_comb`` 实现了,在目标位置(例如 epoch 的总数)来计算期望的最终结果精度。
*
步骤 3:如果拟合结果不收敛,则预测值将为 ``None``。 在这种情况下,会返回 ``AssessResult.Good`` 来请求进一步的精度和预测信息。 此外,将从 ``predict()`` 函数获得正确值。 如果该值大于历史最好结果 * ``THRESHOLD``(默认为 0.95),则返回 ``AssessResult.Good``,否则返回 ``AssessResult.Bad``。
下图显示了此算法在 MNIST Trial 历史数据上结果。其中绿点表示 Assessor 获得的数据,蓝点表示将来,但未知的数据,红色线条是 Curve fitting Assessor 的预测曲线。
.. image:: ../../img/curvefitting_example.PNG
:target: ../../img/curvefitting_example.PNG
:alt: examples
用法
-----
要使用 Curve Fitting Assessor,需要在 Experiment 的 YAML 配置文件进行如下改动。
.. code-block:: yaml
assessor:
builtinAssessorName: Curvefitting
classArgs:
# (必需)epoch总数
# 需要此数据来决定需要预测的点。
epoch_num: 20
#(可选)为了节约计算资源,仅在收到 start_step 个中间结果后,才开始进行预测。
# start_step 的默认值是 6。
start_step: 6
# (可选)决定是否提前终止的阈值。
# 例如,如果 threshold = 0.95,最好的历史结果是 0.9,那么会在 Trial 的预测值低于 0.95 * 0.9 = 0.855 时停止。
# 阈值的默认值是 0.95。
threshold: 0.95
#(可选)gap 是两次评估之间的间隔次数。
# 例如:如果 gap = 2, start_step = 6,就会评估第 6, 8, 10, 12... 个中间结果。
# gap 的默认值是 1。
gap: 1
局限性
----------
根据原始论文,仅支持递增函数。 因此,此 Assessor 仅可用于最大化优化指标的场景。 例如,它可用于准确度,但不能用于损失值。
文件结构
--------------
Assessor 有大量的文件、函数和类。 在这里,会简要描述其中一部分。
* ``curvefunctions.py`` 包含了所有函数表达式和默认参数。
* ``curvefunctions.py`` 包括学习和预测部分,并实现了相应的计算部分。
* ``curvefitting_assessor.py`` 是接收 Trial 历史数据并评估是否需要提前终止的 Assessor。
TODO
----
* 进一步提高预测精度,并在更多模型上测试。
../../en_US/Assessor/CurvefittingAssessor.rst
\ No newline at end of file
自定义 Assessor
==================
NNI 支持自定义 Assessor。
实现自定义的 Assessor,需要如下几步:
#. 继承 Assessor 基类
#. 实现 assess_trial 函数
#. 在 Experiment 的 YAML 文件中配置好自定义的 Assessor
**1. 继承 Assessor 基类**
.. code-block:: python
from nni.assessor import Assessor
class CustomizedAssessor(Assessor):
def __init__(self, ...):
...
**2. 实现 assess_trial 函数**
.. code-block:: python
from nni.assessor import Assessor, AssessResult
class CustomizedAssessor(Assessor):
def __init__(self, ...):
...
def assess_trial(self, trial_history):
"""
决定 Trial 是否应该被终止。 必须重载。
trial_history: 中间结果列表对象。
返回 AssessResult.Good 或 AssessResult.Bad。
"""
# 你的代码
...
**3. 在 Experiment 的 YAML 文件中配置好自定义的 Assessor**
NNI 需要定位到自定义的 Assessor 类,并实例化它,因此需要指定自定义 Assessor 类的文件位置,并将参数值传给 __init__ 构造函数。
.. code-block:: yaml
assessor:
codeDir: /home/abc/myassessor
classFileName: my_customized_assessor.py
className: CustomizedAssessor
# 所有的参数都需要传递给你 Assessor 的构造函数 __init__
# 例如,可以在可选的 classArgs 字段中指定
classArgs:
arg1: value1
注意 **2** 中: 对象 ``trial_history`` 和 ``report_intermediate_result`` 函数返回给 Assessor 的完全一致。
Assessor 的工作目录是 ``<home>/nni-experiments/<experiment_id>/log``\ ,可从环境变量 ``NNI_LOG_DIRECTORY``\ 中获取。
更多示例,可参考:
* :githublink:`medianstop-assessor <nni/algorithms/hpo/medianstop_assessor.py>`
* :githublink:`curvefitting-assessor <nni/algorithms/hpo/curvefitting_assessor/>`
../../en_US/Assessor/CustomizeAssessor.rst
\ No newline at end of file
Medianstop Assessor
==========================
Median Stop
-----------
Medianstop 是一种简单的提前终止策略,可参考 `论文 <https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/46180.pdf>`__。 如果 Trial X 在步骤 S 的最好目标值低于所有已完成 Trial 前 S 个步骤目标平均值的中位数,这个 Trial 就会被提前停止。
../../en_US/Assessor/MedianstopAssessor.rst
\ No newline at end of file
自动补全 nnictl 命令
===================================
NNI的命令行工具 **nnictl** 支持自动补全,也就是说,您可以通过按 ``tab`` 键来完成 nnictl 命令。
例如当前命令是
.. code-block:: bash
nnictl cre
按下 ``tab`` 键,它可以被自动补全成:
.. code-block:: bash
nnictl create
目前,如果您通过 ``pip`` 安装 NNI ,默认情况下不会启用自动补全,并且它只在bash shell 的 Linux 上工作。 如果要启用此功能,请参阅以下步骤:
步骤 1. 下载 ``bash-completion``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: bash
cd ~
wget https://raw.githubusercontent.com/microsoft/nni/{nni-version}/tools/bash-completion
{nni-version} 应该填充 NNI 的版本,例如 ``master``\ , ``v2.3``。 你也可以 :githublink:`在这里 <tools/bash-completion>` 查看最新的 ``bash-completion`` 脚本。
.. cannot find :githublink:`here <tools/bash-completion>`.
步骤 2. 安装脚本
^^^^^^^^^^^^^^^^^^^^^^^^^^
如果您运行的是 root 帐户并希望为所有用户安装此脚本
.. code-block:: bash
install -m644 ~/bash-completion /usr/share/bash-completion/completions/nnictl
如果您只是想自己安装这个脚本
.. code-block:: bash
mkdir -p ~/.bash_completion.d
install -m644 ~/bash-completion ~/.bash_completion.d/nnictl
echo '[[ -f ~/.bash_completion.d/nnictl ]] && source ~/.bash_completion.d/nnictl' >> ~/.bash_completion
步骤 3. 重启终端
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
重新打开终端,您应该能够使用自动补全功能。 享受它吧!
步骤 4. 卸载
^^^^^^^^^^^^^^^^^
如果要卸载此功能,只需还原上述步骤中的更改。
超参数优化的对比
=======================================
*匿名作者*
超参优化算法(HPO)在几个问题上的对比。
超参数优化算法如下:
* `Random Search(随机搜索) <../Tuner/BuiltinTuner.rst>`__
* `Grid Search(网格搜索) <../Tuner/BuiltinTuner.rst>`__
* `Evolution <../Tuner/BuiltinTuner.rst>`__
* `Anneal <../Tuner/BuiltinTuner.rst>`__
* `Metis <../Tuner/BuiltinTuner.rst>`__
* `TPE <../Tuner/BuiltinTuner.rst>`__
* `SMAC <../Tuner/BuiltinTuner.rst>`__
* `HyperBand <../Tuner/BuiltinTuner.rst>`__
* `BOHB <../Tuner/BuiltinTuner.rst>`__
所有算法都在 NNI 本机环境下运行。
环境:
.. code-block:: bash
OS: Linux Ubuntu 16.04 LTS
CPU: Intel(R) Xeon(R) CPU E5-2690 v3 @ 2.60GHz 2600 MHz
Memory: 112 GB
NNI Version: v0.7
NNI Mode(local|pai|remote): local
Python version: 3.6
Is conda or virtualenv used?: Conda
is running in docker?: no
AutoGBDT 示例
----------------
问题描述
^^^^^^^^^^^^^^^^^^^
超参搜索上的非凸问题 `AutoGBDT <../TrialExample/GbdtExample.rst>`__ 示例。
搜索空间
^^^^^^^^^^^^
.. code-block:: json
{
"num_leaves": {
"_type": "choice",
"_value": [10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 48, 64, 96, 128]
},
"learning_rate": {
"_type": "choice",
"_value": [0.00001, 0.0001, 0.001, 0.01, 0.05, 0.1, 0.2, 0.5]
},
"max_depth": {
"_type": "choice",
"_value": [-1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 48, 64, 96, 128]
},
"feature_fraction": {
"_type": "choice",
"_value": [0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2]
},
"bagging_fraction": {
"_type": "choice",
"_value": [0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2]
},
"bagging_freq": {
"_type": "choice",
"_value": [1, 2, 4, 8, 10, 12, 14, 16]
}
}
总搜索空间为 1, 204, 224 次,将最大 Trial 次数设置为 1000。 时间限制为 48 小时。
结果
^^^^^^^
.. list-table::
:header-rows: 1
:widths: auto
* - 算法
- 最好的损失值
- 最好的 5 次损失的平均值
- 最好的 10 次损失的平均值
* - Random Search
- 0.418854
- 0.420352
- 0.421553
* - Random Search
- 0.417364
- 0.420024
- 0.420997
* - Random Search
- 0.417861
- 0.419744
- 0.420642
* - Grid Search
- 0.498166
- 0.498166
- 0.498166
* - Evolution
- 0.409887
- 0.409887
- 0.409887
* - Evolution
- 0.413620
- 0.413875
- 0.414067
* - Evolution
- 0.409887
- 0.409887
- 0.409887
* - Anneal
- 0.414877
- 0.417289
- 0.418281
* - Anneal
- 0.409887
- 0.409887
- 0.410118
* - Anneal
- 0.413683
- 0.416949
- 0.417537
* - Metis
- 0.416273
- 0.420411
- 0.422380
* - Metis
- 0.420262
- 0.423175
- 0.424816
* - Metis
- 0.421027
- 0.424172
- 0.425714
* - TPE
- 0.414478
- 0.414478
- 0.414478
* - TPE
- 0.415077
- 0.417986
- 0.418797
* - TPE
- 0.415077
- 0.417009
- 0.418053
* - SMAC
- **0.408386**
- **0.408386**
- **0.408386**
* - SMAC
- 0.414012
- 0.414012
- 0.414012
* - SMAC
- **0.408386**
- **0.408386**
- **0.408386**
* - BOHB
- 0.410464
- 0.415319
- 0.417755
* - BOHB
- 0.418995
- 0.420268
- 0.422604
* - BOHB
- 0.415149
- 0.418072
- 0.418932
* - HyperBand
- 0.414065
- 0.415222
- 0.417628
* - HyperBand
- 0.416807
- 0.417549
- 0.418828
* - HyperBand
- 0.415550
- 0.415977
- 0.417186
* - GP
- 0.414353
- 0.418563
- 0.420263
* - GP
- 0.414395
- 0.418006
- 0.420431
* - GP
- 0.412943
- 0.416566
- 0.418443
此例中,所有算法都使用了默认参数。 Metis 算法因为其高斯计算过程的复杂度为 O(n^3) 而运行非常慢,因此仅执行了 300 次 Trial。
RocksDB 的 'fillrandom' 和 'readrandom' 基准测试
-----------------------------------------------------------
问题描述
^^^^^^^^^^^^^^^^^^^
`DB_Bench <https://github.com/facebook/rocksdb/wiki/Benchmarking-tools>`__ 是用来做 `RocksDB <https://rocksdb.org/>`__ 性能基准测试的工具。 有多个参数需要调优。
``DB_Bench`` 的性能与计算机配置和安装方法有关。 在 ``DB_Bench`` Linux 系统上运行,并将 Rock 作为共享库安装。
计算机配置
^^^^^^^^^^^^^^^^^^^^^
.. code-block:: bash
RocksDB: version 6.1
CPU: 6 * Intel(R) Xeon(R) CPU E5-2690 v4 @ 2.60GHz
CPUCache: 35840 KB
Keys: 16 bytes each
Values: 100 bytes each (50 bytes after compression)
Entries: 1000000
存储性能
^^^^^^^^^^^^^^^^^^^
**延迟** :每个 IO 请求都需要一些时间才能完成,这称为平均延迟。 有几个因素会影响此时间,包括网络连接质量和硬盘IO性能。
**IOPS**: **每秒的 IO 操作数量**,这意味着可以在一秒钟内完成的 *读取或写入操作次数*。
**IO 大小**: **每个 IO 请求的大小**。 根据操作系统和需要磁盘访问的应用程序、服务,它将同时发出读取或写入一定数量数据的请求。
**吞吐量(以 MB/s 为单位)= 平均 IO 大小 x IOPS**
IOPS 与在线处理能力有关,我们在实验中使用 IOPS 作为指标。
搜索空间
^^^^^^^^^^^^
.. code-block:: json
{
"max_background_compactions": {
"_type": "quniform",
"_value": [1, 256, 1]
},
"block_size": {
"_type": "quniform",
"_value": [1, 500000, 1]
},
"write_buffer_size": {
"_type": "quniform",
"_value": [1, 130000000, 1]
},
"max_write_buffer_number": {
"_type": "quniform",
"_value": [1, 128, 1]
},
"min_write_buffer_number_to_merge": {
"_type": "quniform",
"_value": [1, 32, 1]
},
"level0_file_num_compaction_trigger": {
"_type": "quniform",
"_value": [1, 256, 1]
},
"level0_slowdown_writes_trigger": {
"_type": "quniform",
"_value": [1, 1024, 1]
},
"level0_stop_writes_trigger": {
"_type": "quniform",
"_value": [1, 1024, 1]
},
"cache_size": {
"_type": "quniform",
"_value": [1, 30000000, 1]
},
"compaction_readahead_size": {
"_type": "quniform",
"_value": [1, 30000000, 1]
},
"new_table_reader_for_compaction_inputs": {
"_type": "randint",
"_value": [1]
}
}
搜索空间非常大(约10 的 40 次方),将最大 Trial 次数设置为 100 以限制资源。
结果
^^^^^^^
fillrandom 基准
^^^^^^^^^^^^^^^^^^^^^
.. list-table::
:header-rows: 1
:widths: auto
* - 模型
- 最高 IOPS(重复 1 次)
- 最高 IOPS(重复 2 次)
- 最高 IOPS(重复 3 次)
* - Random
- 449901
- 427620
- 477174
* - Anneal
- 461896
- 467150
- 437528
* - Evolution
- 436755
- 389956
- 389790
* - TPE
- 378346
- 482316
- 468989
* - SMAC
- 491067
- 490472
- **491136**
* - Metis
- 444920
- 457060
- 454438
图:
.. image:: ../../img/hpo_rocksdb_fillrandom.png
:target: ../../img/hpo_rocksdb_fillrandom.png
:alt:
readrandom 基准
^^^^^^^^^^^^^^^^^^^^^^
.. list-table::
:header-rows: 1
:widths: auto
* - 模型
- 最高 IOPS(重复 1 次)
- 最高 IOPS(重复 2 次)
- 最高 IOPS(重复 3 次)
* - Random
- 2276157
- 2285301
- 2275142
* - Anneal
- 2286330
- 2282229
- 2284012
* - Evolution
- 2286524
- 2283673
- 2283558
* - TPE
- 2287366
- 2282865
- 2281891
* - SMAC
- 2270874
- 2284904
- 2282266
* - Metis
- **2287696**
- 2283496
- 2277701
图:
.. image:: ../../img/hpo_rocksdb_readrandom.png
:target: ../../img/hpo_rocksdb_readrandom.png
:alt:
../../en_US/CommunitySharings/HpoComparison.rst
\ No newline at end of file
滤波器剪枝算法比较
=======================================
为了初步了解各种滤波器剪枝算法的性能,
NNI 在一些基准模型和数据集上使用各种剪枝算法进行了广泛的实验。
此文档中展示了实验结果。
此外,还对这些实验的复现提供了友好的说明,以促进对这项工作的进一步贡献。
实验设置
------------------
实验使用以下剪枝器/数据集/模型进行:
*
模型: :githublink:`VGG16, ResNet18, ResNet50 <examples/model_compress/models/cifar10>`
*
数据集:CIFAR-10
*
剪枝器:
* 剪枝器包括:
迭代式剪枝器 : ``SimulatedAnnealing Pruner``\ , ``NetAdapt Pruner``\ , ``AutoCompress Pruner``。
给定总体稀疏度要求,这类剪枝器可以在不同层中自动分配稀疏度。
单轮剪枝器:``L1Filter Pruner``\ , ``L2Filter Pruner``\ , ``FPGM Pruner``。
每层的稀疏度与实验设置的总体稀疏度相同。
*
这里只比较 **filter pruning** 的剪枝效果。
对于迭代式剪枝器,使用 ``L1Filter Pruner`` 作为基础算法。 也就是说, 在迭代式剪枝器决定了稀疏度分布之后,使用 ``L1Filter Pruner`` 进行真正的剪枝。
*
上面列出来的所有的剪枝器都已经在 :githublink:`nni <docs/zh_CN/Compression/Overview.rst>` 中实现。
实验结果
-----------------
对于每一个数据集/模型/剪枝器的组合,设置不同的目标稀疏度对模型进行剪枝。
这里展示了 **权重数量 - 性能** 曲线,还展示了 **FLOPs - 性能** 曲线。
同时在图上画出论文 `AutoCompress: An Automatic DNN Structured Pruning Framework for Ultra-High Compression Rates <http://arxiv.org/abs/1907.03141>`__ 中对 VGG16 和 ResNet18 在 CIFAR-10 上的剪枝结果作为对比。
实验结果如下图所示:
CIFAR-10, VGG16:
.. image:: ../../../examples/model_compress/pruning/comparison_of_pruners/img/performance_comparison_vgg16.png
:target: ../../../examples/model_compress/pruning/comparison_of_pruners/img/performance_comparison_vgg16.png
:alt:
CIFAR-10, ResNet18:
.. image:: ../../../examples/model_compress/pruning/comparison_of_pruners/img/performance_comparison_resnet18.png
:target: ../../../examples/model_compress/pruning/comparison_of_pruners/img/performance_comparison_resnet18.png
:alt:
CIFAR-10, ResNet50:
.. image:: ../../../examples/model_compress/pruning/comparison_of_pruners/img/performance_comparison_resnet50.png
:target: ../../../examples/model_compress/pruning/comparison_of_pruners/img/performance_comparison_resnet50.png
:alt:
分析
--------
从实验结果中,得到以下结论:
* 如果稀疏度是通过限制参数量,那么迭代式剪枝器 ( ``AutoCompress Pruner`` , ``SimualatedAnnealing Pruner`` ) 比单轮剪枝器表现好。 但是在以 FLOPs 稀疏度为标准的情况下,它们相比于单轮剪枝器就没有了优势,因为当前的这些剪枝算法都是根据参数稀疏度来剪枝的。
* 在上述实验中,简单的单轮剪枝器 ``L1Filter Pruner`` , ``L2Filter Pruner`` , ``FPGM Pruner`` 表现比较相近。
* ``NetAdapt Pruner`` 无法达到比较高的压缩率。 因为它的机制是一次迭代只剪枝一层。 这就导致如果每次迭代剪掉的稀疏度远小于指定的总的稀疏度的话,会导致不可接受的剪枝复杂度。
实验复现
------------------------
实现细节
^^^^^^^^^^^^^^^^^^^^^^
*
实验结果都是在 NNI 中使用剪枝器的默认配置收集的,这意味着当我们在 NNI 中调用一个剪枝器类时,我们不会更改任何默认的类参数。
*
FLOPs 和 参数数量均通过 :githublink:`模型 FLOPs 和参数量计数器 <docs/zh_CN/Compression/CompressionUtils.md#model-flopsparameters-counter>` 在 :githublink:`模型加速 <docs/zh_CN/Compression/ModelSpeedup.rst>` 后计算。
这避免了依据掩码模型计算的潜在问题。
*
实验代码在 :githublink:`这里 <examples/model_compress/auto_pruners_torch.py>`。
实验结果展示
^^^^^^^^^^^^^^^^^^^^^^^^^^^
*
如果遵循 :githublink:`示例 <examples/model_compress/auto_pruners_torch.py>`\ 的做法,对于每一次剪枝实验,实验结果将以JSON格式保存如下:
.. code-block:: json
{
"performance": {"original": 0.9298, "pruned": 0.1, "speedup": 0.1, "finetuned": 0.7746},
"params": {"original": 14987722.0, "speedup": 167089.0},
"flops": {"original": 314018314.0, "speedup": 38589922.0}
}
*
实验代码在 :githublink:`这里 <examples/model_compress/comparison_of_pruners>`.
可以参考 :githublink:`分析 <examples/model_compress/comparison_of_pruners/analyze.py>` 来绘制新的性能比较图。
贡献
------------
待办事项
^^^^^^^^^^
* 有 FLOPS/延迟 限制的剪枝器
* 更多剪枝算法/数据集/模型
问题
^^^^^^
关于算法实现及实验问题,请 `发起 issue <https://github.com/microsoft/nni/issues/new/>`__。
../../en_US/CommunitySharings/ModelCompressionComparison.rst
\ No newline at end of file
.. role:: raw-html(raw)
:format: html
来自知乎的评论::raw-html:`<an open source project with highly reasonable design>` - 作者 Garvin Li
========================================================================================================================
本文由 NNI 用户在知乎论坛上发表。 在这篇文章中,Garvin 分享了在使用 NNI 进行自动特征工程方面的体验。 我们认为本文对于有兴趣使用 NNI 进行特征工程的用户非常有用。 经作者许可,将原始文章摘编如下。
**原文(source)**\ : `如何看待微软最新发布的AutoML平台NNI?By Garvin Li <https://www.zhihu.com/question/297982959/answer/964961829?utm_source=wechat_session&utm_medium=social&utm_oi=28812108627968&from=singlemessage&isappinstalled=0>`__
01 AutoML概述
---------------------
作者认为 AutoML 不光是调参,
也可以针对机器学习过程不同阶段,
包括特征工程、神经网络架构搜索等。
02 NNI 概述
------------------
NNI (Neural Network Intelligence) 是一个微软开源的自动机器学习工具包。
通过自动而有效的方法来帮助用户设计并调优机器学习模型,神经网络架构,
或复杂系统的参数
:`https://github.com/Microsoft/nni <https://github.com/Microsoft/nni>`__
总体看微软的工具都有一个比较大的特点,
技术可能不一定多新颖,但是设计都非常赞。
NNI 的 AutoFeatureENG 基本包含了用户对于 AutoFeatureENG 的一切幻想。
底层的框架的设计都极为合理。
03 细说NNI - AutoFeatureENG
--------------------------------
..
本文使用了此项目: `https://github.com/SpongebBob/tabular_automl_NNI <https://github.com/SpongebBob/tabular_automl_NNI>`__。
新用户可以使用 NNI 轻松高效地进行 AutoFeatureENG。 使用是非常简单的,安装下文件中的 require,然后 pip install NNI。
.. image:: https://pic3.zhimg.com/v2-8886eea730cad25f5ac06ef1897cd7e4_r.jpg
:target: https://pic3.zhimg.com/v2-8886eea730cad25f5ac06ef1897cd7e4_r.jpg
:alt:
NNI把 AutoFeatureENG 拆分成 exploration 和 selection 两个模块。 exploration 主要是特征衍生和交叉,selection 讲的是如何做特征筛选。
04 特征 Exploration
----------------------
对于功能派生,NNI 提供了许多可自动生成新功能的操作,`列表如下 <https://github.com/SpongebBob/tabular_automl_NNI/blob/master/AutoFEOp.md>`__ :
**count**:传统的统计,统计一些数据的出现频率
**target**:特征和目标列的一些映射特征
**embedding**:把特征看成句子,用 *word2vector* 的方式制作向量
**crosscount**:特征间除法,有点类似CTR
**aggregete**:特征的 min/max/var/mean
**nunique**:统计唯一特征的数量。
**histsta**:特征存储桶的统计信息,如直方图统计信息。
具体特征怎么交叉,哪一列和哪一列交叉,每一列特征用什么方式衍生呢?可以通过 **search_space. json** 这个文件控制。
.. image:: https://pic1.zhimg.com/v2-3c3eeec6eea9821e067412725e5d2317_r.jpg
:target: https://pic1.zhimg.com/v2-3c3eeec6eea9821e067412725e5d2317_r.jpg
:alt:
图片展示了定义搜索空间的过程。 NNI 为 1 阶运算提供计数编码,并为 2 阶运算提供聚合的统计(min max var mean median nunique)。
例如,希望以下列方式搜索列名称 {"C1"、"...","C26"} 上的频率编码(valuecount)功能的功能:
.. image:: https://github.com/JSong-Jia/Pic/blob/master/images/pic%203.jpg
:target: https://github.com/JSong-Jia/Pic/blob/master/images/pic%203.jpg
:alt:
可以在列 {"C1",...,"C26"} x {"C1",...,"C26"} 上定义交叉频率编码(交叉维度的值计数)方法:
.. image:: https://github.com/JSong-Jia/Pic/blob/master/images/pic%204.jpg
:target: https://github.com/JSong-Jia/Pic/blob/master/images/pic%204.jpg
:alt:
Exploration 的目的就是长生出新的特征。 在代码里可以用 **get_next_parameter** 的方式获取 tuning 的参数:
..
RECEIVED_PARAMS = nni.get_next_parameter()
05 特征 Selection
--------------------
为了避免特征泛滥的情况,避免过拟合,一定要有 Selection 的机制挑选特征。 在 NNI-AutoFeatureENG 的 Selection 中,主要使用了微软开发的梯度提升框架 LightGBM(Light Gradient Boosting Machine)。
.. image:: https://pic2.zhimg.com/v2-7bf9c6ae1303692101a911def478a172_r.jpg
:target: https://pic2.zhimg.com/v2-7bf9c6ae1303692101a911def478a172_r.jpg
:alt:
了解 xgboost 或者 GBDT 算法同学应该知道,这种树形结构的算法是很容易计算出每个特征对于结果的影响的。 所以使用 lightGBM 可以天然的进行特征筛选。
弊病就是,如果下游是个 *LR* (逻辑回归)这种线性算法,筛选出来的特征可能不具备普适性。
.. image:: https://pic4.zhimg.com/v2-d2f919497b0ed937acad0577f7a8df83_r.jpg
:target: https://pic4.zhimg.com/v2-d2f919497b0ed937acad0577f7a8df83_r.jpg
:alt:
06 总结
----------
NNI 的 AutoFeature 模块是给整个行业制定了一个教科书般的标准,告诉大家这个东西要怎么做,有哪些模块,使用起来非常方便。 但是如果只是基于这样简单的模式,不一定能达到很好的效果。
对 NNI 的建议
------------------
我觉得在Exploration方面可以引用一些 DNN(如:xDeepFM) 的特征组合方式,提取更高维度的特征。
在 Selection 方面可以有更多的智能化方案,比如可以基于下游的算法自动选择 Selection 机制。
总之 NNI 在设计曾给了我一些启发,还是一个挺好的开源项目,推荐给大家~ 建议 AI 研究人员使用它来加速研究。
大家用的时候如果是 Mac 电脑可能会遇到 gcc 的问题,因为开源项目自带的脚本是基于 gcc7 编译的, 可以用下面的方法绕过去:
.. code-block:: bash
brew install libomp
../../en_US/CommunitySharings/NNI_AutoFeatureEng.rst
\ No newline at end of file
在 Google Colab 上使用 NNI
===============================
在 Google Colab 上轻松使用 NNI。 Colab 没有暴露它的公网 IP 及端口,因此默认情况下无法在 Colab 中访问 NNI 的 Web 界面。 为解决此问题,需要使用反向代理软件,例如 ``ngrok`` 或 ``frp``。 此教程将展示如何使用 ngrok 在 Colab 上访问 NNI 的Web 界面。
如何在 Google Colab 上打开 NNI 的 Web 界面
--------------------------------------------------
#. 安装需要的包和软件。
.. code-block:: bash
! pip install nni # install nni
! wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip # download ngrok and unzip it
! unzip ngrok-stable-linux-amd64.zip
! mkdir -p nni_repo
! git clone https://github.com/microsoft/nni.git nni_repo/nni # clone NNI's offical repo to get examples
#. 在 `here <https://ngrok.com/>`__ 注册 ngrok 账号,然后通过 authtoken 来连接。
.. code-block:: bash
! ./ngrok authtoken <your-authtoken>
#. 在大于 1024 的端口号上启动 NNI 样例,之后在相同端口上启动 ngrok。 如果希望使用 GPU,确保 config.yml 中 gpuNum >= 1 。 因为使用 ``ngrok http 5000 &`` 会停止响应,所以要使用 ``get_ipython()`` 来启动 ngrok。
.. code-block:: bash
! nnictl create --config nni_repo/nni/examples/trials/mnist-pytorch/config.yml --port 5000 &
get_ipython().system_raw('./ngrok http 5000 &')
#. 查看公网 url 。
.. code-block:: bash
! curl -s http://localhost:4040/api/tunnels # don't change the port number 4040
在步骤 4 后将会看到类似 http://xxxx.ngrok.io 的 url,打开此url即可看到 NNI 的Web 界面。 玩得开心 :)
使用 frp 访问 Web 界面
----------------------
frp 是另一款提供了相似功能的反向代理软件。 但 frp 不提供免费的公网 url,因此可能需要一台拥有公网 IP 的服务器来作为 frp 的服务器端。 参考 `这里 <https://github.com/fatedier/frp>`__ 来了解如何部署 frp。
../../en_US/CommunitySharings/NNI_colab_support.rst
\ No newline at end of file
神经网络结构搜索的对比
=====================================
*匿名作者*
训练和比较 NAS(神经网络架构搜索)的模型,包括 Autokeras,DARTS,ENAS 和 NAO。
源码链接如下:
*
Autokeras: `https://github.com/jhfjhfj1/autokeras <https://github.com/jhfjhfj1/autokeras>`__
*
DARTS: `https://github.com/quark0/darts <https://github.com/quark0/darts>`__
*
ENAS: `https://github.com/melodyguan/enas <https://github.com/melodyguan/enas>`__
*
NAO: `https://github.com/renqianluo/NAO <https://github.com/renqianluo/NAO>`__
实验说明
----------------------
为了避免算法仅仅在 **CIFAR-10** 数据集上过拟合,还对比了包括 Fashion-MNIST, CIFAR-100, OUI-Adience-Age, ImageNet-10-1 (ImageNet的子集) 和 ImageNet-10-2 (ImageNet 的另一个子集) 在内的其它 5 个数据集。 分别从 ImageNet 中抽取 10 种不同类别标签的子集,组成 ImageNet10-1 和 ImageNet10-2 数据集 。
.. list-table::
:header-rows: 1
:widths: auto
* - 数据集
- 训练数据集大小
- 类别标签数
- 数据集说明
* - `Fashion-MNIST <https://github.com/zalandoresearch/fashion-mnist>`__
- 60,000
- 10
- T恤上衣,裤子,套头衫,连衣裙,外套,凉鞋,衬衫,运动鞋,包和踝靴。
* - `CIFAR-10 <https://www.cs.toronto.edu/~kriz/cifar.html>`__
- 50,000
- 10
- 飞机,汽车,鸟类,猫,鹿,狗,青蛙,马,船和卡车。
* - `CIFAR-100 <https://www.cs.toronto.edu/~kriz/cifar.html>`__
- 50,000
- 100
- 和 CIFAR-10 类似,但总共有 100 个类,每个类有 600 张图。
* - `OUI-Adience-Age <https://talhassner.github.io/home/projects/Adience/Adience-data.html>`__
- 26,580
- 8
- 8 个年龄组类别 (0-2, 4-6, 8-13, 15-20, 25-32, 38-43, 48-53, 60-)。
* - `ImageNet-10-1 <http://www.image-net.org/>`__
- 9,750
- 10
- 咖啡杯、电脑键盘、餐桌、衣柜、割草机、麦克风、秋千、缝纫机、里程表和燃气泵。
* - `ImageNet-10-2 <http://www.image-net.org/>`__
- 9,750
- 10
- 鼓,班吉,口哨,三角钢琴,小提琴,管风琴,原声吉他,长号,长笛和萨克斯。
没有改变源码中的 Fine-tuning 方法。 为了匹配每个任务,改变了源码中模型的输入图片大小和输出类别数目的部分。
所有 NAS 方法模型搜索时间和重训练时间都是 **两天**。 所有结果都是基于 **三次重复实验**。 评估计算机有一块 Nvidia Tesla P100 GPU、112GB 内存和 2.60GHz CPU (Intel E5-2690)。
NAO 需要太多的计算资源,因此只使用提供 Pipeline 脚本的 NAO-WS。
对于 AutoKeras,使用了 0.2.18 版本的代码, 因为这是开始实验时的最新版本。
NAS 结果对比
---------------
.. list-table::
:header-rows: 1
:widths: auto
* - NAS
- AutoKeras (%)
- ENAS (macro) (%)
- ENAS (micro) (%)
- DARTS (%)
- NAO-WS (%)
* - Fashion-MNIST
- 91.84
- 95.44
- 95.53
- **95.74**
- 95.20
* - CIFAR-10
- 75.78
- 95.68
- **96.16**
- 94.23
- 95.64
* - CIFAR-100
- 43.61
- 78.13
- 78.84
- **79.74**
- 75.75
* - OUI-Adience-Age
- 63.20
- **80.34**
- 78.55
- 76.83
- 72.96
* - ImageNet-10-1
- 61.80
- 77.07
- 79.80
- **80.48**
- 77.20
* - ImageNet-10-2
- 37.20
- 58.13
- 56.47
- 60.53
- **61.20**
很遗憾,我们无法复现论文中所有的结果。
论文中提供的最佳或平均结果:
.. list-table::
:header-rows: 1
:widths: auto
* - NAS
- AutoKeras(%)
- ENAS (macro) (%)
- ENAS (micro) (%)
- DARTS (%)
- NAO-WS (%)
* - CIFAR- 10
- 88.56(best)
- 96.13(best)
- 97.11(best)
- 97.17(average)
- 96.47(best)
AutoKeras,由于其算法中的随机因素,它在所有数据集中的表现相对较差。
对于 ENAS,ENAS(macro)在 OUI-Adience-Age 数据集中表现较好,并且 ENAS(micro)在 CIFAR-10 数据集中表现较好。
对于 DARTS,在某些数据集上具有良好的结果,但在某些数据集中具有比较大的方差。 DARTS 三次实验中的差异在 OUI-Audience-Age 数据集上可达 5.37%(绝对值),在 ImageNet-10-1 数据集上可达4.36%(绝对值)。
NAO-WS 在 ImageNet-10-2 中表现良好,但在 OUI-Adience-Age 中表现非常差。
参考
---------
#.
Jin, Haifeng, Qingquan Song, and Xia Hu. "Efficient neural architecture search with network morphism." *arXiv preprint arXiv:1806.10282* (2018).
#.
Liu, Hanxiao, Karen Simonyan, and Yiming Yang. "Darts: Differentiable architecture search." arXiv preprint arXiv:1806.09055 (2018).
#.
Pham, Hieu, et al. "Efficient Neural Architecture Search via Parameters Sharing." international conference on machine learning (2018): 4092-4101.
#.
Luo, Renqian, et al. "Neural Architecture Optimization." neural information processing systems (2018): 7827-7838.
../../en_US/CommunitySharings/NasComparison.rst
\ No newline at end of file
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