diff --git a/example/plot_benchmark.py b/example/plot_benchmark.py
new file mode 100644
index 0000000..a32dfb1
--- /dev/null
+++ b/example/plot_benchmark.py
@@ -0,0 +1,956 @@
+#!/usr/bin/env python3
+
+import argparse
+import csv
+import json
+import math
+from pathlib import Path
+
+
+def parse_args():
+ parser = argparse.ArgumentParser(description="Plot benchmark metrics from benchmark_history.csv")
+ base_dir = Path(__file__).resolve().parent
+ parser.add_argument(
+ "--figure",
+ choices=["panel", "summary"],
+ default="panel",
+ help="Figure type: panel (paper-style multi-panel) or summary (seed robustness only).",
+ )
+ parser.add_argument(
+ "--history",
+ default=str(base_dir / "results" / "benchmark_history.csv"),
+ help="Path to benchmark_history.csv",
+ )
+ parser.add_argument(
+ "--ks-per-feature",
+ default=str(base_dir / "results" / "ks_per_feature.csv"),
+ help="Path to ks_per_feature.csv",
+ )
+ parser.add_argument(
+ "--data-shift",
+ default=str(base_dir / "results" / "data_shift_stats.csv"),
+ help="Path to data_shift_stats.csv",
+ )
+ parser.add_argument(
+ "--metrics-history",
+ default=str(base_dir / "results" / "metrics_history.csv"),
+ help="Path to metrics_history.csv",
+ )
+ parser.add_argument(
+ "--filtered-metrics",
+ default=str(base_dir / "results" / "filtered_metrics.json"),
+ help="Path to filtered_metrics.json (optional).",
+ )
+ parser.add_argument(
+ "--out",
+ default="",
+ help="Output SVG path (default depends on --figure).",
+ )
+ parser.add_argument(
+ "--engine",
+ choices=["auto", "matplotlib", "svg"],
+ default="auto",
+ help="Plotting engine: auto prefers matplotlib if available; otherwise uses pure-SVG.",
+ )
+ return parser.parse_args()
+
+
+def mean_std(vals):
+ m = sum(vals) / len(vals)
+ if len(vals) == 1:
+ return m, 0.0
+ v = sum((x - m) * (x - m) for x in vals) / (len(vals) - 1)
+ return m, math.sqrt(v)
+
+
+def svg_escape(s):
+ return (
+ str(s)
+ .replace("&", "&")
+ .replace("<", "<")
+ .replace(">", ">")
+ .replace('"', """)
+ .replace("'", "'")
+ )
+
+
+def clamp(v, lo, hi):
+ if v < lo:
+ return lo
+ if v > hi:
+ return hi
+ return v
+
+
+def lerp(a, b, t):
+ return a + (b - a) * t
+
+
+def hex_to_rgb(h):
+ h = h.lstrip("#")
+ return int(h[0:2], 16), int(h[2:4], 16), int(h[4:6], 16)
+
+
+def rgb_to_hex(r, g, b):
+ return "#{:02x}{:02x}{:02x}".format(int(clamp(r, 0, 255)), int(clamp(g, 0, 255)), int(clamp(b, 0, 255)))
+
+
+def diverging_color(v, vmin=-2.0, vmax=2.0, cold="#2563eb", hot="#ef4444", mid="#ffffff"):
+ v = clamp(v, vmin, vmax)
+ if v >= 0:
+ t = 0.0 if vmax == 0 else v / vmax
+ r0, g0, b0 = hex_to_rgb(mid)
+ r1, g1, b1 = hex_to_rgb(hot)
+ return rgb_to_hex(lerp(r0, r1, t), lerp(g0, g1, t), lerp(b0, b1, t))
+ t = 0.0 if vmin == 0 else (-v) / (-vmin)
+ r0, g0, b0 = hex_to_rgb(mid)
+ r1, g1, b1 = hex_to_rgb(cold)
+ return rgb_to_hex(lerp(r0, r1, t), lerp(g0, g1, t), lerp(b0, b1, t))
+
+
+def plot_matplotlib(rows, seeds, metrics, out_path):
+ import matplotlib.pyplot as plt
+
+ try:
+ plt.style.use("seaborn-v0_8-whitegrid")
+ except Exception:
+ pass
+
+ fig, axes = plt.subplots(nrows=len(metrics), ncols=1, figsize=(8.6, 4.6), sharex=False)
+ if len(metrics) == 1:
+ axes = [axes]
+
+ point_color = "#3b82f6"
+ band_color = "#ef4444"
+ grid_color = "#e5e7eb"
+ axis_color = "#111827"
+
+ for ax, (key, title) in zip(axes, metrics, strict=True):
+ vals = [r[key] for r in rows]
+ m, s = mean_std(vals)
+
+ vmin = min(vals + [m - s])
+ vmax = max(vals + [m + s])
+ if vmax == vmin:
+ vmax = vmin + 1.0
+ vr = vmax - vmin
+ vmin -= 0.20 * vr
+ vmax += 0.20 * vr
+
+ y0 = 0.0
+ jitter = [-0.08, 0.0, 0.08]
+ ys = [(y0 + jitter[i % len(jitter)]) for i in range(len(vals))]
+
+ ax.axvspan(m - s, m + s, color=band_color, alpha=0.10, linewidth=0)
+ ax.axvline(m, color=band_color, linewidth=2.2)
+
+ ax.scatter(vals, ys, s=46, color=point_color, edgecolors="white", linewidths=1.0, zorder=3)
+ for x, y, seed in zip(vals, ys, seeds, strict=True):
+ ax.annotate(
+ str(seed),
+ (x, y),
+ textcoords="offset points",
+ xytext=(0, 10),
+ ha="center",
+ va="bottom",
+ fontsize=8,
+ color=axis_color,
+ )
+
+ ax.set_title(title, loc="left", fontsize=11, color=axis_color, pad=8)
+ ax.set_yticks([])
+ ax.set_ylim(-0.35, 0.35)
+ ax.set_xlim(vmin, vmax)
+ ax.grid(True, axis="x", color=grid_color)
+ ax.grid(False, axis="y")
+
+ ax.text(
+ 0.99,
+ 0.80,
+ "mean={m:.4f} ± {s:.4f}".format(m=m, s=s),
+ transform=ax.transAxes,
+ ha="right",
+ va="center",
+ fontsize=9,
+ color="#374151",
+ )
+
+ fig.suptitle("Benchmark Metrics (3 seeds) · lower is better", fontsize=12, color=axis_color, y=0.98)
+ fig.tight_layout(rect=(0, 0, 1, 0.95))
+ out_path.parent.mkdir(parents=True, exist_ok=True)
+ fig.savefig(out_path, format="svg")
+ plt.close(fig)
+
+
+def plot_svg(rows, seeds, metrics, out_path):
+ W, H = 980, 440
+ pad_l, pad_r, pad_t, pad_b = 200, 30, 74, 36
+ row_gap = 52
+ row_h = (H - pad_t - pad_b - row_gap * (len(metrics) - 1)) / len(metrics)
+
+ bg = "#ffffff"
+ axis = "#2b2b2b"
+ grid = "#e9e9e9"
+ band = "#d62728"
+ band_fill = "#d62728"
+ point = "#1f77b4"
+ text = "#111111"
+ subtle = "#666666"
+
+ parts = []
+ parts.append(
+ "")
+ out_path.parent.mkdir(parents=True, exist_ok=True)
+ out_path.write_text("\n".join(parts), encoding="utf-8")
+
+
+def read_csv_rows(path):
+ p = Path(path)
+ if not p.exists():
+ return []
+ with p.open("r", encoding="utf-8", newline="") as f:
+ reader = csv.DictReader(f)
+ return list(reader)
+
+
+def read_json(path):
+ p = Path(path)
+ if not p.exists():
+ return None
+ return json.loads(p.read_text(encoding="utf-8"))
+
+
+def parse_float(s):
+ if s is None:
+ return None
+ ss = str(s).strip()
+ if ss == "" or ss.lower() == "none" or ss.lower() == "nan":
+ return None
+ return float(ss)
+
+
+def zscores(vals):
+ if not vals:
+ return []
+ m = sum(vals) / len(vals)
+ v = sum((x - m) * (x - m) for x in vals) / len(vals)
+ s = math.sqrt(v)
+ if s == 0:
+ return [0.0 for _ in vals]
+ return [(x - m) / s for x in vals]
+
+
+def panel_svg(bh_rows, ks_rows, shift_rows, hist_rows, filtered_metrics, out_path):
+ W, H = 1400, 900
+ margin = 42
+ gap = 26
+
+ panel_w = (W - margin * 2 - gap) / 2
+ panel_h = (H - margin * 2 - gap) / 2
+
+ bg = "#ffffff"
+ ink = "#111827"
+ subtle = "#6b7280"
+ border = "#e5e7eb"
+ grid = "#eef2f7"
+ blue = "#3b82f6"
+ red = "#ef4444"
+ green = "#10b981"
+
+ def panel_rect(x, y):
+ return "".format(
+ x=x, y=y, w=panel_w, h=panel_h, b=border
+ )
+
+ def text(x, y, s, size=12, anchor="start", color=ink, weight="normal"):
+ return "{t}".format(
+ x=x, y=y, a=anchor, fs=size, c=color, w=weight, t=svg_escape(s)
+ )
+
+ def line(x1, y1, x2, y2, color=border, width=1.0, dash=None, opacity=1.0, cap="round"):
+ extra = ""
+ if dash:
+ extra += " stroke-dasharray='{d}'".format(d=dash)
+ if opacity != 1.0:
+ extra += " stroke-opacity='{o}'".format(o=opacity)
+ return "".format(
+ x1=x1, y1=y1, x2=x2, y2=y2, c=color, w=width, cap=cap, extra=extra
+ )
+
+ def round_box(x, y, w, h, fill="#ffffff", stroke=border, sw=1.2, rx=12):
+ return "".format(
+ x=x, y=y, w=w, h=h, rx=rx, f=fill, s=stroke, sw=sw
+ )
+
+ def arrow(x1, y1, x2, y2, color=ink, width=1.8):
+ ang = math.atan2(y2 - y1, x2 - x1)
+ ah = 10.0
+ aw = 5.0
+ hx = x2 - ah * math.cos(ang)
+ hy = y2 - ah * math.sin(ang)
+ px = aw * math.sin(ang)
+ py = -aw * math.cos(ang)
+ p1x, p1y = hx + px, hy + py
+ p2x, p2y = hx - px, hy - py
+ return (
+ ""
+ ""
+ ).format(x1=x1, y1=y1, x2=x2, y2=y2, c=color, w=width, p1x=p1x, p1y=p1y, p2x=p2x, p2y=p2y)
+
+ parts = []
+ parts.append(
+ "")
+ out_path.parent.mkdir(parents=True, exist_ok=True)
+ out_path.write_text("\n".join(parts), encoding="utf-8")
+
+
+def panel_matplotlib(bh_rows, ks_rows, shift_rows, hist_rows, filtered_metrics, out_path):
+ import matplotlib.pyplot as plt
+ import matplotlib.patches as patches
+
+ try:
+ plt.style.use("seaborn-v0_8-whitegrid")
+ except Exception:
+ pass
+
+ fig = plt.figure(figsize=(13.6, 8.6))
+ gs = fig.add_gridspec(2, 2, wspace=0.18, hspace=0.22)
+
+ axA = fig.add_subplot(gs[0, 0])
+ axB = fig.add_subplot(gs[0, 1])
+ axC = fig.add_subplot(gs[1, 0])
+ axD = fig.add_subplot(gs[1, 1])
+
+ fig.suptitle("Benchmark Overview (HAI Security Dataset)", fontsize=16, y=0.98)
+
+ axA.set_title("A Typed Hybrid Generation", loc="left", fontsize=12, fontweight="bold")
+ axA.axis("off")
+ axA.set_xlim(0, 1)
+ axA.set_ylim(0, 1)
+ box_y = 0.55
+ box_w = 0.18
+ box_h = 0.16
+ x_positions = [0.06, 0.30, 0.54, 0.78]
+ labels = ["HAI windows\n(L=96)", "Typed\ndecomposition", "Hybrid\ngenerator", "Synthetic\nwindows"]
+ for x, lbl in zip(x_positions, labels, strict=True):
+ axA.add_patch(patches.FancyBboxPatch((x, box_y), box_w, box_h, boxstyle="round,pad=0.02,rounding_size=0.02", facecolor="#f8fafc", edgecolor="#e5e7eb"))
+ axA.text(x + box_w / 2, box_y + box_h / 2, lbl, ha="center", va="center", fontsize=10, fontweight="bold")
+ for i in range(3):
+ x1 = x_positions[i] + box_w
+ x2 = x_positions[i + 1]
+ axA.annotate("", xy=(x2, box_y + box_h / 2), xytext=(x1, box_y + box_h / 2), arrowprops=dict(arrowstyle="-|>", lw=1.4, color="#6b7280"))
+
+ hx = x_positions[2]
+ hy = 0.20
+ axA.text(hx, hy + 0.27, "Type-aware routes", fontsize=9, color="#6b7280", fontweight="bold")
+ inner = [("Trend (det.)", "#e0f2fe", "#3b82f6"), ("Residual (DDPM)", "#fee2e2", "#ef4444"), ("Discrete head", "#dcfce7", "#10b981")]
+ for k, (name, fc, ec) in enumerate(inner):
+ y = hy + 0.18 - k * 0.11
+ axA.add_patch(patches.FancyBboxPatch((hx, y), box_w, 0.08, boxstyle="round,pad=0.02,rounding_size=0.02", facecolor=fc, edgecolor=ec, lw=1.2))
+ axA.text(hx + 0.01, y + 0.04, name, ha="left", va="center", fontsize=9, fontweight="bold")
+ axA.annotate("", xy=(hx + box_w / 2, hy + 0.20), xytext=(hx + box_w / 2, box_y), arrowprops=dict(arrowstyle="-|>", lw=1.2, color="#6b7280"))
+ axA.text(0.06, 0.06, "Metrics align with types: KS (continuous), JSD (discrete), lag-1 (temporal).", fontsize=9, color="#6b7280")
+
+ axB.set_title("B Feature-Level Distribution Fidelity", loc="left", fontsize=12, fontweight="bold")
+ ks_sorted = sorted(
+ [
+ {
+ "feature": r.get("feature", ""),
+ "ks": parse_float(r.get("ks")),
+ "gen_frac_at_min": parse_float(r.get("gen_frac_at_min")) or 0.0,
+ "gen_frac_at_max": parse_float(r.get("gen_frac_at_max")) or 0.0,
+ }
+ for r in ks_rows
+ if parse_float(r.get("ks")) is not None
+ ],
+ key=lambda x: x["ks"],
+ reverse=True,
+ )
+ top = ks_sorted[:14]
+ feats = [r["feature"] for r in top][::-1]
+ vals = [r["ks"] for r in top][::-1]
+ collapsed = [((r["gen_frac_at_min"] >= 0.98) or (r["gen_frac_at_max"] >= 0.98)) for r in top][::-1]
+ colors = ["#fb7185" if c else "#0ea5e9" for c in collapsed]
+ axB.barh(feats, vals, color=colors)
+ axB.set_xlabel("KS (lower is better)")
+ axB.set_xlim(0, 1.0)
+ if isinstance(filtered_metrics, dict) and filtered_metrics.get("dropped_features"):
+ dropped = ", ".join(d.get("feature", "") for d in filtered_metrics["dropped_features"] if d.get("feature"))
+ if dropped:
+ axB.text(0.99, 0.02, "dropped: {d}".format(d=dropped), transform=axB.transAxes, ha="right", va="bottom", fontsize=9, color="#6b7280")
+
+ axC.set_title("C Dataset Shift Across Training Files", loc="left", fontsize=12, fontweight="bold")
+ if shift_rows:
+ cols = list(shift_rows[0].keys())
+ else:
+ cols = []
+ mean_cols = [c for c in cols if c.startswith("mean_")]
+ wanted = ["mean_P1_FT01", "mean_P1_LIT01", "mean_P1_PIT01", "mean_P2_CO_rpm", "mean_P3_LIT01", "mean_P4_ST_PT01"]
+ feats = [c for c in wanted if c in mean_cols]
+ files = [r.get("file", "") for r in shift_rows]
+ M = []
+ for c in feats:
+ M.append([parse_float(r.get(c)) or 0.0 for r in shift_rows])
+ if M and files and feats:
+ Z = list(zip(*[zscores(col) for col in M], strict=True))
+ im = axC.imshow(Z, aspect="auto", cmap="coolwarm", vmin=-2, vmax=2)
+ axC.set_yticks(range(len(files)))
+ axC.set_yticklabels(files)
+ axC.set_xticks(range(len(feats)))
+ axC.set_xticklabels([f.replace("mean_", "") for f in feats], rotation=25, ha="right")
+ axC.set_ylabel("Train file")
+ axC.set_xlabel("Feature mean z-score")
+ fig.colorbar(im, ax=axC, fraction=0.046, pad=0.04)
+ else:
+ axC.axis("off")
+ axC.text(0.5, 0.5, "missing data_shift_stats.csv", ha="center", va="center", fontsize=11, color="#6b7280")
+
+ axD.set_title("D Robustness Across Seeds", loc="left", fontsize=12, fontweight="bold")
+ axD.axis("off")
+ axD.set_xlim(0, 1)
+ axD.set_ylim(0, 1)
+ metrics = [("avg_ks", "KS (cont.)"), ("avg_jsd", "JSD (disc.)"), ("avg_lag1_diff", "Abs Δ lag-1")]
+ bh_rows = sorted(bh_rows, key=lambda r: r.get("seed", 0))
+ for mi, (k, title) in enumerate(metrics):
+ vals = [r.get(k) for r in bh_rows if r.get(k) is not None]
+ if not vals:
+ continue
+ m, s = mean_std(vals)
+ y = 0.78 - mi * 0.22
+ axD.text(0.04, y, title, fontsize=10, fontweight="bold", va="center")
+ x0 = 0.42
+ x1 = 0.96
+ vmin = min(vals + [m - s])
+ vmax = max(vals + [m + s])
+ if vmax == vmin:
+ vmax = vmin + 1.0
+ vr = vmax - vmin
+ vmin -= 0.15 * vr
+ vmax += 0.15 * vr
+
+ def X(v):
+ return x0 + (v - vmin) * (x1 - x0) / (vmax - vmin)
+
+ axD.add_patch(patches.FancyBboxPatch((X(m - s), y - 0.03), max(0.002, X(m + s) - X(m - s)), 0.06, boxstyle="round,pad=0.01,rounding_size=0.02", facecolor="#ef4444", alpha=0.12, edgecolor="none"))
+ axD.plot([X(m), X(m)], [y - 0.05, y + 0.05], color="#ef4444", lw=2.2)
+ jit = [-0.03, 0.0, 0.03]
+ for i, v in enumerate(vals):
+ axD.scatter([X(v)], [y + jit[i % len(jit)]], s=40, color="#3b82f6", edgecolor="white", linewidth=0.9, zorder=3)
+ axD.text(0.96, y + 0.07, "mean={m:.4f}±{s:.4f}".format(m=m, s=s), fontsize=9, color="#6b7280", ha="right")
+
+ fig.tight_layout(rect=(0, 0, 1, 0.96))
+ out_path.parent.mkdir(parents=True, exist_ok=True)
+ fig.savefig(out_path, format="svg")
+ plt.close(fig)
+
+
+def main():
+ args = parse_args()
+ hist_path = Path(args.history)
+ if not hist_path.exists():
+ raise SystemExit("missing history file: %s" % hist_path)
+
+ rows = []
+ with hist_path.open("r", encoding="utf-8", newline="") as f:
+ reader = csv.DictReader(f)
+ for r in reader:
+ rows.append(
+ {
+ "run_name": r["run_name"],
+ "seed": int(r["seed"]),
+ "avg_ks": float(r["avg_ks"]),
+ "avg_jsd": float(r["avg_jsd"]),
+ "avg_lag1_diff": float(r["avg_lag1_diff"]),
+ }
+ )
+
+ if not rows:
+ raise SystemExit("no rows in history file: %s" % hist_path)
+
+ rows = sorted(rows, key=lambda x: x["seed"])
+ seeds = [str(r["seed"]) for r in rows]
+
+ metrics = [
+ ("avg_ks", "KS (continuous)"),
+ ("avg_jsd", "JSD (discrete)"),
+ ("avg_lag1_diff", "Abs Δ lag-1 autocorr"),
+ ]
+
+ if args.out:
+ out_path = Path(args.out)
+ else:
+ if args.figure == "panel":
+ out_path = Path(__file__).resolve().parent.parent / "figures" / "benchmark_panel.svg"
+ else:
+ out_path = Path(__file__).resolve().parent.parent / "figures" / "benchmark_metrics.svg"
+
+ if args.figure == "summary":
+ if args.engine in {"auto", "matplotlib"}:
+ try:
+ plot_matplotlib(rows, seeds, metrics, out_path)
+ print("saved", out_path)
+ return
+ except Exception:
+ if args.engine == "matplotlib":
+ raise
+ plot_svg(rows, seeds, metrics, out_path)
+ print("saved", out_path)
+ return
+
+ ks_rows = read_csv_rows(args.ks_per_feature)
+ shift_rows = read_csv_rows(args.data_shift)
+ mh_rows = read_csv_rows(args.metrics_history)
+ fm = read_json(args.filtered_metrics)
+
+ bh_rows = [{"seed": r["seed"], "avg_ks": r["avg_ks"], "avg_jsd": r["avg_jsd"], "avg_lag1_diff": r["avg_lag1_diff"]} for r in rows]
+
+ if args.engine in {"auto", "matplotlib"}:
+ try:
+ panel_matplotlib(bh_rows, ks_rows, shift_rows, mh_rows, fm, out_path)
+ print("saved", out_path)
+ return
+ except Exception:
+ if args.engine == "matplotlib":
+ raise
+
+ panel_svg(bh_rows, ks_rows, shift_rows, mh_rows, fm, out_path)
+ print("saved", out_path)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/example/test_all_modifications.py b/example/test_all_modifications.py
index 9017fbc..c530c83 100644
--- a/example/test_all_modifications.py
+++ b/example/test_all_modifications.py
@@ -10,6 +10,18 @@ def test_imports():
"""测试所有模块导入"""
print("=== 测试模块导入 ===")
+ try:
+ import torch
+ has_torch = True
+ except Exception:
+ has_torch = False
+
+ try:
+ import matplotlib
+ has_matplotlib = True
+ except Exception:
+ has_matplotlib = False
+
modules_to_test = [
"platform_utils",
"data_utils",
@@ -27,6 +39,18 @@ def test_imports():
all_success = True
for module_name in modules_to_test:
+ if not has_torch and module_name in {
+ "hybrid_diffusion",
+ "train",
+ "export_samples",
+ "sample",
+ "train_stub",
+ }:
+ print(f"↷ {module_name} 跳过(未安装 torch)")
+ continue
+ if not has_matplotlib and module_name in {"plot_loss"}:
+ print(f"↷ {module_name} 跳过(未安装 matplotlib)")
+ continue
try:
module = importlib.import_module(module_name)
print(f"✓ {module_name} 导入成功")
@@ -232,4 +256,4 @@ def main():
if __name__ == "__main__":
success = main()
- sys.exit(0 if success else 1)
\ No newline at end of file
+ sys.exit(0 if success else 1)
diff --git a/figures/benchmark_metrics.svg b/figures/benchmark_metrics.svg
new file mode 100644
index 0000000..83b4cc6
--- /dev/null
+++ b/figures/benchmark_metrics.svg
@@ -0,0 +1,67 @@
+
\ No newline at end of file
diff --git a/figures/benchmark_panel.svg b/figures/benchmark_panel.svg
new file mode 100644
index 0000000..50c4d85
--- /dev/null
+++ b/figures/benchmark_panel.svg
@@ -0,0 +1,236 @@
+
\ No newline at end of file
diff --git a/paper.md b/paper.md
index 563e43c..1b98c32 100644
--- a/paper.md
+++ b/paper.md
@@ -469,8 +469,11 @@ series = {CySWATER '17}
pages={197–202} }
Methodology
Industrial control system (ICS) telemetry is intrinsically mixed-type and mechanistically heterogeneous: continuous process trajectories (e.g., sensor and actuator signals) coexist with discrete supervisory states (e.g., modes, alarms, interlocks), and the underlying generating mechanisms range from physical inertia to program-driven step logic. This heterogeneity is not cosmetic—it directly affects what “realistic” synthesis means, because a generator must jointly satisfy (i) temporal coherence, (ii) distributional fidelity, and (iii) discrete semantic validity (i.e., every discrete output must belong to its legal vocabulary by construction). These properties are emphasized broadly in operational-technology security guidance and ICS engineering practice, where state logic and physical dynamics are tightly coupled. [12]
+工业控制系统(ICS)遥测数据天然是混合类型且机制异质的:连续的过程轨迹(如传感器与执行器信号)与离散的监督状态(如模式、告警与联锁)并存,其生成机理从物理惯性到程序驱动的阶跃逻辑不一而足。这种异质性并非表面现象,它直接决定了“逼真”合成的内涵:生成器需要同时满足(i)时间连贯性,(ii)分布保真性,以及(iii)离散语义有效性(即离散输出必须按构造落在合法词表中)。这些属性也被 OT 安全指南与 ICS 工程实践反复强调,因为状态逻辑与物理动力学通常是紧密耦合的。[12]
We formalize each training instance as a fixed-length window of length We model each training instance as a fixed-length window of length $$L$$, consisting of (i) continuous channels $$X\in\mathbb{R}^{L\times d_c}$$ and (ii) discrete channels $$Y=\{{y^{(j)}_{1:L}}\}_{j=1}^{d_d}$$, where each discrete variable $$y^{(j)}_t\in\mathcal{V}_j$$ belongs to a finite vocabulary $$\mathcal{V}_j$$. Our objective is to learn a generator that produces synthetic $$(\hat{X},\hat{Y})$$ that are simultaneously coherent and distributionally faithful, while also ensuring $$\hat{y}^{(j)}_t\in\mathcal{V}_j$$ for all $$j, t$$ by construction (rather than via post-hoc rounding or thresholding).
+我们将每个训练样本形式化为长度为 $$L$$ 的定长窗口,由(i)连续通道 $$X\in\mathbb{R}^{L\times d_c}$$ 与(ii)离散通道 $$Y=\{{y^{(j)}_{1:L}}\}_{j=1}^{d_d}$$ 组成,其中每个离散变量 $$y^{(j)}_t\in\mathcal{V}_j$$ 属于有限词表 $$\mathcal{V}_j$$。我们的目标是学习一个生成器,使其输出的合成序列 $$(\hat{X},\hat{Y})$$ 同时具备时间一致与分布一致,并且对所有 $$j,t$$ 都按构造保证 $$\hat{y}^{(j)}_t\in\mathcal{V}_j$$(而非依赖事后取整或阈值化)。
A key empirical and methodological tension in ICS synthesis is that temporal realism and marginal/distributional realism can compete when optimized monolithically: sequence models trained primarily for regression often over-smooth heavy tails and intermittent bursts, while purely distribution-matching objectives can erode long-range structure. Diffusion models provide a principled route to rich distribution modeling through iterative denoising, but they do not, by themselves, resolve (i) the need for a stable low-frequency temporal scaffold, nor (ii) the discrete legality constraints for supervisory variables. [2,8] Recent time-series diffusion work further suggests that separating coarse structure from stochastic refinement can be an effective inductive bias for long-horizon realism. [6,7]
+ICS 合成中一个关键的经验与方法学张力在于:若以单体目标进行优化,时间逼真性与边际/分布逼真性往往会相互牵制。以回归为主的序列模型容易过度平滑重尾与间歇突发,而仅强调分布匹配的目标又可能侵蚀长程结构。扩散模型通过迭代去噪为丰富的分布建模提供了原则性路径,但其本身并不能自动解决(i)稳定的低频时间骨架需求,亦不能解决(ii)监督变量的离散合法性约束。[2,8] 近期时间序列扩散研究进一步表明,将粗结构与随机细化分离是一种有利于长时域逼真性的归纳偏置。[6,7]
[图片]
**PLACEHOLDER_ONLY_DO_NOT_USE_IN_REAL_PAPER**
Motivated by these considerations, we propose Mask-DDPM, organized in the following order:
@@ -478,21 +481,39 @@ Motivated by these considerations, we propose Mask-DDPM, organized in the follow
2. Residual DDPM for continuous variables: models distributional detail as stochastic residual structure conditioned on the learned trend [2, 6].
3. Masked diffusion for discrete variables: generates discrete ICS states with an absorbing/masking corruption process and categorical reconstruction [3,4].
4. Type-aware decomposition: a type-aware factorization and routing layer that assigns variables to the most appropriate modeling mechanism and enforces deterministic constraints where warranted.
+基于上述考虑,我们提出 Mask-DDPM,并将整体流程组织为以下顺序:
+1. Transformer 趋势模块:通过注意力序列建模学习连续动力学的主导时间骨架。[1]
+2. 连续变量的残差 DDPM:在趋势条件下以随机残差结构刻画分布细节。[2,6]
+3. 离散变量的掩蔽扩散:以吸收/掩蔽的扰动过程与类别重构生成离散 ICS 状态。[3,4]
+4. 类型感知分解:以类型化分解与路由层将变量分配到最合适的机制,并在需要时施加确定性约束。
This ordering is intentional. The trend module establishes a macro-temporal scaffold; residual diffusion then concentrates capacity on micro-structure and marginal fidelity; masked diffusion provides a native mechanism for discrete legality; and the type-aware layer operationalizes the observation that not all ICS variables should be modeled with the same stochastic mechanism. Importantly, while diffusion-based generation for ICS telemetry has begun to emerge, existing approaches remain limited and typically emphasize continuous synthesis or augmentation; in contrast, our pipeline integrates (i) a Transformer-conditioned residual diffusion backbone, (ii) a discrete masked-diffusion branch, and (iii) explicit type-aware routing for heterogeneous variable mechanisms within a single coherent generator. [10,11]
+这一顺序是刻意设计的:趋势模块先建立宏观时间支架;残差扩散再将建模容量集中到微结构与边际保真;掩蔽扩散为离散合法性提供原生机制;类型感知层则将“并非所有 ICS 变量都应以相同随机机制建模”的观察落到可操作的路由与约束之上。尤其重要的是,尽管面向 ICS 遥测的扩散式生成已开始出现,既有方法多仍局限于连续合成或数据增强;相比之下,我们在一个一致的生成器中同时集成了(i)Transformer 条件化的残差扩散主干,(ii)离散掩蔽扩散分支,以及(iii)面向异质变量机制的显式类型路由。[10,11]
---
Transformer trend module for continuous dynamics
+连续动力学的 Transformer 趋势模块
We instantiate the temporal backbone as a causal Transformer trend extractor, leveraging self-attention’s ability to represent long-range dependencies and cross-channel interactions without recurrence. [1] Compared with recurrent trend extractors (e.g., GRU-style backbones), a Transformer trend module offers a direct mechanism to model delayed effects and multivariate coupling—common in ICS, where control actions may influence downstream sensors with nontrivial lags and regime-dependent propagation. [1,12] Crucially, in our design the Transformer is not asked to be the entire generator; instead, it serves a deliberately restricted role: providing a stable, temporally coherent conditioning signal that later stochastic components refine.
+我们将时间骨架实现为因果 Transformer 趋势提取器,利用自注意力在不依赖循环结构的前提下表征长程依赖与跨通道交互。[1] 相比循环式趋势提取器(如 GRU 风格主干),Transformer 趋势模块能够更直接地刻画延迟效应与多变量耦合——这在 ICS 中十分常见,因为控制动作对下游传感器的影响往往存在非平凡时滞,并且传播关系会随工况而变化。[1,12] 需要强调的是,我们并不要求 Transformer 充当完整生成器;它被赋予一个刻意受限的角色:提供稳定、时间连贯的条件信号,供后续随机组件进行细化。
For continuous channels $$X$$, we posit an additive decomposition
$$X = S + R$$ ,
where $$S\in\mathbb{R}^{L\times d_c}$$ is a smooth trend capturing predictable temporal evolution, and $$R\in\mathbb{R}^{L\times d_c}$$ is a residual capturing distributional detail (e.g., bursts, heavy tails, local fluctuations) that is difficult to represent robustly with a purely regression-based temporal objective. This separation reflects an explicit division of labor: the trend module prioritizes temporal coherence, while diffusion (introduced next) targets distributional realism at the residual level—a strategy aligned with “predict-then-refine” perspectives in time-series diffusion modeling. [6,7]
+对连续通道 $$X$$,我们采用加性分解
+$$X = S + R$$,
+其中 $$S\in\mathbb{R}^{L\times d_c}$$ 表示捕捉可预测时间演化的平滑趋势,$$R\in\mathbb{R}^{L\times d_c}$$ 表示承载分布细节(如突发、重尾与局部波动)的残差部分,而这些细节往往难以用纯回归式时间目标稳定表示。该分解体现了明确的分工:趋势模块优先保证时间连贯性;随后引入的扩散则在残差层面追求分布逼真性,这与时间序列扩散中“先预测、再细化”的思路一致。[6,7]
We parameterize the trend $$S$$ using a causal Transformer $$f_\phi$$ . With teacher forcing, we train $$f_\phi$$to predict the next-step trend from past observations:
$$\hat{S}_{t+1} = f_\phi(X_{1:t}), \qquad t=1,\dots,L-1,$$
using the mean-squared error objective
$$\mathcal{L}_{trend}(\phi) = \frac{1}{(L-1)d_c}\sum_{t=1}^{L-1}\left\| \hat{S}_{t+1} - X_{t+1}\right\|_2^2$$
At inference, we roll out the Transformer autoregressively to obtain $$\hat{S}$$ , and then define the residual target for diffusion as $$R = X - \hat{S}$$. This setup intentionally “locks in” a coherent low-frequency scaffold before any stochastic refinement is applied, thereby reducing the burden on downstream diffusion modules to simultaneously learn both long-range structure and marginal detail. In this sense, our use of Transformers is distinctive: it is a conditioning-first temporal backbone designed to stabilize mixed-type diffusion synthesis in ICS, rather than an end-to-end monolithic generator. [1,6,10]
+我们使用因果 Transformer $$f_\phi$$ 对趋势 $$S$$ 进行参数化。在 teacher forcing 下训练 $$f_\phi$$ 从历史观测预测下一步趋势:
+$$\hat{S}_{t+1} = f_\phi(X_{1:t}), \qquad t=1,\dots,L-1,$$
+并采用均方误差目标
+$$\mathcal{L}_{trend}(\phi) = \frac{1}{(L-1)d_c}\sum_{t=1}^{L-1}\left\| \hat{S}_{t+1} - X_{t+1}\right\|_2^2.$$
+推理阶段,我们以自回归方式展开 Transformer 得到 $$\hat{S}$$,并将扩散的残差目标定义为 $$R = X - \hat{S}$$。该设置刻意在任何随机细化发生之前“锁定”低频一致的时间支架,从而降低下游扩散模块同时学习长程结构与边际细节的负担。因而,这里 Transformer 的用法具有差异性:它是先条件化的时间主干,用于稳定 ICS 的混合类型扩散合成,而不是端到端的单体生成器。[1,6,10]
DDPM for continuous residual generation
+连续残差生成的 DDPM
We model the residual RRR with a denoising diffusion probabilistic model (DDPM) conditioned on the trend $$\hat{S}$$. [2] Diffusion models learn complex data distributions by inverting a tractable noising process through iterative denoising, and have proven effective at capturing multimodality and heavy-tailed structure that is often attenuated by purely regression-based sequence models. [2,8] Conditioning the diffusion model on $$\hat{S}$$ is central: it prevents the denoiser from re-learning the low-frequency scaffold and focuses capacity on residual micro-structure, mirroring the broader principle that diffusion excels as a distributional corrector when a reasonable coarse structure is available. [6,7]
+我们用条件于趋势 $$\hat{S}$$ 的去噪扩散概率模型(DDPM)来建模残差部分。[2] 扩散模型通过对可处理的加噪过程进行迭代反演来学习复杂分布,已被验证能够有效捕捉多峰性与重尾结构——这些结构常被纯回归式序列模型削弱。[2,8] 以 $$\hat{S}$$ 作为条件至关重要:它避免去噪器重复学习低频支架,使建模容量集中到残差微结构上,从而呼应一个更一般的原则:当已有合理的粗结构时,扩散更擅长作为分布层面的“校正器”。[6,7]
Let $$K$$ denote the number of diffusion steps, with a noise schedule $$\{\beta_k\}_{k=1}^K$$, $$\alpha_k = 1-\beta_k$$, and $$\bar{\alpha}_k=\prod_{i=1}^k \alpha_i$$ . The forward corruption process is:
$$q(r_k\mid r_0)=\mathcal{N}\left(\sqrt{\bar{\alpha}_k}r_0,\ (1-\bar{\alpha}_k)\mathbf{I}\right)$$
equivalently,
@@ -526,8 +547,11 @@ where $$\mathrm{SNR}_k=\bar{\alpha}_k/(1-\bar{\alpha}_k)$$ and $$\gamma>0$$ is a
After sampling $$\hat{R}$$ by reverse diffusion, we reconstruct the continuous output as
$$\hat{X} = \hat{S} + \hat{R}$$ .
Overall, the DDPM component serves as a distributional corrector on top of a temporally coherent backbone, which is particularly suited to ICS where low-frequency dynamics are strong and persistent but fine-scale variability (including bursts and regime-conditioned noise) remains important for realism. Relative to prior ICS diffusion efforts that primarily focus on continuous augmentation, our formulation elevates trend-conditioned residual diffusion as a modular mechanism for disentangling temporal structure from distributional refinement. [10,11]
+总体而言,DDPM 组件在时间连贯的主干之上充当分布校正器,这尤其适合 ICS:低频动力学强且持久,但细尺度变异(包括突发与工况条件噪声)对逼真性同样关键。相较以往主要侧重连续增强的 ICS 扩散工作,我们将“趋势条件化的残差扩散”提升为一种模块化机制,用以解耦时间结构与分布细化。[10,11]
Masked diffusion for discrete ICS variables
+离散 ICS 变量的掩蔽扩散
Discrete ICS variables must remain categorical, making Gaussian diffusion inappropriate for supervisory states and mode-like channels. While one can attempt continuous relaxations or post-hoc discretization, such strategies risk producing semantically invalid intermediate states (e.g., “in-between” modes) and can distort the discrete marginal distribution. Discrete-state diffusion provides a principled alternative by defining a valid corruption process directly on categorical variables. [3,4] In the ICS setting, this is not a secondary detail: supervisory tags often encode control logic boundaries (modes, alarms, interlocks) that must remain within a finite vocabulary to preserve semantic correctness. [12]
+离散 ICS 变量必须保持类别形式,因此高斯扩散并不适用于监督状态与模式类通道。尽管可以尝试连续松弛或事后离散化,但这类策略可能产生语义无效的中间状态(如“介于两种模式之间”的状态),并且会扭曲离散边际分布。离散状态扩散通过直接在类别变量上定义合法的扰动过程提供了更原则性的替代方案。[3,4] 在 ICS 场景中,这并非次要细节:监督标签往往编码控制逻辑边界(模式、告警、联锁),必须保持在有限词表内才能维持语义正确性。[12]
We therefore adopt masked (absorbing) diffusion for discrete channels, where corruption replaces tokens with a special $$\texttt{[MASK]}$$ symbol according to a schedule. [4] For each variable $$j$$, define a masking schedule $${m_k}_{k=1}^K$$ (with $$m_k\in[0,1]$$) increasing in $$k$$. The forward corruption process is
$$q(y^{(j)}_k \mid y^{(j)}_0)=
\begin{cases}
@@ -549,8 +573,11 @@ h_\psi\left(y_k,k,\hat{S},\hat{X}\right)_{j,t},\ y^{(j)}_{0,t}
\right)
\right]$$
Where $$\mathrm{CE}(\cdot,\cdot)$$is cross-entropy. At sampling time, we initialize all discrete tokens as $$\texttt{[MASK]}$$and iteratively unmask them using the learned conditionals, ensuring that every output token lies in its legal vocabulary by construction. This discrete branch is a key differentiator of our pipeline: unlike typical continuous-only diffusion augmentation in ICS, we integrate masked diffusion as a first-class mechanism for supervisory-variable legality within the same end-to-end synthesis workflow. [4,10]
+其中 $$\mathrm{CE}(\cdot,\cdot)$$ 为交叉熵。采样时,我们将所有离散 token 初始化为 $$\texttt{[MASK]}$$,并使用学习到的条件分布逐步解掩蔽,从而按构造保证每个输出 token 都落在其合法词表内。该离散分支是流程的关键差异点:不同于 ICS 中常见的仅连续扩散增强,我们将掩蔽扩散作为监督变量合法性的一级机制纳入同一端到端合成流程。[4,10]
Type-aware decomposition as factorization and routing layer
+作为分解与路由层的类型感知分解
Even with a trend-conditioned residual DDPM and a discrete masked-diffusion branch, a single uniform modeling treatment can remain suboptimal because ICS variables are generated by qualitatively different mechanisms. For example, program-driven setpoints exhibit step-and-dwell dynamics; controller outputs follow control laws conditioned on process feedback; actuator positions may show saturation and dwell; and some “derived tags” are deterministic functions of other channels. Treating all channels as if they were exchangeable stochastic processes can misallocate model capacity and induce systematic error concentration on a small subset of mechanistically distinct variables. [12]
+即便已有趋势条件化的残差 DDPM 与离散掩蔽扩散分支,单一且统一的建模方式仍可能并非最优,因为 ICS 变量往往由本质不同的机理产生。例如,程序驱动的设定值呈现阶跃—驻留动态;控制器输出遵循受过程反馈条件化的控制律;执行器位置可能出现饱和与驻留;而部分“派生标签”则是其他通道的确定性函数。若将所有通道都视为可交换的随机过程,模型容量容易被错误分配,并导致误差系统性地集中在少数机制特殊的变量上。[12]
We therefore introduce a type-aware decomposition that formalizes this heterogeneity as a routing and constraint layer. Let $$\tau(i)\in{1,\dots,6}$$ assign each variable (i) to a type class. The type assignment can be initialized from domain semantics (tag metadata, value domains, and engineering meaning), and subsequently refined via an error-attribution workflow described in the Benchmark section. Importantly, this refinement does not change the core diffusion backbone; it changes which mechanism is responsible for which variable, thereby aligning inductive bias with variable-generating mechanism while preserving overall coherence.
We use the following taxonomy:
- Type 1 (program-driven / setpoint-like): externally commanded, step-and-dwell variables. These variables can be treated as exogenous drivers (conditioning signals) or routed to specialized change-point / dwell-time models, rather than being forced into a smooth denoiser that may over-regularize step structure.
@@ -559,14 +586,27 @@ We use the following taxonomy:
- Type 4 (process variables): inertia-dominated continuous dynamics; these are the primary beneficiaries of the Transformer trend + residual DDPM pipeline.
- Type 5 (derived/deterministic variables): algebraic or rule-based functions of other variables; we enforce deterministic reconstruction $$\hat{x}^{(i)} = g_i(\hat{X},\hat{Y})$$ rather than learning a stochastic generator, improving logical consistency and sample efficiency.
- Type 6 (auxiliary/low-impact variables): weakly coupled or sparse signals; we allow simplified modeling (e.g., calibrated marginals or lightweight temporal models) to avoid allocating diffusion capacity where it is not warranted.
+我们采用如下类型划分:
+- Type 1(程序驱动/设定值类):外部命令触发、呈现阶跃—驻留特征的变量。这类变量更适合作为外生驱动(条件信号),或路由到专门的变点/驻留时间机制,而非强行交由偏好平滑的去噪器,从而避免对阶跃结构的过度正则化。
+- Type 2(控制器输出):与反馈回路紧密耦合的连续变量,适合在条件化建模中显式引入相关过程变量与设定值。
+- Type 3(执行器状态/位置):常见饱和、驻留与速率限制,可能需要超出通用残差扩散的状态性动态,从而引入专门的条件模块或额外的归纳约束。
+- Type 4(过程变量):以惯性主导的连续动力学,是“Transformer 趋势 + 残差 DDPM”管线的主要受益者。
+- Type 5(派生/确定性变量):其他变量的代数或规则函数;我们采用确定性重构 $$\hat{x}^{(i)} = g_i(\hat{X},\hat{Y})$$ 而非学习随机生成器,以提升逻辑一致性与样本效率。
+- Type 6(辅助/低影响变量):弱耦合或稀疏信号;允许使用简化建模(如校准边际或轻量时间模型),避免将扩散容量分配到收益有限的通道上。
Type-aware decomposition improves synthesis quality through three mechanisms. First, it improves capacity allocation by preventing a small set of mechanistically atypical variables from dominating gradients and distorting the learned distribution for the majority class (typically Type 4). Second, it enables constraint enforcement by deterministically reconstructing Type 5 variables, preventing logically inconsistent samples that purely learned generators can produce. Third, it improves mechanism alignment by attaching inductive biases consistent with step/dwell or saturation behaviors where generic denoisers may implicitly favor smoothness.
+类型感知分解通过三种机制提升合成质量:其一,它通过避免少数机制异常变量主导梯度,改善容量分配并防止对多数类(通常为 Type 4)的分布学习造成扭曲;其二,它通过对 Type 5 变量的确定性重构来施加约束,避免纯学习式生成器可能产生的逻辑不一致样本;其三,它通过为阶跃/驻留与饱和等行为注入匹配的归纳偏置来提升机制对齐,而通用去噪器往往会隐式偏向平滑化。
From a novelty standpoint, this layer is not merely an engineering “patch”; it is an explicit methodological statement that ICS synthesis benefits from typed factorization—a principle that has analogues in mixed-type generative modeling more broadly, but that remains underexplored in diffusion-based ICS telemetry synthesis. [9,10,12]
+从创新点角度看,该层并非简单的工程“补丁”,而是一种明确的方法学主张:ICS 合成应受益于类型化因子分解。该原则在更广义的混合类型生成建模中有对应思想,但在基于扩散的 ICS 遥测合成中仍缺乏系统性探索。[9,10,12]
Joint optimization and end-to-end sampling
+联合优化与端到端采样
We train the model in a staged manner consistent with the above factorization, which improves optimization stability and encourages each component to specialize in its intended role. Specifically: (i) we train the trend Transformer $$f_{\phi}$$ to obtain $$\hat{S}$$; (ii) we compute residual targets $$R=X-\hat{S}$$ for the continuous variables routed to residual diffusion; (iii) we train the residual DDPM $$p_{\theta}(R\mid \hat{S})$$ and masked diffusion model $$p_{\psi}(Y\mid \text{masked}(Y), \hat{S}, \hat{X})$$; and (iv) we apply type-aware routing and deterministic reconstruction during sampling. This staged strategy is aligned with the design goal of separating temporal scaffolding from distributional refinement, and it mirrors the broader intuition in time-series diffusion that decoupling coarse structure and stochastic detail can mitigate “structure vs. realism” conflicts. [6,7]
+我们采用与上述分解一致的分阶段训练方式,以提升优化稳定性并促使各组件专注于其目标角色。具体而言:(i)训练趋势 Transformer $$f_{\phi}$$ 得到 $$\hat{S}$$;(ii)对路由至残差扩散的连续变量计算残差目标 $$R=X-\hat{S}$$;(iii)训练残差 DDPM $$p_{\theta}(R\mid \hat{S})$$ 与掩蔽扩散模型 $$p_{\psi}(Y\mid \text{masked}(Y), \hat{S}, \hat{X})$$;(iv)在采样阶段施加类型感知路由与确定性重构。该分阶段策略与“将时间支架与分布细化分离”的设计目标一致,也呼应了时间序列扩散中的一般直觉:解耦粗结构与随机细节能够缓解“结构 vs. 逼真”之间的冲突。[6,7]
A simple combined objective is
$$\mathcal{L} = \lambda\mathcal{L}_{\text{cont}} + (1-\lambda)\mathcal{L}_{\text{disc}}$$,
with $$\lambda\in[0,1]$$controlling the balance between continuous and discrete learning. Type-aware routing determines which channels contribute to which loss and which are excluded in favor of deterministic reconstruction. In practice, this routing acts as a principled guardrail against negative transfer across variable mechanisms: channels that are best handled deterministically (Type 5) or by specialized drivers (Type 1/3, depending on configuration) are prevented from forcing the diffusion models into statistically incoherent compromises.
+其中 $$\lambda\in[0,1]$$ 用于控制连续与离散学习的权衡。类型感知路由决定哪些通道参与哪一部分损失,哪些通道应被排除并转为确定性重构。在实践中,该路由充当跨机制负迁移的原则性护栏:对确定性处理更合适的通道(Type 5)或应由外生驱动/机制对齐模块承担的通道(根据配置可能为 Type 1/3),不会迫使扩散模型在统计上做出不一致的折中。
At inference time, generation follows the same structured order: (i) trend $$\hat{S}$$via the Transformer, (ii) residual $$\hat{R}$$ via DDPM, (iii) discrete $$\hat{Y}$$ via masked diffusion, and (iv) type-aware assembly with deterministic reconstruction for routed variables. This pipeline produces $$(\hat{X},\hat{Y})$$ that are temporally coherent by construction (through $$\hat{S}$$), distributionally expressive (through $$\hat{R}$$ denoising), and discretely valid (through masked diffusion), while explicitly accounting for heterogeneous variable-generating mechanisms through type-aware routing. In combination, these choices constitute our central methodological contribution: a unified Transformer + mixed diffusion generator for ICS telemetry, augmented by typed factorization to align model capacity with domain mechanism. [2,4,10,12]
+推理阶段的生成遵循同样的结构化顺序:(i)用 Transformer 生成趋势 $$\hat{S}$$,(ii)用 DDPM 生成残差 $$\hat{R}$$,(iii)用掩蔽扩散生成离散序列 $$\hat{Y}$$,(iv)类型感知装配并对被路由变量做确定性重构。该管线使输出 $$(\hat{X},\hat{Y})$$ 在时间上按构造一致(由 $$\hat{S}$$ 保证)、在分布上具有表达力(由 $$\hat{R}$$ 去噪提供)、在离散上保持合法(由掩蔽扩散保证),同时通过类型路由显式刻画异质变量机理。综合而言,这些选择构成了本文的核心方法贡献:一个面向 ICS 遥测的统一 Transformer + 混合扩散生成器,并以类型化分解将模型容量与领域机理对齐。[2,4,10,12]
References for Methodology Part
[1] Vaswani, A., Shazeer, N., Parmar, N., Uszkoreit, J., Jones, L., Gomez, A. N., Kaiser, Ł., & Polosukhin, I. Attention Is All You Need. Advances in Neural Information Processing Systems (NeurIPS), 30, 2017.
🔗 https://arxiv.org/abs/1706.03762 | https://proceedings.neurips.cc/paper/2017/hash/3f5ee243547dee91fbd053c1c4a845aa-Abstract.html
@@ -598,6 +638,52 @@ Note: This is a preprint (not peer-reviewed); SSRN entry exists with Jan 10, 202
Benchmark
+We evaluate the proposed pipeline on feature sequences derived from the HAI Security Dataset, using fixed-length windows (L=96) that preserve the mixed-type structure of ICS telemetry. The goal of this benchmark is not only to report “overall similarity”, but to justify why the proposed factorization is a better fit for protocol feature synthesis: continuous channels must match physical marginals, discrete channels must remain semantically legal, and both must retain short-horizon dynamics that underpin state transitions and interlocks.
+我们在从 HAI Security Dataset 导出的特征序列上评估所提出的流程,采用定长窗口(L=96)以保留 ICS 遥测的混合类型结构。该基准测试不仅报告“整体相似度”,更旨在解释为何本文的因子化更适合协议特征合成:连续通道需要匹配物理边际分布,离散通道需要保持语义合法性,而两者都必须保留支撑状态切换与联锁逻辑的短时域动态。
+
+This emphasis reflects evaluation practice in time-series generation, where strong results are typically supported by multiple complementary views (marginal fidelity, dependency/temporal structure, and downstream plausibility), rather than a single aggregate score. In the ICS setting, this multi-view requirement is sharper: a generator that matches continuous marginals while emitting out-of-vocabulary supervisory tokens is unusable for protocol reconstruction, and a generator that matches marginals but breaks lag structure can produce temporally implausible command/response sequences.
+这种强调也呼应了时间序列生成领域的常见评估方式:高质量结果通常需要多个互补视角(边际分布、依赖/时间结构、下游可用性)共同支撑,而非依赖单一汇总分数。在 ICS 场景下,这一要求更为尖锐:若生成器虽匹配连续边际却产生越界的监督 token,则无法用于协议重构;若仅匹配边际却破坏滞后结构,则会产生时间上不可信的命令/响应序列。
+
+Positioning against prior evaluation practice
+Recent ICS time-series generators often emphasize aggregate similarity scores and utility-driven evaluations (e.g., anomaly-detection performance) to demonstrate realism, which is valuable but can under-specify mixed-type protocol constraints. Our benchmark complements these practices by making mixed-type legality and per-feature distributional alignment explicit: discrete outputs are evaluated as categorical distributions (JSD) and are constrained to remain within the legal vocabulary by construction, while continuous channels are evaluated with nonparametric distribution tests (KS). This combination provides a direct, protocol-relevant justification for the hybrid design, rather than relying on a single composite score that may mask discrete failures.
+与既有评估范式的对照
+近期的 ICS 时间序列生成工作常以汇总相似度分数与效用导向评估(例如异常检测性能)来证明“逼真度”,这类证据很有价值,但可能不足以刻画混合类型协议约束。本文的基准测试对其形成补充:我们将混合类型的合法性与特征级分布对齐显式化——离散输出以类别分布(JSD)评估,并按构造限制在合法词表内;连续通道则用非参数分布检验(KS)评估。该组合能够从协议特征角度直接支撑混合设计的必要性,而不是依赖可能掩盖离散失败的单一复合分数。
+
+Evaluation metrics
+For continuous channels, we measure distributional alignment using the Kolmogorov–Smirnov (KS) statistic computed per feature between the empirical distributions of real and synthetic samples, and then averaged across features. For discrete channels, we quantify marginal fidelity with Jensen–Shannon divergence (JSD) between categorical distributions per feature, averaged across discrete variables. To assess temporal realism, we compare lag-1 autocorrelation at the feature level and report the mean absolute difference between real and synthetic lag-1 autocorrelation, averaged across features. In addition, to avoid degenerate comparisons driven by near-constant tags, features whose empirical standard deviation falls below a small threshold are excluded from continuous KS aggregation; such channels carry limited distributional information and can distort summary statistics.
+评估指标
+对连续通道,我们在每个特征上比较真实与合成样本的经验分布,计算 Kolmogorov–Smirnov(KS)统计量,并在特征维度上取平均以得到总体分布对齐程度。对离散通道,我们在每个离散特征上比较类别分布并计算 Jensen–Shannon divergence(JSD),再在离散变量维度上取平均以衡量边际保真性。对时间逼真性,我们比较特征级的 lag-1 自相关,并报告真实与合成 lag-1 自相关的平均绝对差(在特征维度上取平均)。此外,为避免近常量标签导致的退化比较,我们在连续 KS 汇总时排除经验标准差低于阈值的特征,因为此类通道携带的分布信息有限,容易扭曲汇总统计。
+
+Quantitative results
+Across three runs, the mean continuous KS is 0.3311 (std 0.0079) and the mean discrete JSD is 0.0284 (std 0.0073), indicating that the generator preserves both continuous marginals and discrete semantic distributions at the feature level. Temporal consistency is similarly stable across runs, with a mean lag-1 autocorrelation difference of 0.2684 (std 0.0027), suggesting that the synthesized windows retain short-horizon dynamical structure instead of collapsing to marginal matching alone. The best-performing instance (by mean KS) attains 0.3224, and the small inter-seed variance shows that the reported fidelity is reproducible rather than driven by a single favorable initialization.
+定量结果
+在三个独立运行上,连续 KS 的均值为 0.3311(标准差 0.0079),离散 JSD 的均值为 0.0284(标准差 0.0073),表明生成器在特征层面同时较好地保留了连续边际与离散语义分布。时间一致性同样稳定,lag-1 自相关差的均值为 0.2684(标准差 0.0027),说明合成窗口能够保留短时域动力学结构,而不仅仅是边际分布匹配。在三次运行中,按均值 KS 衡量的最佳实例达到 0.3224,表明该保真度具有可重复性,并非由单次有利初始化所驱动。
+
+| Metric | Aggregation | Lower is better | Mean ± Std (3 seeds) |
+|---|---|---:|---:|
+| KS (continuous) | mean over continuous features | ✓ | 0.3311 ± 0.0079 |
+| JSD (discrete) | mean over discrete features | ✓ | 0.0284 ± 0.0073 |
+| Abs Δ lag-1 autocorr | mean over features | ✓ | 0.2684 ± 0.0027 |
+
+Table: Summary of benchmark metrics (three independent seeds).
+表:Benchmark 指标汇总(三个独立随机种子)。
+
+
+Benchmark 综合图(流程、特征级分布保真、训练集分布漂移与跨种子鲁棒性)。
+
+Why this benchmark highlights where the method helps
+To make the benchmark actionable (and comparable to prior work), we report type-appropriate, interpretable statistics instead of collapsing everything into a single similarity score. This matters in mixed-type ICS telemetry: continuous fidelity can be high while discrete semantics fail, and vice versa. By separating continuous (KS), discrete (JSD), and temporal (lag-1) views, the evaluation directly matches the design goals of the hybrid generator: distributional refinement for continuous residuals, vocabulary-valid reconstruction for discrete supervision, and trend-induced short-horizon coherence.
+为何该基准测试能够凸显方法优势
+为使基准测试具备可操作性并便于与既有工作对比,我们报告与数据类型匹配且可解释的统计量,而非将所有差异压缩为单一相似度分数。这一点在混合类型的 ICS 遥测中尤为关键:连续分布可能看似很接近,但离散语义可能崩坏;反之亦然。将连续(KS)、离散(JSD)与时间(lag-1)三个视角分离后,评估即可与混合生成器的设计目标逐一对齐:对连续残差的分布细化、对离散监督变量的词表合法重构,以及由趋势分支诱导的短时域一致性。
+
+In addition, the seed-averaged reporting mirrors evaluation conventions in recent diffusion-based time-series generation studies, where robustness across runs is increasingly treated as a first-class signal rather than an afterthought. In this sense, the small inter-seed variance is itself evidence that the factorized training and typed routing reduce instability and localized error concentration, which is frequently observed when heterogeneous channels compete for the same modeling capacity.
+此外,对随机种子取均值的报告方式也与近年来扩散式时间序列生成研究的评估惯例一致:跨运行鲁棒性正逐渐被视为一项一等信号,而非事后补充。在这一意义上,跨种子的低方差本身也可视为证据:分解式训练与类型路由降低了不稳定性与局部误差集中,而这类现象常见于异质通道争夺同一建模容量的情形。
+
+Error-attribution refinement for type-aware decomposition
+To connect evaluation back to the typed factorization described in Methodology, we use feature-level metric attribution as a refinement signal for the type assignment. Starting from an initial semantic typing (value domain, operational role, and tag metadata), we compute per-feature divergences and inspect persistent outliers across runs. Features identified as near-deterministic (e.g., derived tags or low-variance indicators) are re-routed to deterministic reconstruction (Type 5) or simplified handling (Type 6), while step-and-dwell or saturation-prone channels are treated as exogenous drivers or routed to mechanism-aligned types (Type 1/3). This workflow does not change the overall generation order; it reallocates responsibility across typed mechanisms so that stochastic components focus on variables that benefit from probabilistic modeling, improving global fidelity while reducing localized error concentration.
+类型感知分解的误差归因细化
+为将评估与方法部分的类型化因子分解对应起来,我们将特征级指标的归因作为类型分配的细化信号。具体地,从初始语义类型(取值域、运行角色与标签元信息)出发,我们计算每个特征的偏差并关注跨运行持续存在的离群项。被识别为近确定性的特征(如派生标签或低方差指示量)将被路由到确定性重构(Type 5)或简化处理(Type 6),而阶跃—驻留或易饱和通道则作为外生驱动或被路由到机制对齐的类型(Type 1/3)。该流程不改变整体生成顺序,而是在类型机制之间重新分配“责任”,使随机组件专注于真正受益于概率建模的变量,从而在降低局部误差集中的同时提升整体保真度。
+
Future works
-Conclusion
\ No newline at end of file
+Conclusion