- 数据可视化
- 机器学习
- 前端
- 后端
【免费下载链接】tensorboard
TensorFlow's Visualization Toolkit
本篇技术指南围绕 TensorBoard HParams(超参数调优)插件的 HTTP API 展开,系统讲解其基于 Protocol Buffers(proto3)的 JSON 编码约定、GET/POST 两种请求方式、三个核心数据端点(experiment、session_groups、metric_evals)的请求/响应协议,以及背后的数据模型与源码实现。读者读完可掌握如何直接通过 HTTP 调用 HParams 后端接口,理解 session group 聚合、过滤、排序的底层机制,并能基于本仓库源码独立调试或扩展该插件。
一、API 总体设计:一个 proto3 驱动的 REST 风格接口
HParams 插件的后端(HParamsPlugin,见 hparams_plugin.py)对外提供了一组 HTTP 接口,用于前端读取超参数实验数据。其设计核心有两点:
- 请求与响应都是 Protocol Buffer 消息:每个端点(end-point)都对应一个"请求 proto"并返回一个"响应 proto"。
- 一律使用 JSON 编码传输:请求体按 proto3 的 JSON 映射规则编码为 JSON 字符串,响应同样以 JSON 返回。关于 proto 与 JSON 的映射规则(字段名、enum 值、bytes 编码等),可参考 proto3 JSON 规范中对
json_format的说明。
这种设计使接口天然具备类型约束——前端组件(如tf-hparams-backend.ts)与后端共享api.proto中定义的消息类型,前后端通过 api.proto 保持契约一致,该文件注释中明确要求"如果你修改了任何消息,务必同步更新 api.d.ts"。
GET 与 POST 的请求传递方式
同一套端点同时支持 HTTP GET 与 POST 两种调用方式,区别仅在于请求的携带位置:
- POST:请求 proto 的 JSON 编码放在请求体(request body)中。
- GET:请求 proto 的 JSON 编码放在名为
request的 URL 查询参数中(注意需要做 URL 转义)。
这一逻辑在源码中有精确对应。hparams_plugin.py中的_parse_request_argument()函数按请求方法选择数据来源:
request_json = ( request.data if request.method == "POST" else request.args.get("request") ) try: return json_format.Parse(request_json, proto_class()) except (AttributeError, json_format.ParseError) as e: raise error.HParamsError(...)可以看到,后端统一用json_format.Parse()把 JSON 解析成对应的请求 proto;如果 JSON 缺失或格式错误,会抛出HParamsError,最终被包装成 HTTP 400 Bad Request 返回。
前端侧,tf-hparams-backend.ts 默认使用 GET(构造函数useHttpGet = true),其_sendRequest()方法用JSON.stringify(request_proto)把请求 proto 序列化为 JSON 后拼入request查询参数;若useHttpGet为 false 则改用 POST,把 JSON 作为text/plain请求体发送。
二、端点路由约定
1. 统一前缀/data/plugin/hparams
按照 TensorBoard 的惯例,所有端点都带有data/plugin/hparams前缀。该前缀可以通过 TensorBoard 的路由配置改为其他值(即插件挂载路径可定制)。
HParams 插件实际注册的完整路由如下(见hparams_plugin.py的get_plugin_apps()):
| 路由 | 处理函数 | 对应请求 proto |
|---|---|---|
/data/plugin/hparams/experiment | get_experiment_route | GetExperimentRequest |
/data/plugin/hparams/session_groups | list_session_groups_route | ListSessionGroupsRequest |
/data/plugin/hparams/metric_evals | list_metric_evals_route | ListMetricEvalsRequest |
/data/plugin/hparams/download_data | download_data_route | ListSessionGroupsRequest(另需format、columnsVisibility查询参数) |
其中download_data是额外提供的导出端点,它复用ListSessionGroupsRequest,支持把 session groups 导出为指定格式(format参数)的数据文件,前端 tf-hparams-backend.ts 中的getDownloadUrl()正是为生成该导出链接而设计。
2. 关于 experiment name 的说明
一个值得注意的设计细节:虽然当前单个 TensorBoard UI 窗口只支持展示一个实验(experiment),但 API 层仍然要求请求中携带实验名(experiment_name字段)。这是为将来支持多实验预留的扩展点——具体是否尊重该实验名、如何解析它,由 API 服务器(即插件后端)自己决定。
在现有实现中,实验名通常对应 TensorBoard 的 experiment_id 路由参数,hparams_plugin.py中通过plugin_util.experiment_id(request.environ)获取。
三、三个核心端点的协议详解
1./data/plugin/hparams/experiment
返回定义实验元数据的Experiment对象。
Args(请求 proto:GetExperimentRequest)
定义于 api.proto:
| 字段 | 类型 | 说明 |
|---|---|---|
experiment_name | string | 必填,实验的唯一全局标识 |
include_metrics | optional bool | 是否在结果中包含指标元数据,默认 true |
hparams_limit | optional int32 | 返回的超参数元数据条数上限;为 0 时返回全部 |
Returns:Experiment消息,包含实验名、描述、创建者、创建时间,以及超参数元数据列表(hparam_infos)和指标元数据列表(metric_infos)。
2./data/plugin/hparams/session_groups
列出实验中的 session groups(会话组)。这是最复杂、最核心的端点,因为它承载了过滤、排序、聚合与分页四类能力。
Args(请求 proto:ListSessionGroupsRequest)
定义于 api.proto:
| 字段 | 类型 | 说明 |
|---|---|---|
experiment_name | string | 实验名 |
allowed_statuses | repeated Status | 只统计状态在集合内的 session(STATUS_UNKNOWN/SUCCESS/FAILURE/RUNNING) |
col_params | repeated ColParams | 每个元素描述一个"列"(某个超参数或指标)的过滤与排序规则 |
aggregation_type | AggregationType | 组内多 session 的指标聚合方式(AVG/MEDIAN/MIN/MAX) |
aggregation_metric | MetricName | 当聚合类型为 MEDIAN/MIN/MAX 时,用于选择"代表 session"的指标 |
start_index | int32 | 返回结果切片(slice)的起始索引,0 基 |
slice_size | int32 | 返回的 session group 数量 |
include_metrics | optional bool | 是否包含指标,默认 true |
Returns:ListSessionGroupsResponse,含两个字段:
session_groups:SessionGroup列表(本次切片内的);total_size:完整过滤排序后列表的总大小(用于前端分页计算,可设为 -1 表示"未知")。
后端实现中,切片逻辑为session_groups[start_index : start_index + slice_size],即实际返回数量为min(slice_size, total_size - start_index)(见 list_session_groups.py)。
3./data/plugin/hparams/metric_evals
返回某个 session 中指定指标的一系列评估值(evaluation)。
Args(请求 proto:ListMetricEvalsRequest)
定义于 api.proto:
| 字段 | 类型 | 说明 |
|---|---|---|
experiment_name | string | 实验名 |
session_name | string | session 的名称 |
metric_name | MetricName | 指标标识(group + tag) |
Returns:一个 JSON 数组,其元素是形如[wall_time, step, value]的三元素数组:
wall_time:评估发生的时间,UNIX 纪元以来的秒数;step:评估发生时所在的训练步;value:指标评估值(标量浮点数)。
为什么用扁平数组而非结构化消息?文档中明确指出:这是为了与 Scalars 插件所期望的指标评估数据格式保持兼容。源码印证了这一点——list_metric_evals.py 的Handler.run()直接把请求转交给 Scalars 插件:
run, tag = metrics.run_tag_from_session_and_metric( self._request.session_name, self._request.metric_name ) body, _ = self._scalars_plugin_instance.scalars_impl( self._request_context, tag, run, self._experiment, scalars_plugin.OutputFormat.JSON, ) return body而hparams_plugin.py的list_metric_evals_route在进入 Handler 之前会先通过_get_scalars_plugin()检查 Scalars 插件是否已加载,未加载则返回 404。
四、核心数据模型:理解 API 的语义基础
要正确调用上述 API,需要理解 api.proto 中定义的数据模型。它们的层级关系为:
Experiment(实验)→ 多个SessionGroup(会话组)→ 多个Session(会话)→ 指标评估值。
Experiment
name:实验全局标识;description:描述(可含 Markdown);user:归属用户或组的 id;time_created_secs:创建时间(UNIX 秒);hparam_infos:实验用到的每个超参数的元信息(HParamInfo:name、display_name、description、数据类型、值域 domain、differs布尔标记);metric_infos:实验用到的每个指标的元信息(MetricInfo:MetricName、display_name、description、DatasetType)。
其中HParamInfo的值域(domain)是一个 oneof,要么是离散值列表domain_discrete(google.protobuf.ListValue),要么是数值区间domain_interval(Interval,闭区间[min_value, max_value])。数据类型DataType有四种:DATA_TYPE_UNSET、DATA_TYPE_STRING、DATA_TYPE_BOOL、DATA_TYPE_FLOAT64。
SessionGroup 与 Session
- SessionGroup:一组共享相同超参数取值的 session 集合。当用户为处理非确定性训练而对同一组超参数重复训练多次时,这些 session 归入同一组;在没有重复实验时,每个组恰好只有一个 session。其
hparams字段是"超参数名 → 值"的映射(map<string, google.protobuf.Value>),metric_values是组内聚合后的指标值列表,sessions是组内 session 列表,另有可选的monitor_url。 - Session:单次训练会话,含
name(实验内唯一)、start_time_secs、end_time_secs(未结束或不可得时为 0)、status、model_uri(如 checkpoint 目录)、metric_values、monitor_url。Status枚举为STATUS_UNKNOWN/SUCCESS/FAILURE/RUNNING。
MetricName:用 (group, tag) 二元组标识指标
指标不靠单一字符串标识,而是MetricName{group, tag}二元组。文档中的设计意图是:group通常对应数据集或子目录(如 validation / training),tag对应标量 summary 的 tag(如 "loss"),这样 UI 可以把同一计算在不同数据集上的指标放到同一张图里对比。
在典型的 TensorFlow 导出设置中,session 的指标以 Scalars 插件 summary 的形式写入 run<session_base_log_dir>/<sub_dir>与某个 tag。换算规则见 metrics.py 的run_tag_from_session_and_metric():run = os.path.join(session_name, metric_name.group)(group 为空时去除结尾斜杠),tag = metric_name.tag。这也是/metric_evals端点能直接把请求转给 Scalars 插件的前提。
五、源码级深度:ColParams 如何实现过滤与排序
ListSessionGroupsRequest.col_params是 API 中功能最密集的部分(见 api.proto),每个ColParams描述一"列"的排序与过滤:
| 字段 | 说明 |
|---|---|
metric/hparam(oneof) | 该列对应哪个指标或超参数 |
order | 排序方向:ORDER_UNSPECIFIED/ORDER_ASC/ORDER_DESC |
missing_values_first | 缺失值是否排在其他值之前(order 未指定时忽略) |
filter_regexp | 仅对字符串超参数有效:正则部分匹配(用^<regexp>$可全匹配) |
filter_interval | 仅对数值列有效:闭区间过滤 |
filter_discrete | 对所有类型有效:显式离散集合 |
exclude_missing_values | 是否排除值为缺失的 session group |
include_in_result | 是否在响应中返回该列;请求中未出现于任何 ColParams 的超参数/指标不会出现在结果中 |
排序规则
list_session_groups.py的_sort()中体现了精确的排序语义:
- 首先按 session group 名排序,保证结果确定性;
- 然后按
col_params中order非ORDER_UNSPECIFIED的子集排序,col_params 的先后顺序决定排序键的优先级(第一个是主排序键,第二个是次级排序键……)。实现上通过逆序遍历并多次sort()达成(后排序的主键优先级最高); - 文档特别注明:session group 名会作为最低优先级的排序键自动追加,因此响应顺序永远确定。
过滤规则
_create_filter()依据filteroneof 构造不同的过滤函数:正则(re.search部分匹配)、闭区间(min <= v <= max)、离散集合(Pythonin语义)。若列的值为缺失(None),则是否通过取决于exclude_missing_values。如果完全不指定filter字段且允许缺失值,则跳过该过滤器(常见情况的性能优化)。
注意list_session_groups.py源码中的一条安全注释:正则过滤器直接使用 Python 的re库,可能被构造出指数级耗时的输入,在迁移到真正的多租户服务器时需要用更安全的实现替换——这属于实现层面的已知注意点。
六、源码级深度:SessionGroup 的指标聚合策略
当同一 session group 内有多个 session 时,aggregation_type决定组级metric_values如何计算(见 list_session_groups.py):
| 聚合类型 | 组级指标值 |
|---|---|
AGGREGATION_AVG(或未指定时的默认值) | 组内各 session 该指标的平均值,training_step为平均步数(截断取整),wall_time_secs为平均值 |
AGGREGATION_MEDIAN | 取"中位 session"的指标值——即aggregation_metric取值中位数对应的那个 session |
AGGREGATION_MIN | 取aggregation_metric取值最小的 session 的指标值 |
AGGREGATION_MAX | 取aggregation_metric取值最大的 session 的指标值 |
对于 MEDIAN/MIN/MAX,源码_measurements()的一个关键细节是:中位数/极值只在"该指标已在组内最大训练步处被测量"的 session 子集内选取;MEDIAN 在组内 session 数为偶数时,选择"较低中间值"的 session 作为代表。
这些行为都有对应的单元测试覆盖,例如 list_session_groups_test.py 中的test_aggregation_median_current_temp、test_aggregation_max_current_temp、test_include_in_result等,分别验证了中位数代表选择、极值代表选择以及include_in_result对响应字段裁剪的效果。
七、数据写入侧:summary 元数据如何与 API 对接
HParams 的数据并非由 API 端点直接采集,而是由训练程序通过 summary 写入,再由 API 端点读取。写入侧的标签常量定义于 metadata.py:
EXPERIMENT_TAG = "_hparams_/experiment":实验元数据,写入空 run;SESSION_START_INFO_TAG = "_hparams_/session_start_info":会话开始信息,写入 run<session_name>;SESSION_END_INFO_TAG = "_hparams_/session_end_info":会话结束信息(状态、结束时间)。
对应的负载消息定义在 plugin_data.proto:HParamsPluginData是一个 oneof(experiment/session_start_info/session_end_info)外加version字段。SessionStartInfo携带超参数值映射(map<string, google.protobuf.Value>)、model_uri、monitor_url、group_name(为空则该 session 自成一组)、start_time_secs;SessionEndInfo携带status与end_time_secs。
list_session_groups.Handler.run()的数据来源有两个路径(见 list_session_groups.py):
- 优先从 summary 标签构建:先尝试从
EXPERIMENT_TAG与SESSION_START_INFO标签元数据构造 SessionGroup; - 回退到 DataProvider:若找不到上述标签,则使用
DataProvider.read_hyperparameters()的结果构建(_session_groups_from_data_provider())。
metadata.py中的parse_session_start_info_plugin_data()等函数在解析时还会校验plugin_data.version,不匹配则抛HParamsError。
八、端到端调用示例
综合以上协议,给出两个可直接套用的调用示例(假设 TensorBoard 运行在本地默认端口 6006)。
GET 方式:获取实验元数据
# 请求 proto 的 JSON:{"experiment_name": "my_exp"} curl "http://localhost:6006/data/plugin/hparams/experiment?request=%7B%22experiment_name%22%3A%22my_exp%22%7D"响应为Experiment消息的 JSON,例如:
{ "name": "my_exp", "hparamInfos": [ { "name": "optimizer", "type": "DATA_TYPE_STRING", "domainDiscrete": {"values": ["adam", "sgd"]}, "differs": true } ], "metricInfos": [ { "name": {"group": "validation", "tag": "loss"}, "datasetType": "DATASET_VALIDATION" } ] }(注意 proto3 JSON 编码中字段名使用 lowerCamelCase。)
POST 方式:列出 session groups 并按指标过滤排序
curl -X POST "http://localhost:6006/data/plugin/hparams/session_groups" \ -H "Content-Type: text/plain" \ -d '{ "experiment_name": "my_exp", "start_index": 0, "slice_size": 20, "aggregation_type": "AGGREGATION_AVG", "allowed_statuses": ["STATUS_SUCCESS", "STATUS_RUNNING"], "col_params": [ {"hparam": "optimizer", "order": "ORDER_ASC", "filter_regexp": "^adam$"}, {"metric": {"group": "validation", "tag": "loss"}, "order": "ORDER_ASC"} ] }'响应ListSessionGroupsResponse的 JSON 形如:
{ "sessionGroups": [ { "name": "group_1", "hparams": {"optimizer": {"stringValue": "adam"}}, "metricValues": [ {"name": {"group": "validation", "tag": "loss"}, "value": 0.31, "trainingStep": 100, "wallTimeSecs": 1600000000.0} ], "sessions": [ {"name": "session_1", "status": "STATUS_SUCCESS", "startTimeSecs": 1599999000.0} ] } ], "totalSize": 42 }GET 方式:读取单个 session 的指标评估序列
curl "http://localhost:6006/data/plugin/hparams/metric_evals?request=%7B%22experiment_name%22%3A%22my_exp%22%2C%22session_name%22%3A%22session_1%22%2C%22metric_name%22%3A%7B%22group%22%3A%22validation%22%2C%22tag%22%3A%22loss%22%7D%7D"响应为 JSON 数组(Scalars 兼容格式):
[ [1600000000.0, 0, 0.62], [1600000010.0, 10, 0.45], [1600000020.0, 20, 0.31] ]九、结语
TensorBoard HParams 插件的 HTTP API 是一个"以 proto 为契约、以 JSON 为传输格式"的轻量 REST 接口。理解它的关键在于把握三点:一是 GET/POST 下请求携带位置的约定,二是三个端点各自请求/响应 proto 的字段语义,三是ColParams与aggregation_type所承载的过滤、排序、聚合能力。结合本仓库中 api.proto、hparams_plugin.py、list_session_groups.py 与 list_session_groups_test.py 等源码,你可以完整追踪从 HTTP 请求到 summary 标签解析、再到 session group 组装与聚合的整条数据链路,为二次开发或故障排查打下坚实基础。
- 数据可视化
- 机器学习
- 前端
- 后端
【免费下载链接】tensorboard
TensorFlow's Visualization Toolkit
相关推荐
Aptos Indexer GRPC File Store 深度实战指南:从 Redis 缓存到云存储的文件化数据落地
Aptos Indexer GRPC File Store 深度实战指南:从 Redis 缓存到云存储的文件化数据落地 Indexer GRPC File St
数据可视化机器学习前端后端OneUptime 权限参考文档深度解析:从 Dashboard 到 API 的单源权限目录
OneUptime 权限参考文档深度解析:从 Dashboard 到 API 的单源权限目录 OneUptime 的权限参考页面( docs/permissio
数据可视化机器学习前端后端TensorBoard 客户端—服务器 HTTP API 指南:`/data` 数据接口与插件路由机制详解
TensorBoard 客户端—服务器 HTTP API 指南: /data 数据接口与插件路由机制详解 TensorBoard 的前端与后端通过一组约定清晰的
数据可视化机器学习前端后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考