headless / tests /ablate_regime_shift.py
logos42's picture
Upload folder using huggingface_hub
216004d verified
Raw History Blame Contribute Delete
5.26 kB
#!/usr/bin/env python3
"""Regime-shift 消融: 固定 alpha / IDBD / Continual-IDBD 谁在环境突变后适应更快。
按用户给的 §13 设计做 3x4 消融, 但**用我们自己的真实 regime shift**:
阶段 A: 描述子第 0 维决定收益
阶段 B: **第 1 维**决定收益 (环境突变, 最优映射整体改变)
阶段 C: 回到 A (测 recovery / 新旧环境反复切换)
记录 §13 要求的全部指标:
MSE / max(alpha) / min(alpha) / median(alpha) / adaptation time / recovery time /
forgetting / weight-flipping rate F = #{t: sign(dw_t) != sign(dw_{t-1})} / T
关键判据 (§13):
"针对非平稳动力学设计可恢复塑性, 并证明它比固定 alpha / IDBD / TIDBD
在 regime shift 下**更快适应且更少发散**"
"""
import sys
import numpy as np
sys.path.insert(0, "/Users/apple/Downloads/headless")
from hibs_lnn.rl_proposer import RLProposer # noqa: E402
ND, D = 60, 3
rs = np.random.RandomState(0)
desc = rs.randn(ND, D)
PHASE = 120 # 每个阶段长度
def target_dim(t):
"""环境映射: A=[0], B=[1], C=[0]"""
return 1 if PHASE <= t < 2 * PHASE else 0
def run(algo, mu=0.05, alpha0=0.2, seed=1, n_know=0):
p = RLProposer(desc, tau=0.5, k=3, mu=mu, alpha0=alpha0, algo=algo,
seed=seed, n_know=n_know)
T = 3 * PHASE
err, al_hist, w_hist, recovered = [], [], [], None
first_b_ok = None
for t in range(T):
d = target_dim(t)
idx = p.act()
r = 0.5 + 0.3 * np.tanh(desc[idx, d].mean())
w_before = p.theta.copy()
for i in idx:
p.acc[i] = r
p.any_time = r
p.update(idx, r=(r - p.global_acc if t else r))
p.global_acc = r
err.append(abs(r - float(np.mean([p.value(i) for i in idx]))))
al_hist.append(p.alpha.copy())
w_hist.append(p.theta.copy())
# 阶段 B 内第一次误差降到 0.15 以下 = 适应
if PHASE <= t < 2 * PHASE and first_b_ok is None and err[-1] < 0.15:
first_b_ok = t - PHASE
# 阶段 C 内第一次恢复 = recovery time
if t >= 2 * PHASE and recovered is None and err[-1] < 0.15:
recovered = t - 2 * PHASE
A = np.array(err)
AL = np.array(al_hist)
W = np.array(w_hist)
# weight-flipping rate (§13 的定义)
dw = np.diff(W, axis=0)
flip = float(np.mean(np.sign(dw[1:]) != np.sign(dw[:-1]))) if len(dw) > 1 else 0.0
return {
"mse_A": float(A[:PHASE].mean()),
"mse_B": float(A[PHASE:2 * PHASE].mean()),
"mse_C": float(A[2 * PHASE:].mean()),
"adapt_B": first_b_ok,
"recover_C": recovered,
"forget": float(A[2 * PHASE:2 * PHASE + 10].mean() - A[PHASE - 10:PHASE].mean()),
"a_max": float(AL[-1].max()), "a_min": float(AL[-1].min()),
"a_med": float(np.median(AL[-1])),
"a_std": float(AL[-1].std()),
"flip": flip,
"recov_n": int(p.stats().get("n_recovery", 0)),
}
# (显示名, 实际 algo, 参数)
ALGOS = [("fixed-alpha", "cidbd", dict(mu=0.0)), # 固定 alpha 基线
("idbd-raw", "idbd-raw", dict(mu=0.05)),
("idbd", "idbd", dict(mu=0.05)),
("autostep", "autostep", dict(mu=0.05)),
("cidbd", "cidbd", dict(mu=0.05)),
("cidbd+k14", "cidbd", dict(mu=0.05, n_know=14))]
print("=" * 112)
print("Regime-shift 消融 (A=d0 -> B=d1 -> C=d0, 每段 %d 步; 3 seed 平均)" % PHASE)
print("=" * 112)
seeds = [1, 7, 42]
print(" %-12s %8s %8s %8s %9s %9s %8s %8s %8s %7s %6s"
% ("algo", "MSE_A", "MSE_B", "MSE_C", "adapt_B", "recov_C", "forget",
"a_max", "a_med", "flip", "recov"))
results = {}
for name, algo, kw in ALGOS:
rl = [run(algo, seed=s, **kw) for s in seeds]
agg = {k: float(np.mean([r[k] for r in rl if r[k] is not None]))
for k in rl[0] if k != "adapt_B" and k != "recover_C"}
ab = [r["adapt_B"] for r in rl if r["adapt_B"] is not None]
rc = [r["recover_C"] for r in rl if r["recover_C"] is not None]
results[name] = (agg, ab, rc)
print(" %-12s %8.4f %8.4f %8.4f %9s %9s %8.4f %8.3f %8.4f %7.3f %6.0f"
% (name, agg["mse_A"], agg["mse_B"], agg["mse_C"],
("%.0f" % np.mean(ab)) if ab else "未适应",
("%.0f" % np.mean(rc)) if rc else "未恢复",
agg["forget"], agg["a_max"], agg["a_med"], agg["flip"],
agg["recov_n"]))
print()
print("=== §13 判据: 环境突变后「更快适应 且 更少发散」 ===")
base = results["fixed-alpha"][0]
idbd = results["idbd-raw"][0]
cid = results["cidbd"][0]
print(" %-22s %10s %10s %8s" % ("对比", "MSE_B", "adapt_B", "forget"))
for nm, agg, ab, rc in [("fixed-alpha", *results["fixed-alpha"]),
("IDBD (raw)", *results["idbd-raw"]),
("Continual-IDBD", *results["cidbd"]),
("CIDBD+内部知识14", *results["cidbd+k14"])]:
print(" %-22s %10.4f %10s %8.4f"
% (nm, agg["mse_B"], ("%.0f" % np.mean(ab)) if ab else "未适应", agg["forget"]))
print()
print(" CIDBD vs IDBD: MSE_B %+.4f forget %+.4f a_med %+.4f"
% (cid["mse_B"] - idbd["mse_B"], cid["forget"] - idbd["forget"],
cid["a_med"] - idbd["a_med"]))