Unverified Commit cd3a912a authored by SparkSnail's avatar SparkSnail Committed by GitHub
Browse files

Merge pull request #218 from microsoft/master

merge master
parents a0846f2a e9cba778
# 特征工程
我们很高兴的宣布,基于 NNI 的特征工程工具发布了 Alpha 版本。该版本仍处于试验阶段,根据使用反馈会进行改进。 诚挚邀请您使用、反馈,或更多贡献。
当前支持以下特征选择器:
- [GradientFeatureSelector](./GradientFeatureSelector.md)
- [GBDTSelector](./GBDTSelector.md)
# 如何使用
```python
from nni.feature_engineering.gradient_selector import GradientFeatureSelector
# from nni.feature_engineering.gbdt_selector import GBDTSelector
# 读取数据
...
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)
# 初始化 Selector
fgs = GradientFeatureSelector(...)
# 拟合数据
fgs.fit(X_train, y_train)
# 获取重要的特征
# 此处会返回重要特征的索引。
print(fgs.get_selected_features(...))
...
```
使用内置 Selector 时,需要 `import` 对应的特征选择器,并 `initialize`。 可在 Selector 中调用 `fit` 函数来传入数据。 之后,可通过 `get_seleteced_features` 来获得重要的特征。 不同 Selector 的函数参数可能不同,在使用前需要先检查文档。
# 如何定制
NNI 内置了_最先进的_特征工程算法的 Selector。 NNI 也支持定制自己的特征 Selector。
如果要实现定制的特征 Selector,需要:
1. 继承基类 FeatureSelector
1. 实现 _fit_ 和 _get_selected_features_ 函数
1. 与 sklearn 集成 (可选)
示例如下:
**1. 继承基类 FeatureSelector**
```python
from nni.feature_engineering.feature_selector import FeatureSelector
class CustomizedSelector(FeatureSelector):
def __init__(self, ...):
...
```
**2. 实现 _fit_ 和 _get_selected_features_ 函数**
```python
from nni.tuner import Tuner
from nni.feature_engineering.feature_selector import FeatureSelector
class CustomizedSelector(FeatureSelector):
def __init__(self, ...):
...
def fit(self, X, y, **kwargs):
"""
将数据拟合到 FeatureSelector
参数
------------
X : numpy 矩阵
训练输入样本,形状为 [n_samples, n_features]。
y: numpy 矩阵
目标值 (分类中的类标签,回归中为实数)。 形状是 [n_samples]。
"""
self.X = X
self.y = y
...
def get_selected_features(self):
"""
获取重要特征
Returns
-------
list :
返回重要特征的索引。
"""
...
return self.selected_features_
...
```
**3. 与 sklearn 集成**
`sklearn.pipeline.Pipeline` 可将模型连接在一起,例如特征选择,规范化,以及分类、回归,来组成一个典型的机器学习问题工作流。 下列步骤可帮助集成 sklearn,将定制的特征 Selector 作为管道的模块。
1. 继承类 _sklearn.base.BaseEstimator_
1. 实现 _BaseEstimator_ 中的 _get_params_ 和 _set_params_ 函数
1. 继承类 _sklearn.feature_selection.base.SelectorMixin_
1. 实现 _SelectorMixin_ 中的 _get_support_, _transform_ 和 _inverse_transform_ 函数
示例如下:
**1. 继承类 BaseEstimator 及其函数**
```python
from sklearn.base import BaseEstimator
from nni.feature_engineering.feature_selector import FeatureSelector
class CustomizedSelector(FeatureSelector, BaseEstimator):
def __init__(self, ...):
...
def get_params(self, ...):
"""
为此 estimator 获取参数
"""
params = self.__dict__
params = {key: val for (key, val) in params.items()
if not key.endswith('_')}
return params
def set_params(self, **params):
"""
为此 estimator 设置参数
"""
for param in params:
if hasattr(self, param):
setattr(self, param, params[param])
return self
```
**2. 继承 SelectorMixin 类及其函数**
```python
from sklearn.base import BaseEstimator
from sklearn.feature_selection.base import SelectorMixin
from nni.feature_engineering.feature_selector import FeatureSelector
class CustomizedSelector(FeatureSelector, BaseEstimator):
def __init__(self, ...):
...
def get_params(self, ...):
"""
获取参数。
"""
params = self.__dict__
params = {key: val for (key, val) in params.items()
if not key.endswith('_')}
return params
def set_params(self, **params):
"""
设置参数
"""
for param in params:
if hasattr(self, param):
setattr(self, param, params[param])
return self
def get_support(self, indices=False):
"""
获取 mask,整数索引或选择的特征。
Parameters
----------
indices : bool
默认为 False. 如果为 True,返回值为整数数组,否则为布尔的 mask。
Returns
-------
list :
返回 support: 从特征向量中选择保留的特征索引。
如果 indices 为 False,布尔数据的形状为 [输入特征的数量],如果元素为 True,表示保留相对应的特征。
如果 indices 为 True,整数数组的形状为 [输出特征的数量],值表示
输入特征向量中的索引。
"""
...
return mask
def transform(self, X):
"""将 X 减少为选择的特征。
Parameters
----------
X : array
形状为 [n_samples, n_features]
Returns
-------
X_r : array
形状为 [n_samples, n_selected_features]
仅输入选择的特征。
"""
...
return X_r
def inverse_transform(self, X):
"""
反转变换操作
Parameters
----------
X : array
形状为 [n_samples, n_selected_features]
Returns
-------
X_r : array
形状为 [n_samples, n_original_features]
"""
...
return X_r
```
与 sklearn 继承后,可如下使用特征 Selector:
```python
from sklearn.linear_model import LogisticRegression
# 加载数据
...
X_train, y_train = ...
# 构造 pipeline
pipeline = make_pipeline(XXXSelector(...), LogisticRegression())
pipeline = make_pipeline(SelectFromModel(ExtraTreesClassifier(n_estimators=50)), LogisticRegression())
pipeline.fit(X_train, y_train)
# 分数
print("Pipeline Score: ", pipeline.score(X_train, y_train))
```
# 基准测试
`Baseline` 表示没有进行特征选择,直接将数据传入 LogisticRegression。 此基准测试中,仅用了 10% 的训练数据作为测试数据。
| 数据集 | Baseline | GradientFeatureSelector | TreeBasedClassifier | 训练次数 | 特征数量 |
| ------------- | -------- | ----------------------- | ------------------- | ---------- | --------- |
| colon-cancer | 0.7547 | 0.7368 | 0.7223 | 62 | 2,000 |
| gisette | 0.9725 | 0.89416 | 0.9792 | 6,000 | 5,000 |
| avazu | 0.8834 | N/A | N/A | 40,428,967 | 1,000,000 |
| rcv1 | 0.9644 | 0.7333 | 0.9615 | 20,242 | 47,236 |
| news20.binary | 0.9208 | 0.6870 | 0.9070 | 19,996 | 1,355,191 |
| real-sim | 0.9681 | 0.7969 | 0.9591 | 72,309 | 20,958 |
此基准测试可在[这里](https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/)下载
...@@ -16,4 +16,4 @@ help: ...@@ -16,4 +16,4 @@ help:
# Catch-all target: route all unknown targets to Sphinx using the new # Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile %: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
\ No newline at end of file
# NNI NAS 编程接口
我们正在尝试通过统一的编程接口来支持各种 NAS 算法,当前处于试验阶段。 这意味着当前编程接口可能会进行重大变化。
*先前的 [NAS annotation](../AdvancedFeature/GeneralNasInterfaces.md) 接口会很快被弃用。*
## 模型的编程接口
在两种场景下需要用于设计和搜索模型的编程接口。
1. 在设计神经网络时,可能在层、子模型或连接上有多种选择,并且无法确定是其中一种或某些的组合的结果最好。 因此,需要简单的方法来表达候选的层或子模型。
2. 在神经网络上应用 NAS 时,需要统一的方式来表达架构的搜索空间,这样不必为不同的搜索算法来更改代码。
在用户代码中表示的神经网络搜索空间,可使用以下 API (以 PyTorch 为例):
```python
# 在 PyTorch module 类中
def __init__(self):
...
# 从 ``ops`` 中选择 ``ops``, 这是 PyTorch 中的 module。
# op_candidates: 在 PyTorch 中 ``ops`` 是 module 的 list,而在 TensorFlow 中是 Keras 层的 list。
# key: ``LayerChoice`` 实例的名称
self.one_layer = nni.nas.pytorch.LayerChoice([
PoolBN('max', channels, 3, stride, 1, affine=False),
PoolBN('avg', channels, 3, stride, 1, affine=False),
FactorizedReduce(channels, channels, affine=False),
SepConv(channels, channels, 3, stride, 1, affine=False),
DilConv(channels, channels, 3, stride, 2, 2, affine=False)],
key="layer_name")
...
def forward(self, x):
...
out = self.one_layer(x)
...
```
用户可为某层指定多个候选的操作,最后从其中选择一个。 `key` 是层的标识符,可被用来在多个 `LayerChoice` 间共享选项。 例如,两个 `LayerChoice` 有相同的候选操作,并希望能使用同样的选择,(即,如果第一个选择了第 `i` 个操作,第二个也应该选择第 `i` 个操作),则可给它们相同的 key。
```python
def __init__(self):
...
# 从 ``n_candidates`` 个输入中选择 ``n_selected`` 个。
# n_candidates: 候选输入数量
# n_chosen: 选择的数量
# key: ``InputChoice`` 实例的名称
self.input_switch = nni.nas.pytorch.InputChoice(
n_candidates=3,
n_chosen=1,
key="switch_name")
...
def forward(self, x):
...
out = self.input_switch([in_tensor1, in_tensor2, in_tensor3])
...
```
`InputChoice` 是一个 PyTorch module,初始化时需要元信息,例如,从多少个输入后选中选择多少个输入,初始化的 `InputChoice` 名称。 真正候选的输入张量只能在 `forward` 函数中获得。 在 `InputChoice` 中,`forward` 会在调用时传入实际的候选输入张量。
一些 [NAS Trainer](#one-shot-training-mode) 需要知道输入张量的来源层,因此在 `InputChoice` 中添加了输入参数 `choose_from` 来表示每个候选输入张量的来源层。 `choose_from` 是 str 的 list,每个元素都是 `LayerChoice``InputChoice``key`,或者 module 的 name (详情参考[代码](https://github.com/microsoft/nni/blob/master/src/sdk/pynni/nni/nas/pytorch/mutables.py))。
除了 `LayerChoice``InputChoice`,还提供了 `MutableScope`,可以让用户标记自网络,从而给 NAS Trainer 提供更多的语义信息 (如网络结构)。 示例如下:
```python
class Cell(mutables.MutableScope):
def __init__(self, scope_name):
super().__init__(scope_name)
self.layer1 = nni.nas.pytorch.LayerChoice(...)
self.layer2 = nni.nas.pytorch.LayerChoice(...)
self.layer3 = nni.nas.pytorch.LayerChoice(...)
...
```
名为 `scope_name``MutableScope` 包含了三个 `LayerChoice` 层 (`layer1`, `layer2`, `layer3`)。 NAS Trainer 可获得这样的分层结构。
## 两种训练模式
在使用上述 API 在模型中嵌入 搜索空间后,下一步是从搜索空间中找到最好的模型。 有两种驯良模式:[one-shot 训练模式](#one-shot-training-mode) and [经典的分布式搜索](#classic-distributed-search)
### One-shot 训练模式
与深度学习模型的优化器相似,从搜索空间中找到最好模型的过程可看作是优化过程,称之为 `NAS Trainer`。 NAS Trainer 包括 `DartsTrainer` 使用了 SGD 来交替训练架构和模型权重,`ENASTrainer` 使用 Controller 来训练模型。 新的、更高效的 NAS Trainer 在研究界不断的涌现出来。
NNI 提供了一些流行的 NAS Trainer,要使用 NAS Trainer,用户需要在模型定义后初始化 Trainer:
```python
# 创建 DartsTrainer
trainer = DartsTrainer(model,
loss=criterion,
metrics=lambda output, target: accuracy(output, target, topk=(1,)),
optimizer=optim,
num_epochs=args.epochs,
dataset_train=dataset_train,
dataset_valid=dataset_valid,)
# 从搜索空间中找到最好的模型
trainer.train()
# 导出最好的模型
trainer.export(file='./chosen_arch')
```
不同的 Trainer 可能有不同的输入参数,具体取决于其算法。 详细参数可参考具体的 [Trainer 代码](https://github.com/microsoft/nni/tree/master/src/sdk/pynni/nni/nas/pytorch)。 训练完成后,可通过 `trainer.export()` 导出找到的最好的模型。 无需通过 `nnictl` 来启动 NNI Experiment。
[这里](./Overview.md#supported-one-shot-nas-algorithms)是所有支持的 Trainer。 [这里](https://github.com/microsoft/nni/tree/master/examples/nas/simple/train.py)是使用 NNI NAS API 的简单示例。
[这里]()是完整示例的代码。
### 经典分布式搜索
神经网络架构搜索通过在 Trial 任务中独立运行单个子模型来实现。 NNI 同样支持这种搜索方法,其天然适用于 NNI 的超参搜索框架。Tuner 为每个 Trial 生成子模型,并在训练平台上运行。
要使用此模式,不需要修改 NNI NAS API 的搜索空间定义 (即, `LayerChoice`, `InputChoice`, `MutableScope`)。 模型初始化后,在模型上调用 `get_and_apply_next_architecture`。 One-shot NAS Trainer 不能在此模式中使用。 简单示例:
```python
class Net(nn.Module):
# 使用 LayerChoice 和 InputChoice 的模型
...
model = Net()
# 从 Tuner 中选择架构,并应用到模型上
get_and_apply_next_architecture(model)
# 训练模型
train(model)
# 测试模型
acc = test(model)
# 返回此架构的性能
nni.report_final_result(acc)
```
搜索空间应自动生成,并发送给 Tuner。 通过 NNI NAS API,搜索空间嵌入在用户代码中,需要通过 "[nnictl ss_gen](../Tutorial/Nnictl.md)" 来生成搜索空间文件。 然后,将生成的搜索空间文件路径填入 `config.yml``searchSpacePath``config.yml` 中的其它字段参考[教程](../Tutorial/QuickStart.md)
可使用 [NNI Tuner](../Tuner/BuiltinTuner.md) 来搜索。
为了便于调试,其支持独立运行模式,可直接运行 Trial 命令,而不启动 NNI Experiment。 可以通过此方法来检查 Trial 代码是否可正常运行。 在独立模式下,`LayerChoice``InputChoice` 会选择最开始的候选项。
[此处](https://github.com/microsoft/nni/tree/master/examples/nas/classic_nas/config_nas.yml)是完整示例。
## NAS 算法的编程接口
通过简单的接口,可在 NNI 上实现新的 NAS Trainer。
### 在 NNI 上实现新的 NAS Trainer
要实现新的 NAS Trainer,基本上只需要继承 `BaseMutator``BaseTrainer` 这两个类。
`BaseMutator` 中,需要重载 `on_forward_layer_choice``on_forward_input_choice`,这是 `LayerChoice``InputChoice` 相应的实现。 可使用属性 `mutables` 来获得模型中所有的 `LayerChoice``InputChoice`。 然后实现新的 Trainer,来实例化新的 Mutator 并实现训练逻辑。 详细信息,可参考[代码](https://github.com/microsoft/nni/tree/master/src/sdk/pynni/nni/nas/pytorch),及支持的 Trainer,如 [DartsTrainer](https://github.com/microsoft/nni/tree/master/src/sdk/pynni/nni/nas/pytorch/darts)
### 为 NAS 实现 NNI Tuner
NNI 中的 NAS Tuner 需要自动生成搜索空间。 `LayerChoice``InputChoice` 的搜索空间格式如下:
```json
{
"key_name": {
"_type": "layer_choice",
"_value": ["op1_repr", "op2_repr", "op3_repr"]
},
"key_name": {
"_type": "input_choice",
"_value": {
"candidates": ["in1_key", "in2_key", "in3_key"],
"n_chosen": 1
}
}
}
```
相应的,生成的网络架构格式如下:
```json
{
"key_name": {
"_value": "op1_repr",
"_idx": 0
},
"key_name": {
"_value": ["in2_key"],
"_idex": [1]
}
}
```
\ No newline at end of file
# 神经网络结构搜索在 NNI 上的应用
自动化的神经网络架构(NAS)搜索在寻找更好的模型方面发挥着越来越重要的作用。 最近的研究工作证明了自动化 NAS 的可行性,并发现了一些超越手动设计和调整的模型。 代表算法有 [NASNet](https://arxiv.org/abs/1707.07012)[ENAS](https://arxiv.org/abs/1802.03268)[DARTS](https://arxiv.org/abs/1806.09055)[Network Morphism](https://arxiv.org/abs/1806.10282),以及 [Evolution](https://arxiv.org/abs/1703.01041) 等。 新的算法还在不断涌现。
但是,要实现NAS算法需要花费大量的精力,并且很难在新算法中重用现有算法的代码。 为了促进 NAS 创新(例如,设计、实现新的 NAS 模型,并列比较不同的 NAS 模型),易于使用且灵活的编程接口非常重要。
以此为动力,NNI 的目标是提供统一的体系结构,以加速NAS上的创新,并将最新的算法更快地应用于现实世界中的问题上。
通过 [统一的接口](NasInterface.md),有两种方式进行架构搜索。 [第一种](#supported-one-shot-nas-algorithms)称为 one-shot NAS,基于搜索空间构建了一个超级网络,并使用 one-shot 训练来生成性能良好的子模型。 [第二种](.ClassicNas.md)是传统的搜索方法,搜索空间中每个子模型作为独立的 Trial 运行,将性能结果发给 Tuner,由 Tuner 来生成新的子模型。
* [支持的 One-shot NAS 算法](#supported-one-shot-nas-algorithms)
* [使用 NNI Experiment 的经典分布式 NAS](.NasInterface.md#classic-distributed-search)
* [NNI NAS 编程接口](.NasInterface.md)
## 支持的 One-shot NAS 算法
NNI 现在支持以下 NAS 算法,并且正在添加更多算法。 用户可以重现算法或在自己的数据集上使用它。 鼓励用户使用 [NNI API](#use-nni-api) 实现其它算法,以使更多人受益。
| 名称 | 算法简介 |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| [ENAS](#enas) | Efficient Neural Architecture Search via Parameter Sharing [参考论文](https://arxiv.org/abs/1802.03268) |
| [DARTS](#darts) | DARTS: Differentiable Architecture Search [参考论文](https://arxiv.org/abs/1806.09055) |
| [P-DARTS](#p-darts) | Progressive Differentiable Architecture Search: Bridging the Depth Gap between Search and Evaluation [参考论文](https://arxiv.org/abs/1904.12760) |
注意,这些算法**不需要 nnictl**,独立运行,仅支持 PyTorch。 将来的版本会支持 Tensorflow 2.0。
### 依赖项
* NNI 1.2+
* tensorboard
* PyTorch 1.2+
* git
### ENAS
[Efficient Neural Architecture Search via Parameter Sharing](https://arxiv.org/abs/1802.03268). 在 ENAS 中,Contoller 学习在大的计算图中搜索最有子图的方式来发现神经网络。 它通过在子模型间共享参数来实现加速和出色的性能指标。
#### 用法
NNI 中的 ENAS 还在开发中,当前仅支持在 CIFAR10 上 Macro/Micro 搜索空间的搜索阶段。 在 PTB 上从头开始训练及其搜索空间尚未完成。
```bash
#如果未克隆 NNI 代码。 如果代码已被克隆,请忽略此行并直接进入代码目录。
git clone https://github.com/Microsoft/nni.git
# 搜索最好的网络架构
cd examples/nas/enas
# 在 Macro 搜索空间中搜索
python3 search.py --search-for macro
# 在 Micro 搜索空间中搜索
python3 search.py --search-for micro
# 查看更多选项
python3 search.py -h
```
### DARTS
[DARTS: Differentiable Architecture Search](https://arxiv.org/abs/1806.09055) 在算法上的主要贡献是,引入了一种在两级网络优化中使用的可微分算法。
#### 用法
```bash
#如果未克隆 NNI 代码。 如果代码已被克隆,请忽略此行并直接进入代码目录。
git clone https://github.com/Microsoft/nni.git
# 搜索最好的架构
cd examples/nas/darts
python3 search.py
# 训练最好的架构
python3 retrain.py --arc-checkpoint ./checkpoints/epoch_49.json
```
### P-DARTS
[Progressive Differentiable Architecture Search: Bridging the Depth Gap between Search and Evaluation](https://arxiv.org/abs/1904.12760) 基于 [DARTS](#DARTS)。 它在算法上的主要贡献是引入了一种有效的算法,可在搜索过程中逐渐增加搜索的深度。
#### 用法
```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
```
## 使用 NNI API
注意,我们正在尝试通过统一的编程接口来支持各种 NAS 算法,当前处于试验阶段。 这意味着当前编程接口将来会有变化。
*先前的 [NAS annotation](../AdvancedFeature/GeneralNasInterfaces.md) 接口会很快被弃用。*
### 编程接口
在两种场景下需要用于设计和搜索模型的编程接口。
1. 在设计神经网络时,可能在层、子模型或连接上有多种选择,并且无法确定是其中一种或某些的组合的结果最好。 因此,需要简单的方法来表达候选的层或子模型。
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 实现示例。
...@@ -99,32 +99,36 @@ ...@@ -99,32 +99,36 @@
**准备配置文件**:实现 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` 来查看其内容。 大致内容如下:
authorName: your_name ```yaml
experimentName: auto_mnist authorName: your_name
experimentName: auto_mnist
# 并发运行数量
trialConcurrency: 2 # 并发运行数量
trialConcurrency: 2
# Experiment 运行时间
maxExecDuration: 3h # Experiment 运行时间
maxExecDuration: 3h
# 可为空,即数量不限
maxTrialNum: 100 # 可为空,即数量不限
maxTrialNum: 100
# 可选值为: local, remote
trainingServicePlatform: local # 可选值为: local, remote
trainingServicePlatform: local
# 可选值为: true, false
useAnnotation: true # 搜索空间文件
tuner: searchSpacePath: search_space.json
builtinTunerName: TPE
classArgs: # 可选值为: true, false
optimize_mode: maximize useAnnotation: true
trial: tuner:
command: python mnist.py builtinTunerName: TPE
codeDir: ~/nni/examples/trials/mnist-annotation classArgs:
gpuNum: 0 optimize_mode: maximize
trial:
command: python mnist.py
codeDir: ~/nni/examples/trials/mnist-annotation
gpuNum: 0
```
因为这个 Trial 代码使用了 NNI Annotation 的方法(参考[这里](../Tutorial/AnnotationSpec.md) ),所以*useAnnotation* 为 true。 *command* 是运行 Trial 代码所需要的命令,*codeDir* 是 Trial 代码的相对位置。 命令会在此目录中执行。 同时,也需要提供每个 Trial 进程所需的 GPU 数量。 因为这个 Trial 代码使用了 NNI Annotation 的方法(参考[这里](../Tutorial/AnnotationSpec.md) ),所以*useAnnotation* 为 true。 *command* 是运行 Trial 代码所需要的命令,*codeDir* 是 Trial 代码的相对位置。 命令会在此目录中执行。 同时,也需要提供每个 Trial 进程所需的 GPU 数量。
......
...@@ -21,6 +21,8 @@ maxExecDuration: 3h ...@@ -21,6 +21,8 @@ maxExecDuration: 3h
maxTrialNum: 100 maxTrialNum: 100
# 可选项: local, remote, pai # 可选项: local, remote, pai
trainingServicePlatform: pai trainingServicePlatform: pai
# 搜索空间文件
searchSpacePath: search_space.json
# 可选项: true, false # 可选项: true, false
useAnnotation: true useAnnotation: true
tuner: tuner:
...@@ -88,6 +90,23 @@ paiConfig: ...@@ -88,6 +90,23 @@ paiConfig:
portNumber: 1 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),运行以下命令:
nnictl create --config exp_pai.yml nnictl create --config exp_pai.yml
...@@ -107,7 +126,7 @@ paiConfig: ...@@ -107,7 +126,7 @@ paiConfig:
## 数据管理 ## 数据管理
如果训练数据集不大,可放在 codeDir中,NNI会将其上传到 HDFS,或者构建 Docker 映像来包含数据。 如果数据集非常大,则不可放在 codeDir 中,可参考此[指南](https://github.com/microsoft/pai/blob/master/docs/user/storage.md)来将数据目录挂载到容器中。 如果训练数据集不大,可放在 codeDir 中,NNI会将其上传到 HDFS,或者构建 Docker 映像来包含数据。 如果数据集非常大,则不可放在 codeDir 中,可参考此[指南](https://github.com/microsoft/pai/blob/master/docs/user/storage.md)来将数据目录挂载到容器中。
如果要将 Trial 的其它输出保存到 HDFS 上,如模型文件等,需要在 Trial 代码中使用 `NNI_OUTPUT_DIR` 来保存输出文件。NNI 的 SDK 会将文件从 Trial 容器的 `NNI_OUTPUT_DIR` 复制到 HDFS 上,目标路径为:`hdfs://host:port/{username}/nni/{experiments}/{experimentId}/trials/{trialId}/nnioutput` 如果要将 Trial 的其它输出保存到 HDFS 上,如模型文件等,需要在 Trial 代码中使用 `NNI_OUTPUT_DIR` 来保存输出文件。NNI 的 SDK 会将文件从 Trial 容器的 `NNI_OUTPUT_DIR` 复制到 HDFS 上,目标路径为:`hdfs://host:port/{username}/nni/{experiments}/{experimentId}/trials/{trialId}/nnioutput`
......
...@@ -26,16 +26,18 @@ experimentName: example_mnist ...@@ -26,16 +26,18 @@ experimentName: example_mnist
trialConcurrency: 1 trialConcurrency: 1
maxExecDuration: 1h maxExecDuration: 1h
maxTrialNum: 10 maxTrialNum: 10
#可选项: local, remote, pai #choice: local, remote, pai
trainingServicePlatform: remote trainingServicePlatform: remote
#可选项: true, false # 搜索空间文件
searchSpacePath: search_space.json
# 可选项: true, false
useAnnotation: true useAnnotation: true
tuner: tuner:
#可选项: TPE, Random, Anneal, Evolution, BatchTuner # 可选项: TPE, Random, Anneal, Evolution, BatchTuner
#SMAC (SMAC 需要通过 nnictl 安装) #SMAC (SMAC 需要通过 nnictl 安装)
builtinTunerName: TPE builtinTunerName: TPE
classArgs: classArgs:
#可选项: maximize, minimize # 可选项:: maximize, minimize
optimize_mode: maximize optimize_mode: maximize
trial: trial:
command: python3 mnist.py command: python3 mnist.py
......
...@@ -48,7 +48,13 @@ GBDT 有很多超参,但哪些才会影响性能或计算速度呢? 基于 ...@@ -48,7 +48,13 @@ GBDT 有很多超参,但哪些才会影响性能或计算速度呢? 基于
## 3. 如何运行 NNI ## 3. 如何运行 NNI
### 3.1 准备 Trial 代码 ### 3.1 安装所有要求的包
pip install lightgbm
pip install pandas
### 3.2 准备 Trial 代码
基础代码如下: 基础代码如下:
...@@ -90,7 +96,7 @@ if __name__ == '__main__': ...@@ -90,7 +96,7 @@ if __name__ == '__main__':
run(lgb_train, lgb_eval, PARAMS, X_test, y_test) run(lgb_train, lgb_eval, PARAMS, X_test, y_test)
``` ```
### 3.2 准备搜索空间 ### 3.3 准备搜索空间
如果要调优 `num_leaves`, `learning_rate`, `bagging_fraction``bagging_freq`, 可创建一个 [search_space.json](https://github.com/Microsoft/nni/blob/master/examples/trials/auto-gbdt/search_space.json) 文件: 如果要调优 `num_leaves`, `learning_rate`, `bagging_fraction``bagging_freq`, 可创建一个 [search_space.json](https://github.com/Microsoft/nni/blob/master/examples/trials/auto-gbdt/search_space.json) 文件:
...@@ -105,7 +111,7 @@ if __name__ == '__main__': ...@@ -105,7 +111,7 @@ if __name__ == '__main__':
参考[这里](../Tutorial/SearchSpaceSpec.md),了解更多变量类型。 参考[这里](../Tutorial/SearchSpaceSpec.md),了解更多变量类型。
### 3.3 在代码中使用 NNI SDK ### 3.4 在代码中使用 NNI SDK
```diff ```diff
+import nni +import nni
...@@ -153,7 +159,7 @@ if __name__ == '__main__': ...@@ -153,7 +159,7 @@ if __name__ == '__main__':
run(lgb_train, lgb_eval, PARAMS, X_test, y_test) run(lgb_train, lgb_eval, PARAMS, X_test, y_test)
``` ```
### 3.4 实现配置文件并运行 ### 3.5 实现配置文件并运行
在配置文件中,可以设置如下内容: 在配置文件中,可以设置如下内容:
......
...@@ -120,7 +120,7 @@ tuner: ...@@ -120,7 +120,7 @@ tuner:
* **optimize_mode** (*maximize 或 minimize, 可选项, 默认值为 maximize*) - 如果为 'maximize',表示 Tuner 的目标是将指标最大化。 如果为 'minimize',表示 Tuner 的目标是将指标最小化。 * **optimize_mode** (*maximize 或 minimize, 可选项, 默认值为 maximize*) - 如果为 'maximize',表示 Tuner 的目标是将指标最大化。 如果为 'minimize',表示 Tuner 的目标是将指标最小化。
* **population_size** (*int 类型(大于 0), 可选项, 默认值为 20*) - 表示遗传 Tuner 中的种群(Trial 数量)。 * **population_size** (*int 类型(大于 0), 可选项, 默认值为 20*) - 表示遗传 Tuner 中的种群(Trial 数量)。 建议 `population_size``concurrency` 取值更大,这样用户能充分利用算法(至少要等于 `concurrency`,否则 Tuner 在生成第一代参数的时候就会失败)。
**示例** **示例**
...@@ -145,7 +145,7 @@ tuner: ...@@ -145,7 +145,7 @@ tuner:
**安装** **安装**
SMAC 在第一次使用前,必须用下面的命令先安装。 SMAC 在第一次使用前,必须用下面的命令先安装。 注意:SMAC 依赖于 `swig`,Ubuntu 下可通过 `apt` 命令来安装 `swig`
```bash ```bash
nnictl package install --name=SMAC nnictl package install --name=SMAC
......
...@@ -43,6 +43,9 @@ ...@@ -43,6 +43,9 @@
* NNI 遵循 [PEP8](https://www.python.org/dev/peps/pep-0008/) 的 Python 代码命名约定。在提交拉取请求时,请尽量遵循此规范。 可通过`flake8``pylint`的提示工具来帮助遵循规范。 * NNI 遵循 [PEP8](https://www.python.org/dev/peps/pep-0008/) 的 Python 代码命名约定。在提交拉取请求时,请尽量遵循此规范。 可通过`flake8``pylint`的提示工具来帮助遵循规范。
* NNI 还遵循 [NumPy Docstring 风格](https://www.sphinx-doc.org/en/master/usage/extensions/example_numpy.html#example-numpy) 的 Python Docstring 命名方案。 Python API 使用了[sphinx.ext.napoleon](https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html)[生成文档](Contributing.md#documentation) * NNI 还遵循 [NumPy Docstring 风格](https://www.sphinx-doc.org/en/master/usage/extensions/example_numpy.html#example-numpy) 的 Python Docstring 命名方案。 Python API 使用了[sphinx.ext.napoleon](https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html)[生成文档](Contributing.md#documentation)
* 有关 docstrings,参考 [numpydoc docstring 指南](https://numpydoc.readthedocs.io/en/latest/format.html)[pandas docstring 指南](https://python-sprints.github.io/pandas/guide/pandas_docstring.html)
* 函数的 docstring, **description**, **Parameters**, 以及**Returns**/**Yields** 是必需的。
* 类的 docstring, **description**, **Attributes** 是必需的。
## 文档 ## 文档
......
...@@ -22,6 +22,7 @@ nnictl 支持的命令: ...@@ -22,6 +22,7 @@ nnictl 支持的命令:
* [nnictl webui](#webui) * [nnictl webui](#webui)
* [nnictl tensorboard](#tensorboard) * [nnictl tensorboard](#tensorboard)
* [nnictl package](#package) * [nnictl package](#package)
* [nnictl ss_gen](#ss_gen)
* [nnictl --version](#version) * [nnictl --version](#version)
### 管理 Experiment ### 管理 Experiment
...@@ -742,6 +743,38 @@ nnictl 支持的命令: ...@@ -742,6 +743,38 @@ nnictl 支持的命令:
nnictl package show nnictl package show
``` ```
<a name="ss_gen"></a>
![](https://placehold.it/15/1589F0/000000?text=+) `生成搜索空间`
* **nnictl ss_gen**
* 说明
从使用 NNI NAS API 的用户代码生成搜索空间。
* 用法
```bash
nnictl ss_gen [OPTIONS]
```
* 选项
| 参数及缩写 | 是否必需 | 默认值 | 说明 |
| --------------- | ----- | ---------------------------------- | ----------- |
| --trial_command | True | | Trial 代码的命令 |
| --trial_dir | False | ./ | Trial 代码目录 |
| --file | False | nni_auto_gen_search_space.json | 用来存储生成的搜索空间 |
* 示例
> 生成搜索空间
```bash
nnictl ss_gen --trial_command="python3 mnist.py" --trial_dir=./ --file=ss.json
```
<a name="version"></a> <a name="version"></a>
![](https://placehold.it/15/1589F0/000000?text=+) `检查 NNI 版本` ![](https://placehold.it/15/1589F0/000000?text=+) `检查 NNI 版本`
......
...@@ -101,7 +101,7 @@ NNI 用来帮助超参调优。它的流程如下: ...@@ -101,7 +101,7 @@ NNI 用来帮助超参调优。它的流程如下:
mnist_network.train(sess, mnist) mnist_network.train(sess, mnist)
test_acc = mnist_network.evaluate(mnist) test_acc = mnist_network.evaluate(mnist)
+ nni.report_final_result(acc) + nni.report_final_result(test_acc)
if __name__ == '__main__': if __name__ == '__main__':
...@@ -253,4 +253,4 @@ Experiment 相关信息会显示在界面上,配置和搜索空间等。 可 ...@@ -253,4 +253,4 @@ Experiment 相关信息会显示在界面上,配置和搜索空间等。 可
* [如何在多机上运行 Experiment?](../TrainingService/RemoteMachineMode.md) * [如何在多机上运行 Experiment?](../TrainingService/RemoteMachineMode.md)
* [如何在 OpenPAI 上运行 Experiment?](../TrainingService/PaiMode.md) * [如何在 OpenPAI 上运行 Experiment?](../TrainingService/PaiMode.md)
* [如何通过 Kubeflow 在 Kubernetes 上运行 Experiment?](../TrainingService/KubeflowMode.md) * [如何通过 Kubeflow 在 Kubernetes 上运行 Experiment?](../TrainingService/KubeflowMode.md)
* [如何通过 FrameworkController 在 Kubernetes 上运行 Experiment?](../TrainingService/FrameworkControllerMode.md) * [如何通过 FrameworkController 在 Kubernetes 上运行 Experiment?](../TrainingService/FrameworkControllerMode.md)
\ No newline at end of file
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
将第一行作为样例。 `dropout_rate` 定义了一个变量,先验分布为均匀分布,范围从 `0.1``0.5` 将第一行作为样例。 `dropout_rate` 定义了一个变量,先验分布为均匀分布,范围从 `0.1``0.5`
注意,搜索空间的效果与 Tuner 高度相关。 此处列出了内置 Tuner 所支持的类型。 对于自定义的 Tuner,不必遵循鞋标,可使用任何的类型。
## 类型 ## 类型
所有采样策略和参数如下: 所有采样策略和参数如下:
...@@ -78,12 +80,6 @@ ...@@ -78,12 +80,6 @@
* 这表示变量值会类似于 `round(exp(normal(mu, sigma)) / q) * q` * 这表示变量值会类似于 `round(exp(normal(mu, sigma)) / q) * q`
* 适用于值是“平滑”的离散变量,但某一边有界。 * 适用于值是“平滑”的离散变量,但某一边有界。
* `{"_type": "mutable_layer", "_value": {mutable_layer_infomation}}`
* [神经网络架构搜索空间](../AdvancedFeature/GeneralNasInterfaces.md)的类型。 值是字典类型,键值对表示每个 mutable_layer 的名称和搜索空间。
* 当前,只能通过 Annotation 来使用这种类型的搜索空间。因此不需要为搜索空间定义 JSON 文件,它会通过 Trial 中的 Annotation 自动生成。
* 具体用法参考[通用 NAS 接口](../AdvancedFeature/GeneralNasInterfaces.md)
## 每种 Tuner 支持的搜索空间类型 ## 每种 Tuner 支持的搜索空间类型
| | choice | randint | uniform | quniform | loguniform | qloguniform | normal | qnormal | lognormal | qlognormal | | | choice | randint | uniform | quniform | loguniform | qloguniform | normal | qnormal | lognormal | qlognormal |
...@@ -106,4 +102,4 @@ ...@@ -106,4 +102,4 @@
* 请注意,对于嵌套搜索空间: * 请注意,对于嵌套搜索空间:
* 只有 随机搜索/TPE/Anneal/Evolution Tuner 支持嵌套搜索空间 * 只有 随机搜索/TPE/Anneal/Evolution Tuner 支持嵌套搜索空间
* 不支持嵌套搜索空间 "超参" 的可视化,对其的改进通过 #1110(https://github.com/microsoft/nni/issues/1110) 来跟踪 。欢迎任何建议和贡献。 * 不支持嵌套搜索空间 "超参" 的可视化,对其的改进通过 [#1110](https://github.com/microsoft/nni/issues/1110) 来跟踪 。欢迎任何建议和贡献。
\ No newline at end of file \ No newline at end of file
...@@ -3,5 +3,3 @@ ...@@ -3,5 +3,3 @@
.. toctree:: .. toctree::
多阶段<./AdvancedFeature/MultiPhase> 多阶段<./AdvancedFeature/MultiPhase>
高级网络架构搜索<./AdvancedFeature/AdvancedNas>
NAS 编程接口<./AdvancedFeature/GeneralNasInterfaces>
\ No newline at end of file
#################
特征工程
#################
很高兴的宣布 NNI 的特征工程包 Alpha 版本发布了。
其仍处于试验阶段,会根据使用反馈来演化。
诚挚邀请您使用、反馈,或更多贡献。
详细信息,参考以下教程:
.. toctree::
:maxdepth: 2
概述 <FeatureEngineering/Overview>
GradientFeatureSelector <FeatureEngineering/GradientFeatureSelector>
GBDTSelector <FeatureEngineering/GBDTSelector>
#################
模型压缩
#################
NNI 提供了易于使用的工具包来帮助用户设计并使用压缩算法。
其使用了统一的接口来支持 TensorFlow 和 PyTorch。
只需要添加几行代码即可压缩模型。
NNI 中也内置了一些流程的模型压缩算法。
用户可以进一步利用 NNI 的自动调优功能找到最佳的压缩模型,
自动模型压缩部分有详细介绍。
另一方面,用户可以使用 NNI 的接口自定义新的压缩算法。
详细信息,参考以下教程:
.. toctree::
:maxdepth: 2
概述 <Compressor/Overview>
Level Pruner <Compressor/Pruner>
AGP Pruner <Compressor/Pruner>
L1Filter Pruner <Compressor/L1FilterPruner>
Slim Pruner <Compressor/SlimPruner>
Lottery Ticket Pruner <Compressor/LotteryTicketHypothesis>
FPGM Pruner <Compressor/Pruner>
Naive Quantizer <Compressor/Quantizer>
QAT Quantizer <Compressor/Quantizer>
DoReFa Quantizer <Compressor/Quantizer>
自动模型压缩 <Compressor/AutoCompression>
#################
NAS 算法
#################
自动化的神经网络架构(NAS)搜索在寻找更好的模型方面发挥着越来越重要的作用。
最近的研究工作证明了自动化 NAS 的可行性,并发现了一些超越手动设计和调整的模型。
代表工作有 NASNet, ENAS, DARTS, Network Morphism, 以及 Evolution 等。 新的算法还在不断涌现。
但是,要实现NAS算法需要花费大量的精力,并且很难在新算法中重用现有算法的代码。
为了促进 NAS 创新 (如, 设计实现新的 NAS 模型,比较不同的 NAS 模型),
易于使用且灵活的编程接口非常重要。
以此为出发点,我们的目标是在 NNI 中提供统一的架构,
来加速 NAS 创新,并更快的将最先进的算法用于现实世界的问题上。
详细信息,参考以下教程:
.. toctree::
:maxdepth: 2
概述 <NAS/Overview>
NAS 接口 <NAS/NasInterface>
ENAS <NAS/Overview>
DARTS <NAS/Overview>
P-DARTS <NAS/Overview>
...@@ -24,10 +24,10 @@ Tuner(调参器) ...@@ -24,10 +24,10 @@ Tuner(调参器)
.. autoclass:: nni.evolution_tuner.evolution_tuner.EvolutionTuner .. autoclass:: nni.evolution_tuner.evolution_tuner.EvolutionTuner
:members: :members:
.. autoclass:: nni.smac_tuner.smac_tuner.SMACTuner .. autoclass:: nni.smac_tuner.SMACTuner
:members: :members:
.. autoclass:: nni.gridsearch_tuner.gridsearch_tuner.GridSearchTuner .. autoclass:: nni.gridsearch_tuner.GridSearchTuner
:members: :members:
.. autoclass:: nni.networkmorphism_tuner.networkmorphism_tuner.NetworkMorphismTuner .. autoclass:: nni.networkmorphism_tuner.networkmorphism_tuner.NetworkMorphismTuner
...@@ -36,15 +36,27 @@ Tuner(调参器) ...@@ -36,15 +36,27 @@ Tuner(调参器)
.. autoclass:: nni.metis_tuner.metis_tuner.MetisTuner .. autoclass:: nni.metis_tuner.metis_tuner.MetisTuner
:members: :members:
.. autoclass:: nni.ppo_tuner.PPOTuner
:members:
.. autoclass:: nni.batch_tuner.batch_tuner.BatchTuner
:members:
.. autoclass:: nni.gp_tuner.gp_tuner.GPTuner
:members:
Assessor(评估器) Assessor(评估器)
------------------------ ------------------------
.. autoclass:: nni.assessor.Assessor .. autoclass:: nni.assessor.Assessor
:members: :members:
.. autoclass:: nni.curvefitting_assessor.curvefitting_assessor.CurvefittingAssessor .. autoclass:: nni.assessor.AssessResult
:members:
.. autoclass:: nni.curvefitting_assessor.CurvefittingAssessor
:members: :members:
.. autoclass:: nni.medianstop_assessor.medianstop_assessor.MedianstopAssessor .. autoclass:: nni.medianstop_assessor.MedianstopAssessor
:members: :members:
...@@ -57,4 +69,4 @@ Advisor ...@@ -57,4 +69,4 @@ Advisor
:members: :members:
.. autoclass:: nni.bohb_advisor.bohb_advisor.BOHB .. autoclass:: nni.bohb_advisor.bohb_advisor.BOHB
:members: :members:
\ No newline at end of file
...@@ -9,6 +9,9 @@ ...@@ -9,6 +9,9 @@
实现 Trial<./TrialExample/Trials> 实现 Trial<./TrialExample/Trials>
Tuner<tuners> Tuner<tuners>
Assessor<assessors> Assessor<assessors>
NAS (Beta) <nas>
模型压缩 (Beta) <model_compression>
特征工程 (Beta) <feature_engineering>
Web 界面<Tutorial/WebUI> Web 界面<Tutorial/WebUI>
训练平台<training_services> 训练平台<training_services>
如何使用 Docker<Tutorial/HowToUseDocker> 如何使用 Docker<Tutorial/HowToUseDocker>
......
# Copyright (c) Microsoft Corporation
# All rights reserved.
#
# MIT License
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
# to permit persons to whom the Software is furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import bz2
import urllib.request
import numpy as np
from sklearn.datasets import load_svmlight_file
from sklearn.model_selection import train_test_split
from nni.feature_engineering.gbdt_selector import GBDTSelector
url_zip_train = 'https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/binary/rcv1_train.binary.bz2'
urllib.request.urlretrieve(url_zip_train, filename='train.bz2')
f_svm = open('train.svm', 'wt')
with bz2.open('train.bz2', 'rb') as f_zip:
data = f_zip.read()
f_svm.write(data.decode('utf-8'))
f_svm.close()
X, y = load_svmlight_file('train.svm')
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)
lgb_params = {
'boosting_type': 'gbdt',
'objective': 'regression',
'metric': {'l2', 'l1'},
'num_leaves': 20,
'learning_rate': 0.05,
'feature_fraction': 0.9,
'bagging_fraction': 0.8,
'bagging_freq': 5,
'verbose': 0}
eval_ratio = 0.1
early_stopping_rounds = 10
importance_type = 'gain'
num_boost_round = 1000
topk = 10
selector = GBDTSelector()
selector.fit(X_train, y_train,
lgb_params = lgb_params,
eval_ratio = eval_ratio,
early_stopping_rounds = early_stopping_rounds,
importance_type = importance_type,
num_boost_round = num_boost_round)
print("selected features\t", selector.get_selected_features(topk=topk))
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