Instructions to use RomanCohort/RNAQwen with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use RomanCohort/RNAQwen with Transformers:
# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("RomanCohort/RNAQwen", device_map="auto") - Notebooks
- Google Colab
- Kaggle
File size: 8,047 Bytes
68f9568 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | """按序列长度矫正的 s/step 估计 + token 压缩收益的归一化对比。
为什么需要这个:
逐步耗时与**输入 token 数近似线性**(r=0.971,3.13 ms/nt)。
直接比较不同运行的中位数会被"这一轮恰好抽到长/短序列"污染 ——
实测同一配置跨轮差异 1.40–1.57 s,就是这个原因,不是机器抖动。
做法:
1. 在 loss 运行(全 50 条 × 2 epoch = 100 步)上拟合 total_s ~ seq_nt;
2. 把系数按长度分桶验证(短/中/长),确认线性假设;
3. 用 3800 条规模推耗时 —— 但序列长度分布未知,故给"按当前 50 条平均长度"与
"长度分布偏移"的敏感性分析。
"""
from __future__ import annotations
import json
import statistics as st
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
def load(name: str) -> dict:
return json.loads((ROOT / "reports" / name).read_text(encoding="utf-8-sig"))
def fit(xs, ys):
n = len(xs)
mx, my = sum(xs) / n, sum(ys) / n
sxx = sum((a - mx) ** 2 for a in xs)
sxy = sum((a - mx) * (b - my) for a, b in zip(xs, ys))
b = sxy / sxx
a = my - b * mx
r = sxy / ((sxx ** 0.5) * (sum((v - my) ** 2 for v in ys) ** 0.5))
return a, b, r
def main() -> int:
loss = load("_raw_timing_loss.json")
tr = load("_raw_timing_trunc.json")
m = loss["runs"][0]["batch_meta"]
xs = [x["seq_nt"] for x in m]
ys = [x["step_total_s"] for x in m]
a, b, r = fit(xs, ys)
print(f"拟合 total_s = {a:.3f} + {1000*b:.3f} ms/nt (r={r:.3f}, n={len(xs)})")
print(f"seq_nt 样本均值 = {sum(xs)/len(xs):.0f} nt (median {st.median(xs):.0f})")
# 分桶验证
buckets = [("<=400", lambda v: v <= 400), ("401-600", lambda v: 400 < v <= 600),
("601-800", lambda v: 600 < v <= 800), (">800", lambda v: v > 800)]
bucket_check = {}
print("\n分桶核对(模型预测 vs 实测):")
for name, f in buckets:
pts = [(x, y) for x, y in zip(xs, ys) if f(x)]
if not pts:
continue
mx_ = sum(p[0] for p in pts) / len(pts)
my_ = sum(p[1] for p in pts) / len(pts)
pred = a + b * mx_
bucket_check[name] = {"n": len(pts), "mean_nt": mx_, "measured_mean_s": my_,
"model_pred_s": pred, "deviation_pct": 100 * (pred - my_) / my_}
print(f" {name:>8} n={len(pts):>3} nt均值={mx_:>6.0f} 实测均值={my_:.3f}s "
f"模型预测={pred:.3f}s 偏差={100*(pred-my_)/my_:+.1f}%")
# 全 50 条的 token 长度分布(用于把估计校正到真实池)
rows = []
with open(ROOT / "data" / "processed" / "annotations_50.jsonl", encoding="utf-8") as fh:
for line in fh:
if line.strip():
rows.append(json.loads(line))
nt_all = [len(x["sequence"]) for x in rows]
mean_nt_all = sum(nt_all) / len(nt_all)
mean_nt_loss = sum(xs) / len(xs)
print(f"\n全长 50 条的 seq_nt 均值 = {mean_nt_all:.0f}(loss 运行里 = {mean_nt_loss:.0f})")
def s_per_step_for(nt: float) -> float:
return a + b * nt
est_at_all50 = s_per_step_for(mean_nt_all)
est_at_loss50 = s_per_step_for(mean_nt_loss)
print(f"长度校正后 s/step(50 条池,均值 {mean_nt_all:.0f}nt) = {est_at_all50:.3f}")
print(f"对照:loss 运行窗口均值实测 = {sum(ys)/len(ys):.3f},模型在该均值处的预测 = {est_at_loss50:.3f}")
# 长度敏感性:3800 条语料长度分布未知
print("\n长度敏感性(s/step):")
sens = {}
for nt in (300, 416, 600, 800, 1000, 1200):
sens[nt] = s_per_step_for(nt)
print(f" seq_nt={nt:>5} -> {sens[nt]:.3f} s/step")
# 压缩收益做同池对照(F0/D/E/G 同一 16 条池、同一顺序)
by = {r["name"]: r for r in tr["runs"] if "error" not in r}
print("\n同池对照(16 条池、同一顺序,唯一变量 = RNA 软提示长度):")
base = by["F0_baseline_rna731"]["seconds"]["per_optimizer_step"]
for key, label in (("D_compress_real_256", "真压缩 256 latent"),
("E_compress_real_64", "真压缩 64 latent"),
("G_trunc_hack_64", "截断 hack 64 token")):
rr = by[key]
s = rr["seconds"]["per_optimizer_step"]
tot = (rr.get("token_layout_raw") or {}).get("total")
print(f" {label:<22} {s['median']:.3f}s median / {s['mean']:.3f}s mean "
f"seq_total={tot} speedup={base['median']/s['median']:.2f}×")
print(f" peak_alloc={rr['memory']['peak_allocated_GiB']:.2f} GiB "
f"fwd={rr['seconds']['forward_per_micro'].get('median'):.3f} "
f"bwd={rr['seconds']['backward_per_micro'].get('median'):.3f}")
print(f" {'baseline 731':<22} {base['median']:.3f}s median / {base['mean']:.3f}s mean "
f"seq_total=880 peak_alloc={by['F0_baseline_rna731']['memory']['peak_allocated_GiB']:.2f} GiB")
# 用长度模型核对压缩收益是否只是"序列变短"的必然结果
print("\n收益归因(用长度模型预测,对比实测):")
for key, label, nt in (("D_compress_real_256", "真压缩256", 405 + 15),
("E_compress_real_64", "真压缩64", 213),
("G_trunc_hack_64", "截断64", 213)):
rr = by[key]
s_meas = rr["seconds"]["per_optimizer_step"]["mean"]
s_pred = s_per_step_for(nt)
print(f" {label:<12} 实测mean={s_meas:.3f}s 长度模型预测={s_pred:.3f}s "
f"偏差={100*(s_pred-s_meas)/s_meas:+.1f}%")
out = {
"linear_model": {"intercept_s": a, "slope_s_per_nt": b, "pearson_r": r,
"n_points": len(xs),
"fitted_on": "全 50 条 × 2 epoch 的 100 个 optimizer step"},
"bucket_check": bucket_check,
"length_sensitivity_s_per_step": {str(k): v for k, v in sens.items()},
"mean_seq_nt_full50": mean_nt_all,
"mean_seq_nt_loss_window": mean_nt_loss,
"length_corrected_s_per_step_at_full50": est_at_all50,
"same_pool_compression": {},
}
for key, label in (("F0_baseline_rna731", "baseline_rna731"),
("D_compress_real_256", "compress_real_256"),
("E_compress_real_64", "compress_real_64"),
("G_trunc_hack_64", "trunc_hack_64")):
rr = by[key]
s = rr["seconds"]["per_optimizer_step"]
out["same_pool_compression"][label] = {
"s_per_step_median": s["median"], "s_per_step_mean": s["mean"],
"peak_alloc_GiB": rr["memory"]["peak_allocated_GiB"],
"seq_total_tokens": (rr.get("token_layout_raw") or {}).get("total"),
"forward_per_micro_median": rr["seconds"]["forward_per_micro"].get("median"),
"backward_per_micro_median": rr["seconds"]["backward_per_micro"].get("median"),
"speedup_mean_vs_baseline": by["F0_baseline_rna731"]["seconds"]["per_optimizer_step"]["mean"] / s["mean"],
}
# E(真压缩 64)vs G(截断 hack 64):都喂 213 token,验证压缩器自身开销
se = by["E_compress_real_64"]["seconds"]["per_optimizer_step"]
sg = by["G_trunc_hack_64"]["seconds"]["per_optimizer_step"]
out["equivalence_E_vs_G"] = {
"E_compress_real_64_s_per_step_median": se["median"],
"G_trunc_hack_64_s_per_step_median": sg["median"],
"median_diff_pct": 100 * (se["median"] - sg["median"]) / sg["median"],
"mean_diff_pct": 100 * (se["mean"] - sg["mean"]) / sg["mean"],
"verdict": "两者都喂 213 token,耗时差 <0.5%:压缩收益完全来自序列变短,"
"压缩器(resampler)自身前向开销可忽略",
}
dst = ROOT / "reports" / "_verify_all.json"
dst.write_text(json.dumps(out, indent=2, ensure_ascii=False), encoding="utf-8")
print(f"\n-> {dst}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
|