研究

2026-04-02 组会-Analysis Framework

2026-04-02 组会:Analysis Framework

一、框架设计

1. Framework Overview

本框架是 C 端用于 A/B 对齐分析的实验分析框架,工作目录为 /root/flowctl_client/analysis_C。其目标是对 A 端控制序列与 B 端连续出口观测序列进行统一对齐,并在此基础上完成延迟估计、符号恢复与分类指标计算。

该框架面向的不是一次性 trigger-response 实验,而是持续调制实验。在这类实验中,A 端会持续输出控制符号,B 端会持续处于活跃状态,因此分析目标不再是“寻找某次触发后的单次响应”,而是“判断在某个延迟下,A 端不同符号对应的 B 端窗口统计量是否能够稳定分离”。

当前实验形态为:

  • A 端输出控制序列,记录于 A_control_log.jsonl
  • B 端记录连续出口速率,记录于 B_egress_rate.csv
  • 实验为持续下载下的速率调制
  • 典型符号序列为交替 adv_kbps=100adv_kbps=133

2. Directory Layout

框架目录组织如下:

  • bin/
    • analyze_run.py:执行单次实验的对齐、特征提取与指标计算
    • render_report.py:将处理结果转换为 Markdown 报告
    • analyze_all_runs.sh:批量分析脚本
  • config/
    • analyzer.env:lag 扫描范围、步长和阈值相关配置
  • raw/<exp_id>/
    • 保存 B 端原始输入,如 B_egress_rate.csvB_meta.json
  • processed/<exp_id>/
    • 保存中间结果与结构化指标,如 aligned_trace.csvlabels.jsondetection_result.jsonmetrics.json
  • reports/<exp_id>/
    • 保存最终人类可读 Markdown 报告 report.md

该目录设计将原始数据、中间处理结果和最终报告明确分层,便于后续复现实验、排查异常及扩展分析指标。


3. Input Specification

框架依赖三类输入:

  • A side truth log: /root/flowctl_client/runs/<exp_id>/A_control_log.jsonl
  • B side egress trace: /root/flowctl_client/analysis_C/raw/<exp_id>/B_egress_rate.csv
  • B side metadata: /root/flowctl_client/analysis_C/raw/<exp_id>/B_meta.json

其中:

3.1 A-side log

A_control_log.jsonl 提供 A 端控制行为的时间序列记录。当前分析仅使用满足以下条件的记录:

  • event_type == XON
  • 存在 adv_kbps
  • 存在 ts_unix_ms

这些字段分别表示:

  • 事件类型为有效控制事件
  • 当前符号对应的建议速率值
  • 事件发生时间戳

3.2 B-side trace

B_egress_rate.csv 记录 B 端连续出口观测。当前主分析使用字段:

  • ts_ns:纳秒级时间戳,后续统一转换为 ts_unix_ms
  • kbps:对应时刻的出口速率,作为主观测信号

3.3 B-side metadata

B_meta.json 用于补充实验运行信息与上下文元数据。虽然其内容不直接进入当前分类公式,但对实验一致性检查和报表生成仍有辅助价值。


4. Core Analysis Pipeline

框架主流程由五个阶段构成:

  1. 构造 A 端 truth symbol windows
  2. 将 B 端视为连续观测信号
  3. 扫描候选 lag 并评估窗口级可分性
  4. 选取最优 best_lag_ms
  5. 在最优 lag 下完成符号分类与指标计算

下面分别展开。


5. A-side Truth Construction

5.1 Record filtering

首先读取 A_control_log.jsonl,并保留满足分析条件的 XON 记录。此步骤的目的是从原始控制日志中提取可作为真值的符号事件序列。

5.2 Cleanup step 1: dedup within the same millisecond

若同一毫秒存在多条 XON 记录,仅保留最后一条。这样处理的原因是:

  • 在启动或状态切换时,日志可能在同一时间戳下连续记录多个临时值
  • 同一时刻真正生效的状态应视为最后一次写入的状态
  • 如果不去重,会导致同一时刻被错误拆成多个符号

