NNI 超参搜索

想用 NNI 在平台上做超参数自动搜索(编写可接收超参的代码、配置参数空间与算法、启动并查看搜索结果)时阅读

平台使用 / 任务流与训练
超参搜索超参数优化NNInniAutoMLHPOhyperparametertunerTPE参数空间search spacereport_final_resultreport_intermediate_resulttrial

NNI 超参搜索介绍

NNI(Neural Network Intelligence)是微软开源的一个 AutoML 工具包,用于超参数优化、神经架构搜索、模型压缩和特征工程。

NNI 的超参搜索支持更多的算法。同时在 pipeline 中也支持了"边训练边超参搜索"的模板。只需要用户的代码能接受超参数作为输入,同时上报作为超参算法的目标值即可。

每个用户可以启动多个超参搜索的实例,通过 url prefix(/nni/<实验名>/)作为前端的路由(路由前缀实现见 myapp/views/view_nni.py:434,nni web 服务监听容器内 8888 端口)。

可以参考 NNI 官网 的书写方式。

NNI 超参搜索

1、编写超参搜索代码

参数接收

启动超参搜索时,会根据用户配置的超参搜索算法选择好超参的可选值,并将选择值传递给用户的容器。例如下面的超参定义会在用户 docker 运行时传递下面的参数。所以用户不需要在启动命令或参数中添加这些变量,系统会自动添加,用户只需要在自己的业务代码中接收这些参数,并根据这些参数输出值即可。

--lr=0.021593113434583065 --num-layers=5 --optimizer=ftrl

结果上报

业务方容器和代码启动接收超参进行迭代计算,通过主动上报结果来进行迭代。示例如下:用户代码需要能接受超参可取值为输入参数,同时每次迭代通过 nni.report_intermediate_result 上报每次 epoch 的结果值,并使用 nni.report_final_result 上报每次实例的最终结果值。

import os
import argparse
import logging, random, time
import nni
from nni.utils import merge_parameter

logger = logging.getLogger('mnist_AutoML')

def main(args):
    test_acc = random.randint(30, 50)
    for epoch in range(1, 11):
        test_acc_epoch = random.randint(3, 5)
        time.sleep(3)
        test_acc += test_acc_epoch
        # 上报当前迭代目标值
        nni.report_intermediate_result(test_acc)
    # 上报最终目标值
    nni.report_final_result(test_acc)


def get_params():
    # 必须接收超参数为输入参数
    parser = argparse.ArgumentParser(description='PyTorch MNIST Example')
    parser.add_argument('--batch_size', type=int, default=64, help='input batch size for training (default: 64)')

    args, _ = parser.parse_known_args()
    return args


if __name__ == '__main__':
    try:
        # get parameters form tuner
        tuner_params = nni.get_next_parameter()
        params = vars(merge_parameter(get_params(), tuner_params))
        print(tuner_params, params)
        main(params)
    except Exception as exception:
        logger.exception(exception)
        raise

2、添加一个超参搜索实验

在这里插入图片描述

创建实验时需要配置:搜索算法、目标函数类型(maximize/minimize)、目标指标名、超参数(搜索空间)、任务镜像、工作目录、启动命令、资源(cpu/memory/gpu)、任务并行数、最大任务数、最大运行时长、任务并行方式等。

平台实际可选的搜索算法(myapp/views/view_nni.py:191-206):TPE、Random、Anneal、Evolution、SMAC、BatchTuner、GridSearch、Hyperband、NetworkMorphism、MetisTuner、BOHB、GPTuner、PPOTuner、PBTTuner。

任务并行方式(parallel_trial_type)有两种(view_nni.py:132-138):

  • multi-process:单机多进程,平台创建单个 nni Pod 运行(make_nnijob);
  • multi-machine:多机多进程,平台创建 Volcano Job 拉起 master + 多个 worker(make_volcanojob)。

不同超参算法支持不同的超参空间

下表为 NNI 各 Tuner 对不同搜索空间类型的支持情况(参考 NNI 官方文档):

Tuner choice choice(nested) randint uniform quniform loguniform qloguniform normal qnormal lognormal qlognormal
TPE Tuner
Random Search Tuner
Anneal Tuner
Evolution Tuner
SMAC Tuner
Batch Tuner
Grid Search Tuner
Hyperband Advisor
Metis Tuner
GP Tuner

超参空间

必须是标准的 json。示例:

{
    "batch_size": {"_type":"choice", "_value": [16, 32, 64, 128]},
    "hidden_size":{"_type":"choice","_value":[128, 256, 512, 1024]},
    "lr":{"_type":"choice","_value":[0.0001, 0.001, 0.01, 0.1]},
    "momentum":{"_type":"uniform","_value":[0, 1]}
}

该示例与平台内置示例 core.nni_parameters_demo() 一致(myapp/utils/core.py:574)。

3、启动超参搜索

点击 运行 | 容器 | 日志 | 清理 中的 运行 按钮:

  • 运行按钮:启动搜索实验(部署 nni 服务,接口 /nni_modelview/api/run/<nni_id>view_nni.py:791);
  • 容器按钮:查看搜索实验容器运行状况;
  • 日志按钮:查看平台日志(这里不是业务代码日志,接口 /nni_modelview/api/log/<nni_id>view_nni.py:925);
  • 清理按钮:删除清理实验(接口 /nni_modelview/api/stop/<nni_id>view_nni.py:776)。

4、查看超参搜索进度和结果

等待全部容器运行中时,点击名称,进入 web 界面查看实验进度和日志(跳转到 /nni/<实验名>/view_nni.py:938-954)。

web 查看搜索效果

总览界面可以看到实验的 id 和当前实例运行的状态。

输入图片说明

输入图片说明

可以看每次 trial 的运行情况、计算出来的目标值。

输入图片说明

也可以看某次 trial 中每次 epoch 得到的结果值。

分布式超参搜索日志查看

由于是分布式进行超参数搜索,日志保存在分布式存储。想看某次搜索运行实例的日志:

在这里插入图片描述

在 web 界面看到的日志地址为:

Trial stdout: file://test-worker-2.test:/tmp/nni-experiments/$实验名/envs/$任务名

则对应分布式存储日志路径地址为:

/mnt/$用户名/nni/$nni名称/log/$实验名/envs/$任务名

说明:nni 代码、配置和 log 都在 /mnt/${username}/nni/ 目录下。实验工作目录为 /mnt/<username>/nni/<name>/log/,容器内 /tmp/nni-experiments/ 挂载到该 log 目录(view_nni.py:393/489/834)。

在这里插入图片描述

5、清理超参搜索实验

点击 运行 | 容器 | 日志 | 清理 中的 清理 按钮。运行结束后记得主动清理,以释放集群资源。

最后更新 2026-06-30完整文档以官方仓库为准:GitHub Wiki