API 参考#

以下名称可从顶层 observable_library 0.1.0 包导入。

核心类型#

ObservableSpec(source, selector, transforms=[], reduction="", temporal=None, frequency=1, budget_hint={}) 描述一个可观测量。其稳定 id 包含非默认 temporal 和调度字段。

Observable(spec, compute, tags=set()) 将 spec 与接受 source 张量映射和 runtime context 的 callable 组合起来。手工构造 Observable 属于高级 API;Pack(observables) 是传给执行 API 的稳定可迭代容器。

TypedTensor(value, axes, stage="", provenance={}) 携带张量以及 axis、stage 和 provenance 元数据。__version__ 返回已安装包版本。

生成与 Registry#

generate 是常规 instrumentation 的规范 API。generate(model, reductions=..., transforms=...) 检查模型参数并返回可观测量列表。默认使用全部 13 个已注册 reduction:summeanl1_norml2_normmaxminstdvarianceabs_meannonzero_countpositive_fractionnegative_fractionnumel

M2 扫描每个 model.named_parameters() 条目。它没有公共 source allowlist,也不生成 activation、gradient 或 loss 可观测量。过滤返回列表可得到更小的 Runtime pack;其他 source 请使用高级手工 Observable API。示例见操作指南。

Transform 按给定顺序在 reduction 前执行。因此 transforms=["a", "b"] 表示 b(a(tensor));不会生成子集或排列。注册名称在生成期间解析。张量 rank、shape、dtype 和 device 兼容性仍由 transform 作者负责,只在运行时由实际操作检查。

register_transform(name)register_reduction(name) 是 callable 扩展装饰器。get_transform(name)get_reduction(name) 获取已注册 callable。

张量 Sources#

TensorSource 是 protocol get(source_id, step) -> TypedTensor

HookSource(model) 提供在线参数、activation、gradient 和已记录 loss。训练工作前调用 attach(),结束后调用 detach()FileSource(path) 按 key 从 NPZ 文件读取张量。CheckpointSource(path) 从 Torch state dict 读取 param.* source。

参数读取是惰性的,不需要 attach()。当前 hook attachment 范围较广:会捕获所有顶层子模块 activation 和所有可训练参数 gradient。HookSource 保留最近捕获的值,不验证每个 step 的新鲜度,因此每次观测前都要运行对应的 forward/backward。使用 record_loss(loss, step) 显式记录 loss。

M2 只支持 selector='all'。Runtime 读取 TypedTensor 时,会在 compute context 中以 typed_tensor 传入完整对象,并将其 axesstageprovenance 转发到 ValueSink 元数据。

执行与 Budget#

调用 observe(step, **context) 时,Runtime(observables, tensors=None, source=None, budget=None, sink=None) 计算每个符合条件的可观测量。传入张量映射或 TensorSource;配置的 ValueSink 会收到每个值,同一组值也以字典返回。

生成和手写可观测量可以放入同一列表或 Pack。Runtime 将可迭代对象物化,并拒绝重复 spec id。一次观测内会缓存每个 source id,使多个 reduction 共享一次 source lookup。

Budget(max_compute_ms=None) 限制每次 observe() 调用的可观测量估算成本总和。调度使用以下 ObservableSpec 字段:

  • frequency 必须为正。只有 step % frequency == 0 时 spec 才运行;默认每个 step 都运行。

  • budget_hint 可以包含 compute_ms 估算。估算值必须有限且非负;缺失 hint 按零计算。

  • 设置 max_compute_ms 时,其值必须有限且非负。当可观测量估算值超过剩余 budget 时会被跳过。调度器不测量执行时间,也不改变 spec 的 frequency。

  • generate() 为生成的可观测量提供小的正数 shape-aware heuristic,保守下限为 0.01 ms。它只用于调度输入;budget 重要时,自定义可观测量应提供显式 budget_hint。M2 不作 M3 成本准确性声明:该 heuristic 不是经过校准的成本准确性估算。

OfflineAnalyzer(observables, source, budget=None, sink=None) 公开 analyze(step, **context),并委托给同一条 runtime 计算路径。

Temporal 运算符#

Temporal 函数对显式数值历史运行:

  • delta(values, lag=1) 返回最新值减去 lag 位置的值。

  • ema(values, alpha) 返回 0 < alpha <= 1 时的指数移动平均。

  • slope(values) 返回等间隔样本上的最小二乘斜率。

  • rolling_std(values, window) 返回最近窗口的总体标准差。

ObservableSpec 上的 temporal 字段是包含在 id 中的元数据。M2 的 Runtime 不会自动应用 temporal 函数。

存储与查询#

ValueSink 是 callable protocol (observable_id, step, value, meta) -> NoneLocalStorage(root) 是使用 SQLite 元数据和 NumPy NPZ 数组 payload 的可选实现。query(storage, observable_id, step) 执行受支持的 id/step 读回;它不是通用分析查询引擎。

Observable 没有单独的 display-name 字段。ObservableSpec.id 是从完整 spec 派生的 16 字符存储和结果键。应用可以从 source、transforms 和 reduction 派生可读标签,但 M2 不按该标签查询。

Filter 基础#

继承 Filter 并实现 apply(observables)。Filter 本身也可调用。用 & 组合取交集,用 | 组合取稳定并集。Template filter 及其生成 pipeline 属于 M3。M2 不包含内置 BySourceByReduction filter;用户 filter 作用于已经生成的可观测量列表。

可执行模式和当前限制见usage.md