5.3 Cleanup step 2: keep only change points

在时间顺序上,仅保留 adv_kbps 发生变化的位置。这样做的原因是:

  • 如果 A 端连续多次记录相同 adv_kbps,这些记录并不对应新的符号切换
  • 对齐分析关心的是符号边界,而不是重复日志条目

完成上述两步清理后,得到一个按时间排序的 change-point 序列。

5.4 Convert change points into symbol windows

随后,将相邻 change points 转换为 symbol windows。每个窗口由以下字段定义:

  • a_start_ts_unix_ms:符号起始时间
  • a_end_ts_unix_ms:符号结束时间
  • a_adv_kbps:该窗口内 A 端符号值
  • a_label:用于分类评估的二值真值标签

该转换的本质是将离散事件日志重建为一段分段常值信号,以便与 B 端连续时间序列按区间对齐。

5.5 Binary labeling rule

当前版本采用简单的二值标签规则:

  • 当前 run 中最低 adv_kbps 档位记为 0
  • 任何更高 adv_kbps 档位记为 1

因此在本实验中:

  • 100 -> label 0
  • 133 -> label 1

这一设计适合当前二值持续调制场景,同时也明确指出:当前框架属于 binary modulation v1,不直接支持多档位多分类。


6. B-side Observation Modeling

6.1 Continuous-signal view

B 端 B_egress_rate.csv 不再被解释为由若干独立响应事件构成,而是被视为一个连续时间观测信号。这一建模假设更符合持续下载任务,因为:

  • B 端始终处于传输过程中
  • 速率变化具有连续性而不是瞬时离散跳变
  • 单个窗口的观测值可能受前后窗口残留影响

因此,分析对象不再是“某个 rise 事件”,而是“某个时间区间上的统计特征”。

6.2 Main signal field

主分析使用 B 端的 kbps 作为连续观测值,并将 ts_ns 统一换算到 ts_unix_ms 时间轴,以便与 A 端窗口对齐。

6.3 Legacy state-machine output

脚本仍保留旧逻辑派生的 B_state_machine.csv,其中包含:

  • is_low
  • low_streak
  • zero_armed
  • rise_1

但该文件仅作为诊断性 side output。它可以帮助检查:

  • B 端是否曾显著回到低状态
  • 旧逻辑在某些特殊 run 中为何失效
  • 当前 run 是否存在明显异常

7. Lag-Scan Based Alignment

7.1 Main assumption

当前框架采用如下假设:

  • A 端是已知真实调制序列
  • B 端是该序列经过传播时延、网络抖动和缓冲平滑后的延迟观测

因此,与其逐事件匹配,不如扫描候选 lag,并检验在该 lag 下高低符号窗口的可分性是否最强。

7.2 Lag search range

lag 扫描范围由 config/analyzer.env 控制,主要参数包括:

  • DELAY_MIN_MS
  • DELAY_MAX_MS
  • LAG_STEP_MS

当前配置为:

  • 最小 lag:0 ms
  • 最大 lag:5000 ms
  • 扫描步长:100 ms

因此,候选 lag 集合为:

1
0, 100, 200, ..., 5000 ms

7.3 Per-lag window alignment

对每一个候选 lag,执行如下步骤:

  1. 将所有 A-side symbol windows 整体向后平移该 lag
  2. 在 B 端截取落入平移后窗口区间内的所有采样点
  3. 对每个窗口计算聚合统计量
  4. 将这些窗口值按 A 标签划分为 high group 与 low group
  5. 计算该 lag 下的类间可分性指标

这里的核心是:对齐是在窗口层面而不是事件层面完成的。

7.4 Window-level B features

当前框架为每个对齐后的窗口计算多个 B-side 聚合特征:

  • b_mean_kbps
  • b_median_kbps
  • b_max_kbps
  • b_p90_kbps

