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:sum、mean、l1_norm、l2_norm、max、min、std、variance、abs_mean、nonzero_count、positive_fraction、negative_fraction 和 numel。
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 传入完整对象,并将其 axes、stage 和 provenance 转发到 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-awareheuristic,保守下限为0.01ms。它只用于调度输入;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) -> None。LocalStorage(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 不包含内置 BySource 或 ByReduction filter;用户 filter 作用于已经生成的可观测量列表。
可执行模式和当前限制见usage.md。