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
Download scripts/_scratch/_length_correct.py from RomanCohort/RNAQwen: direct link, hf CLI and curl.
- Browser
- Download file 8.05 kB
-
https://huggingface.co/RomanCohort/RNAQwen/resolve/main/scripts/_scratch/_length_correct.py
- Command line
-
hf download hf://RomanCohort/RNAQwen/scripts/_scratch/_length_correct.py
-
curl -L -o _length_correct.py https://huggingface.co/RomanCohort/RNAQwen/resolve/main/scripts/_scratch/_length_correct.py
8.05 kB
| """按序列长度矫正的 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()) | |