其中,当前分类与可分性分析的主特征是:

  • b_mean_kbps

保留其他统计量的原因是:

  • 便于后续扩展更稳健的分类器
  • 便于分析异常窗口
  • 便于比较不同聚合统计量对分离效果的影响

8. Best Lag Selection by Separability

8.1 Separation score

对于每个候选 lag,框架计算:

1
separation_score = (mean_high - mean_low) / (std_high + std_low + eps)

其中:

  • mean_high:A 标签为 1 的窗口在 B 端 b_mean_kbps 的均值
  • mean_low:A 标签为 0 的窗口在 B 端 b_mean_kbps 的均值
  • std_high:高符号窗口 b_mean_kbps 的总体标准差
  • std_low:低符号窗口 b_mean_kbps 的总体标准差
  • eps:防止分母为零的极小项

8.2 Interpretation

该分数可解释为“类间距离相对于类内波动的归一化程度”:

  • 分子越大,说明高低两类中心差距越大
  • 分母越大,说明两类内部噪声越强
  • 因此,分数越大,说明该 lag 下两类越容易分离

具体而言:

  • separation_score > 0:高符号窗口整体上高于低符号窗口
  • 接近 0:两类高度重叠
  • 小于 0:当前 lag 与真实传播延迟不匹配

8.3 Why this criterion is used

选择 separability 而非单点误差最小化的原因在于:

  • 当前实验目标是恢复符号类别,而非拟合某条连续曲线
  • 持续调制实验中,B 端观测受窗口平滑与残留影响,单事件误差不稳定
  • 类间可分性更直接对应“该延迟是否能支持可靠分类”

8.4 Best lag selection rule

最终,将 separation_score 最大的 lag 记为:

  • best_lag_ms

这意味着:当前框架将“使高低类最容易分开”的延迟,作为 A 到 B 的最佳估计传播时延。


9. Classification After Lag Fixing

9.1 Final aligned trace

在确定 best_lag_ms 后,框架生成最终 aligned_trace.csv。该文件是最关键的中间结果,每一行对应一个 A-side symbol window 在 B 端的对齐结果。

关键字段包括:

  • symbol_idx
  • a_start_ts_iso, a_end_ts_iso
  • a_adv_kbps
  • a_label
  • best_lag_ms
  • b_mean_kbps, b_median_kbps, b_max_kbps, b_p90_kbps
  • b_pred_label
  • has_valid_b_window

9.2 Threshold definition

在固定最优 lag 后,框架不再继续搜索分类阈值,而是直接使用:

1
classification_threshold_kbps = (median_high_kbps + median_low_kbps) / 2

其中:

  • median_high_kbps:所有 A 标签为 1 的 aligned windows 中,b_mean_kbps 的中位数
  • median_low_kbps:所有 A 标签为 0 的 aligned windows 中,b_mean_kbps 的中位数

9.3 Rationale for median-midpoint threshold

该阈值定义具有三个优点:

  1. 鲁棒性更强。 中位数相较均值更不容易受尖峰值影响。
  2. 解释性更好。 阈值位于两类中心趋势之间,符合直观分类边界。
  3. 避免过拟合。 阈值由类分布直接给出,而不是针对单次 run 复杂调参。

最终分类规则为:

1
b_pred_label = 1 if b_mean_kbps >= classification_threshold_kbps else 0

10. Output Files and Their Roles

10.1 aligned_trace.csv

最重要的中间文件,用于保存窗口级对齐结果。它支撑:

  • 单窗口案例检查
  • 错误样本定位
  • 可视化与后续统计分析

10.2 labels.json

记录标签与阈值定义,包括:

  • A 侧标签映射规则
  • B 侧预测标签规则
  • best_lag_ms
  • classification_threshold_kbps

10.3 detection_result.json

保存分类评估结果,包括:

  • accuracy
  • precision
  • recall
  • f1
  • fpr
  • fnr
  • confusion matrix

10.4 metrics.json

保存整体对齐与分类质量摘要,包括:

  • 符号数量统计
  • best_lag_ms
  • separation_score
  • 高低类统计特征
  • window_coverage_rate
  • 分类指标
  • 附加说明

10.5 B_state_machine.csv

仅作为调试辅助输出,用于与旧方法对照,不作为主报告结论依据。


11. Metric Definitions

11.1 Delay and alignment metrics

  • best_lag_ms
    • 使高低类窗口在 B 端最可分的延迟估计
  • separation_score
    • 当前 lag 下的类间可分性得分,值越大越好
  • mean_high_kbps
    • A=1 窗口对应的 B-side b_mean_kbps 均值
  • mean_low_kbps
    • A=0 窗口对应的 B-side b_mean_kbps 均值
  • median_high_kbps
    • A=1 窗口对应的 B-side b_mean_kbps 中位数
  • median_low_kbps
    • A=0 窗口对应的 B-side b_mean_kbps 中位数
  • window_coverage_rate
    • 经过最优 lag 平移后,仍能提取到有效 B-side 样本的窗口占比
  • classification_threshold_kbps
    • 最终对 b_mean_kbps 执行分类时使用的阈值

11.2 Classification metrics

在固定最佳 lag 与阈值后,计算如下指标:

  • accuracy = (TP + TN) / (TP + TN + FP + FN)
  • precision = TP / (TP + FP)
  • recall = TP / (TP + FN)
  • f1 = 2 * precision * recall / (precision + recall)
  • fpr = FP / (FP + TN)
  • fnr = FN / (FN + TP)

11.3 Confusion matrix terms

  • tp:A-label-1 被正确预测为 1
  • tn:A-label-0 被正确预测为 0
  • fp:A-label-0 被误判为 1
  • fn:A-label-1 被误判为 0

二、原始实验报告

Summary

  • first_symbol_ts: 2026-03-31T07:25:55-04:00
  • last_symbol_ts: 2026-03-31T08:50:28-04:00
  • best_lag_ms: 1400
  • classification_threshold_kbps: 934.272

Metrics

metric value
symbol_count_total 1401
symbol_count_high 700
symbol_count_low 701
best_lag_ms 1400
separation_score 0.245
mean_high_kbps 1076.346
mean_low_kbps 851.456
median_high_kbps 1044.360
median_low_kbps 824.184
window_coverage_rate 1.000
accuracy 0.989
precision 0.983
recall 0.994
f1 0.989
fpr 0.017
fnr 0.006

Confusion Matrix

item value
tp 696
tn 689
fp 12
fn 4

Notes

  • none

Sample Aligned Windows

symbol_idx a_adv_kbps a_label b_mean_kbps b_pred_label best_lag_ms
0 100 0 826.9019999999998 0 1400
1 133 1 1042.0480000000007 1 1400
2 100 0 812.1499999999978 0 1400
3 133 1 1053.8739999999984 1 1400
4 100 0 819.2459999999992 0 1400
5 133 1 1035.1860000000001 1 1400
6 100 0 959.6419999999983 1 1400
7 133 1 1038.453999999995 1 1400
8 100 0 808.4479999999982 0 1400
9 133 1 1039.6280000000029 1 1400
10 100 0 811.0399999999936 0 1400
11 133 1 1050.5640000000028 1 1400

三、实验结果分析

这一部分开始进入具体实验结果。

1. 样本数量与平衡性

  • symbol_count_total = 1401
  • symbol_count_high = 700
  • symbol_count_low = 701

这说明本次实验总共分析了 1401 个符号窗口,而且高低符号几乎完全平衡。

这个平衡性很重要,因为这样分类准确率不会被类别分布偏置影响。

2. separation_score = 0.245

这个指标表示高低两类在 B 端观测值上的可分离程度。

可以这样讲:

  • 这个值越大,说明两类越容易分开。
  • 这个值不是特别夸张地大,说明两类并不是完全没有重叠。
  • 但后面的分类结果依然很高,说明虽然存在一定重叠,但整体上仍然足够区分。

所以这个值传达的信息是:

两类不是完全分离,但已经具备稳定可判别性。

3. 高低符号在 B 端的均值和中位数

  • mean_high_kbps = 1076.346
  • mean_low_kbps = 851.456
  • median_high_kbps = 1044.360
  • median_low_kbps = 824.184

这四个值可以一起讲。

先看均值,高符号比低符号大约高出:

  • 1076.346 - 851.456 ≈ 224.89 kbps

再看中位数,高符号和低符号也有明显差距。

这说明:

  • A 端的高低速率调制,确实在 B 端留下了清楚的统计差异。
  • 这种差异不是少数异常值造成的,因为中位数也同样分开了。

所以这里的核心结论是:

高低符号在 B 端的观测分布中心是明显分离的。

4. window_coverage_rate = 1.000

这个指标表示窗口覆盖率是 100%。

也就是说,1401 个符号窗口全部都成功对齐并参与了分析,没有出现大面积丢窗或无效窗口。

这说明实验数据完整性很好。


2. 分类效果

1. accuracy = 0.989

总体准确率是 98.9%。

也就是在全部 1401 个符号窗口里,有 98.9% 被正确恢复。

这已经说明恢复效果非常强。

2. precision = 0.983

精确率表示:所有被预测成高符号 1 的窗口里,有 98.3% 真实就是 1。

这个值高,说明误报不多。

3. recall = 0.994

召回率表示:所有真实的高符号 1 里,有 99.4% 被成功检测出来。

这个值更高,说明漏检很少。

4. f1 = 0.989

F1 是 precision 和 recall 的综合指标。

接近 0.99,说明整体分类质量非常稳定。

5. fpr 和 fnr

  • fpr = 0.017
  • fnr = 0.006

可以讲成:

  • 真正的低符号中,只有 1.7% 被误判成高符号。
  • 真正的高符号中,只有 0.6% 被误判成低符号。

这说明系统对高符号尤其敏感,漏检率很低。


3. 混淆矩阵

混淆矩阵如下:

  • tp = 696
  • tn = 689
  • fp = 12
  • fn = 4

你可以直接这样给老师解释:

  • 696 个高符号被正确识别出来。
  • 689 个低符号被正确识别出来。
  • 只有 12 个低符号被误报成高符号。
  • 只有 4 个高符号被漏判成低符号。

所以总错误数只有:

  • 12 + 4 = 16

总正确数是:

  • 696 + 689 = 1385

这就是为什么准确率能达到 98.9%。

这里可以顺着给出一句结论:

B 端几乎可以完整恢复 A 端的二值符号序列。


4. Sample Aligned Windows

这张表是一些具体样本,用来展示分类过程不是黑箱,而是可以落到单个窗口上检查的。

例如:

样本 0

  • A 端发出 100 kbps
  • 标签是 0
  • B 端测得平均吞吐率 826.902 kbps
  • 低于阈值 934.272 kbps
  • 所以预测成 0

这个分类是正确的。

样本 1

  • A 端发出 133 kbps
  • 标签是 1
  • B 端测得平均吞吐率 1042.048 kbps
  • 高于阈值
  • 所以预测成 1

这个分类也是正确的。

样本 6

  • A 端发出 100 kbps
  • 标签是 0
  • 但 B 端测得 959.642 kbps
  • 高于阈值 934.272 kbps
  • 所以被误判成 1

这个样本很有价值,因为它解释了错误是怎么来的。

也就是说,虽然 A 端真实发的是低符号,但由于网络波动、缓冲残留或者窗口串扰,B 端这个窗口的平均吞吐率被抬高了,于是被分错。