diff --git a/docs/figures/neuron/phase17/loss_curves.png b/docs/figures/neuron/phase17/loss_curves.png new file mode 100644 index 0000000..f979339 Binary files /dev/null and b/docs/figures/neuron/phase17/loss_curves.png differ diff --git a/docs/figures/neuron/phase17/phase16_vs_phase17.png b/docs/figures/neuron/phase17/phase16_vs_phase17.png new file mode 100644 index 0000000..57abe6a Binary files /dev/null and b/docs/figures/neuron/phase17/phase16_vs_phase17.png differ diff --git a/notebooks/02-function-level/17-phase17-scale-up.ipynb b/notebooks/02-function-level/17-phase17-scale-up.ipynb new file mode 100644 index 0000000..001ae3c --- /dev/null +++ b/notebooks/02-function-level/17-phase17-scale-up.ipynb @@ -0,0 +1,497 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "0", + "metadata": {}, + "source": "# 17-phase17-scale-up\n\n**neuron Phase 17** — paradigm 의 dynamic method (DST, Net2Net grow) 의 **advantage 가 scale-up 으로 발현되는지** 검증.\n\n**배경**: Phase 16a/16b 둘 다 framework 검증은 PASS 했으나 *expected performance benefit 미실현*. Phase 16b Notion 분석에서 원인을 *본 setup (~1M params, 1500 step) 의 scale 한계* 로 결론. RigL/Net2Net 의 reference paper 들이 large-scale 에서만 advantage 발현하는 알려진 패턴.\n\n**핵심 가설** (scale-up 효과):\n1. **DST_RigL ≤ static_prune (16a 의 advantage 발현)** — 더 긴 학습으로 swap cost 가 amortized?\n2. **grown ≈ large_baseline (16b 의 gap 축소)** — 더 긴 post-grow 학습으로 새 capacity 활성화?\n3. **scale 자체의 효과 분리** — control mode 로 hyperparameter 와 scale 효과 분리 (Copilot #3315013786 반영)\n4. **all-finite + smooth convergence** — 확대된 setup 에서도 안정성?\n\n설계: 5 mode × 2 seed = 10 run at **scale-up config**.\n\n| 항목 | Phase 16 | Phase 17 (scale-up) | 배수 |\n|---|---|---|---|\n| hidden_dim | 128 | **256** | 2x |\n| n_layers | 4 | **6** | 1.5x |\n| ffn_dim (large) | 256 | **512** | 2x |\n| max_steps | 1500 | **5000** | 3.3x |\n| approx params | ~1M | **~5M** | ~5x |\n\n5 mode:\n- `dense_large`: 큰 모델 baseline (target reference)\n- `static_prune_50`: dense 학습 후 step 2500 에서 50% prune (Phase 15 at scale)\n- `DST_RigL_p16hp`: **Phase 16a 동일 hyperparameter** (period=50, swap=10%) at Phase 17 scale → **scale 효과 only 분리**\n- `DST_RigL_p17hp`: Phase 17 의 보수적 hyperparameter (period=200, swap=5%) at Phase 17 scale → **scale + hp 동시 효과**\n- `grown`: ffn=256 시작 → step 2500 에서 512 로 grow (Phase 16b at scale)\n\n**Confound 명시 (Copilot #3315013786)**: `DST_RigL_p17hp` 만 보면 *scale 변화* 와 *hyperparameter 변화* 가 confounded. 두 효과 분리를 위해 `DST_RigL_p16hp` (Phase 16a 와 동일 hp) 를 control 로 추가 → Phase 16a 결과와 직접 비교 시 *순수 scale 효과* 측정 가능.\n\narch 고정: `hybrid_around_one_around_one` + `use_full_graph=True`\n데이터: TinyShakespeare (char-LM, block_size=64 유지)\n시드: [42, 123]\n작성일: 2026-05-28\n연관: Issue [#80](https://github.com/EinSofINTEREST/GraphLM/issues/80) / Phase 16 메인 [#75](https://github.com/EinSofINTEREST/GraphLM/issues/75)" + }, + { + "cell_type": "markdown", + "id": "1", + "metadata": {}, + "source": [ + "## 0. 환경 / 의존성" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2", + "metadata": {}, + "outputs": [], + "source": [ + "from __future__ import annotations\n", + "\n", + "import math\n", + "import statistics\n", + "from pathlib import Path\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import torch\n", + "\n", + "from graphlm.data.tinyshakespeare import (\n", + " CharTokenizer,\n", + " TinyShakespeareDataset,\n", + " load_tinyshakespeare_text,\n", + ")\n", + "from graphlm.neuron.hybrid_transformer_demo import (\n", + " HybridTransformerTrainConfig,\n", + " train_hybrid_transformer_lm,\n", + ")\n", + "from graphlm.utils import safe_perplexity\n", + "\n", + "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n", + "print(f\"device: {device}\")\n", + "print(f\"torch: {torch.__version__}\")" + ] + }, + { + "cell_type": "markdown", + "id": "3", + "metadata": {}, + "source": [ + "## 1. Config — scale-up" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4", + "metadata": {}, + "outputs": [], + "source": [ + "text = load_tinyshakespeare_text()\n", + "tokenizer = CharTokenizer(text)\n", + "dataset = TinyShakespeareDataset(text, tokenizer)\n", + "vocab_size = tokenizer.vocab_size\n", + "print(f\"vocab_size = {vocab_size}, dataset size = {len(dataset)}\")\n", + "\n", + "# scale-up — Phase 16 대비 hidden 2x, layers 1.5x, ffn 2x, steps 3.3x\n", + "HIDDEN_DIM = 256\n", + "N_HEADS = 8 # head_dim = 32 (256/8)\n", + "N_LAYERS = 6\n", + "GROUP_SIZE = 16\n", + "BLOCK_SIZE = 64\n", + "BATCH_SIZE = 32\n", + "LR = 3e-4\n", + "MAX_STEPS = 5000\n", + "DYNAMIC_AT_STEP = MAX_STEPS // 2 # 2500 — prune/grow/DST 시작 시점\n", + "# Phase 16a hyperparameter (control — scale 효과 only 분리)\n", + "DST_PERIOD_P16 = 50\n", + "DST_SWAP_FRACTION_P16 = 0.1\n", + "# Phase 17 hyperparameter (보수적 — 추가로 swap-cost 완화 시도)\n", + "DST_PERIOD_P17 = 200\n", + "DST_SWAP_FRACTION_P17 = 0.05\n", + "# 빠른 테스트 (MAX_STEPS<500) 대응: max(1, ...) 로 음수 방지 (gemini #3314998767)\n", + "DST_END_STEP = max(1, MAX_STEPS - 500) # 마지막 500 step stabilize\n", + "SEEDS = [42, 123]\n", + "ARCH = \"hybrid_around_one_around_one\"\n", + "FFN_SMALL = 256\n", + "FFN_LARGE = 512\n", + "\n", + "# 5 mode 정의 — Copilot #3315013786 confound 분리 위해 DST 두 hp variant 모두 포함\n", + "MODES = [\n", + " {\n", + " \"name\": \"dense_large\",\n", + " \"ffn_dim\": FFN_LARGE,\n", + " \"prune_at_step\": None,\n", + " \"prune_fraction\": 0.0,\n", + " \"regrow_method\": None,\n", + " \"dst_period\": None,\n", + " \"dst_swap_fraction\": 0.0,\n", + " \"grow_at_step\": None,\n", + " \"grow_ffn_target\": None,\n", + " },\n", + " {\n", + " \"name\": \"static_prune_50\",\n", + " \"ffn_dim\": FFN_LARGE,\n", + " \"prune_at_step\": DYNAMIC_AT_STEP,\n", + " \"prune_fraction\": 0.5,\n", + " \"regrow_method\": None,\n", + " \"dst_period\": None,\n", + " \"dst_swap_fraction\": 0.0,\n", + " \"grow_at_step\": None,\n", + " \"grow_ffn_target\": None,\n", + " },\n", + " {\n", + " \"name\": \"DST_RigL_p16hp\",\n", + " \"ffn_dim\": FFN_LARGE,\n", + " \"prune_at_step\": DYNAMIC_AT_STEP,\n", + " \"prune_fraction\": 0.5,\n", + " \"regrow_method\": \"rigl\",\n", + " \"dst_period\": DST_PERIOD_P16, # Phase 16a 와 동일\n", + " \"dst_swap_fraction\": DST_SWAP_FRACTION_P16,\n", + " \"grow_at_step\": None,\n", + " \"grow_ffn_target\": None,\n", + " },\n", + " {\n", + " \"name\": \"DST_RigL_p17hp\",\n", + " \"ffn_dim\": FFN_LARGE,\n", + " \"prune_at_step\": DYNAMIC_AT_STEP,\n", + " \"prune_fraction\": 0.5,\n", + " \"regrow_method\": \"rigl\",\n", + " \"dst_period\": DST_PERIOD_P17, # Phase 17 보수적\n", + " \"dst_swap_fraction\": DST_SWAP_FRACTION_P17,\n", + " \"grow_at_step\": None,\n", + " \"grow_ffn_target\": None,\n", + " },\n", + " {\n", + " \"name\": \"grown\",\n", + " \"ffn_dim\": FFN_SMALL,\n", + " \"prune_at_step\": None,\n", + " \"prune_fraction\": 0.0,\n", + " \"regrow_method\": None,\n", + " \"dst_period\": None,\n", + " \"dst_swap_fraction\": 0.0,\n", + " \"grow_at_step\": DYNAMIC_AT_STEP,\n", + " \"grow_ffn_target\": FFN_LARGE,\n", + " },\n", + "]\n", + "print(\"\\nScale-up config:\")\n", + "print(\n", + " f\" hidden={HIDDEN_DIM}, n_heads={N_HEADS}, n_layers={N_LAYERS}, ffn(L)={FFN_LARGE}, group={GROUP_SIZE}\"\n", + ")\n", + "print(f\" max_steps={MAX_STEPS}, dynamic_at={DYNAMIC_AT_STEP}\")\n", + "print(f\" DST p16hp: period={DST_PERIOD_P16}, swap={DST_SWAP_FRACTION_P16} (Phase 16a 동일)\")\n", + "print(f\" DST p17hp: period={DST_PERIOD_P17}, swap={DST_SWAP_FRACTION_P17} (보수적)\")" + ] + }, + { + "cell_type": "markdown", + "id": "5", + "metadata": {}, + "source": "## 2. Sweep 실행 (5 mode × 2 seed = 10 run, GPU 권장)" + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6", + "metadata": {}, + "outputs": [], + "source": [ + "results = {}\n", + "for mode in MODES:\n", + " for seed in SEEDS:\n", + " key = (mode[\"name\"], seed)\n", + " print(f\"\\n== mode={mode['name']} seed={seed} ==\")\n", + " cfg = HybridTransformerTrainConfig(\n", + " dataset=dataset,\n", + " vocab_size=vocab_size,\n", + " hidden_dim=HIDDEN_DIM,\n", + " n_heads=N_HEADS,\n", + " ffn_dim=mode[\"ffn_dim\"],\n", + " n_layers=N_LAYERS,\n", + " group_size=GROUP_SIZE,\n", + " arch=ARCH,\n", + " use_full_graph=True,\n", + " block_size=BLOCK_SIZE,\n", + " batch_size=BATCH_SIZE,\n", + " lr=LR,\n", + " max_steps=MAX_STEPS,\n", + " prune_at_step=mode[\"prune_at_step\"],\n", + " prune_fraction=mode[\"prune_fraction\"],\n", + " regrow_method=mode[\"regrow_method\"],\n", + " dst_period=mode[\"dst_period\"],\n", + " dst_swap_fraction=mode[\"dst_swap_fraction\"],\n", + " dst_end_step=DST_END_STEP if mode[\"regrow_method\"] else None,\n", + " grow_at_step=mode[\"grow_at_step\"],\n", + " grow_ffn_target=mode[\"grow_ffn_target\"],\n", + " seed=seed,\n", + " device=device,\n", + " )\n", + " out = train_hybrid_transformer_lm(cfg)\n", + " results[key] = out\n", + " n_cycles = len(out[\"dst_cycles\"])\n", + " print(\n", + " f\" final_loss = {out['final_loss']:.4f} (ppl = {safe_perplexity(out['final_loss']):.2f})\"\n", + " f\" params = {out['final_param_count']:,}\"\n", + " f\" sparsity = {out['final_sparsity']:.3f} dst_cycles = {n_cycles}\"\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "7", + "metadata": {}, + "source": [ + "## 3. 결과 표 + 자동 verdict" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8", + "metadata": {}, + "outputs": [], + "source": [ + "print(\n", + " f\"{'mode':>16s} {'seed':>6s} {'final_loss':>12s} {'perplexity':>12s} \"\n", + " f\"{'params':>10s} {'sparsity':>10s}\"\n", + ")\n", + "print(\"-\" * 75)\n", + "for (name, seed), out in results.items():\n", + " fl = out[\"final_loss\"]\n", + " print(\n", + " f\"{name:>16s} {seed:>6d} {fl:>12.4f} {safe_perplexity(fl):>12.2f} \"\n", + " f\"{out['final_param_count']:>10,} {out['final_sparsity']:>10.3f}\"\n", + " )\n", + "\n", + "# mode 별 평균\n", + "print(\"\\n== Mode summary (mean ± σ across seeds) ==\")\n", + "summary = {}\n", + "for mode in MODES:\n", + " name = mode[\"name\"]\n", + " vals = [results[(name, s)][\"final_loss\"] for s in SEEDS]\n", + " params = [results[(name, s)][\"final_param_count\"] for s in SEEDS]\n", + " sparsities = [results[(name, s)][\"final_sparsity\"] for s in SEEDS]\n", + " m = statistics.mean(vals)\n", + " sd = statistics.stdev(vals) if len(vals) > 1 else 0.0\n", + " summary[name] = (m, sd, statistics.mean(params), statistics.mean(sparsities))\n", + " print(\n", + " f\" {name:>16s} {m:.4f} ± {sd:.4f} (ppl ≈ {safe_perplexity(m):.2f}) \"\n", + " f\"params={statistics.mean(params):,.0f} sparsity={statistics.mean(sparsities):.3f}\"\n", + " )\n", + "\n", + "# 자동 verdict\n", + "print(\"\\n== Verdict ==\")\n", + "dense_loss = summary[\"dense_large\"][0]\n", + "static_loss = summary[\"static_prune_50\"][0]\n", + "rigl_p16_loss = summary[\"DST_RigL_p16hp\"][0]\n", + "rigl_p17_loss = summary[\"DST_RigL_p17hp\"][0]\n", + "grown_loss = summary[\"grown\"][0]\n", + "\n", + "# 1. all-finite\n", + "all_finite = all(math.isfinite(out[\"final_loss\"]) for out in results.values())\n", + "verdict_1 = \"PASS\" if all_finite else \"FAIL\"\n", + "print(f\"1. all-finite: {all_finite} [{verdict_1}]\")\n", + "\n", + "# 2. Phase 16a 가설 — 순수 scale 효과 (p16hp control) 로 검증\n", + "diff_rigl_static = rigl_p16_loss - static_loss\n", + "verdict_2 = \"PASS\" if diff_rigl_static <= 0.02 else \"FAIL\"\n", + "print(\n", + " f\"2. DST_RigL_p16hp ≤ static + 0.02 (순수 scale 효과): diff = {diff_rigl_static:+.4f} [{verdict_2}]\"\n", + ")\n", + "if diff_rigl_static < 0:\n", + " print(\" → DST advantage 발현! Phase 16a 의 scale-limit 가설 입증 (순수 scale 효과).\")\n", + "elif diff_rigl_static < 0.005:\n", + " print(\" → DST 가 static 근방까지 도달 — 부분 advantage.\")\n", + "else:\n", + " print(\" → DST 여전히 static 보다 약간 열위 — 추가 scale-up 필요.\")\n", + "\n", + "# 2b. hyperparameter 효과 — p17hp vs p16hp (같은 scale 에서 hp 만 다름)\n", + "diff_hp = rigl_p17_loss - rigl_p16_loss\n", + "print(f\" 2b. hp 효과: p17hp - p16hp = {diff_hp:+.4f} (음수면 보수적 hp 가 도움)\")\n", + "\n", + "# 3. Phase 16b 가설 재검증 — grown ≤ dense_large + 0.02\n", + "diff_grown_dense = grown_loss - dense_loss\n", + "verdict_3 = \"PASS\" if diff_grown_dense <= 0.02 else \"FAIL\"\n", + "print(f\"3. grown ≤ dense_large + 0.02 (16b 재검증): diff = {diff_grown_dense:+.4f} [{verdict_3}]\")\n", + "if diff_grown_dense < 0.01:\n", + " print(\" → grown 이 dense_large 근방 — 0-init activation 충분.\")\n", + "else:\n", + " print(\" → grown 과 dense 격차 여전 — post-grow 학습 시간 더 필요할 수 있음.\")\n", + "\n", + "# 4. plateau 도달 확인 — 마지막 500 step 의 loss 변동 < threshold\n", + "# 짧은 학습 (MAX_STEPS<500) 대응: 동적 half 분할 (gemini #3314998775)\n", + "print(\"\\n plateau 분석 (마지막 500 step rolling mean 변동):\")\n", + "for name in [m[\"name\"] for m in MODES]:\n", + " for seed in SEEDS:\n", + " losses = results[(name, seed)][\"losses\"]\n", + " last_500 = losses[-500:]\n", + " half_len = len(last_500) // 2\n", + " if half_len > 0:\n", + " first_half = sum(last_500[:half_len]) / half_len\n", + " second_half = sum(last_500[half_len:]) / (len(last_500) - half_len)\n", + " plateau_drift = second_half - first_half\n", + " else:\n", + " plateau_drift = 0.0\n", + " print(\n", + " f\" {name:>16s} seed={seed}: drift = {plateau_drift:+.4f} (< -0.01 = still learning)\"\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "9", + "metadata": {}, + "source": [ + "## 4. Loss curve 시각화" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "10", + "metadata": {}, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(1, 1, figsize=(12, 6))\n", + "colors = {\n", + " \"dense_large\": \"tab:green\",\n", + " \"static_prune_50\": \"tab:red\",\n", + " \"DST_RigL_p16hp\": \"tab:purple\",\n", + " \"DST_RigL_p17hp\": \"tab:blue\",\n", + " \"grown\": \"tab:orange\",\n", + "}\n", + "window = 100 # scale-up 이라 더 긴 rolling window\n", + "\n", + "for mode in MODES:\n", + " name = mode[\"name\"]\n", + " losses_per_seed = [results[(name, s)][\"losses\"] for s in SEEDS]\n", + " smoothed = []\n", + " for losses in losses_per_seed:\n", + " smoothed.append(\n", + " [\n", + " sum(losses[max(0, i - window + 1) : i + 1]) / min(i + 1, window)\n", + " for i in range(len(losses))\n", + " ]\n", + " )\n", + " arr = torch.tensor(smoothed)\n", + " mean = arr.mean(dim=0)\n", + " # single seed 시 std=NaN 회피 (gemini #3314998777)\n", + " std = arr.std(dim=0) if arr.size(0) > 1 else torch.zeros_like(mean)\n", + " steps = list(range(len(mean)))\n", + " ax.plot(steps, mean, label=name, color=colors[name], linewidth=1.5)\n", + " ax.fill_between(steps, mean - std, mean + std, color=colors[name], alpha=0.12)\n", + "\n", + "# dynamic step + DST end 수직선\n", + "ax.axvline(\n", + " DYNAMIC_AT_STEP,\n", + " color=\"black\",\n", + " linestyle=\":\",\n", + " alpha=0.5,\n", + " label=f\"prune/grow @ {DYNAMIC_AT_STEP}\",\n", + ")\n", + "ax.axvline(DST_END_STEP, color=\"gray\", linestyle=\":\", alpha=0.4, label=f\"DST end @ {DST_END_STEP}\")\n", + "\n", + "ax.set_xlabel(\"step\")\n", + "ax.set_ylabel(f\"loss (rolling mean w={window})\")\n", + "ax.set_title(\n", + " \"Phase 17 scale-up (hidden=256, n_layers=6, ffn(L)=512, steps=5000) — 5 mode (mean ± σ over 2 seeds)\"\n", + ")\n", + "ax.legend(loc=\"upper right\")\n", + "ax.grid(alpha=0.3)\n", + "plt.tight_layout()\n", + "\n", + "out_dir = Path(\"../../runs/notebook-neuron-phase17\")\n", + "out_dir.mkdir(parents=True, exist_ok=True)\n", + "fig.savefig(out_dir / \"loss_curves.png\", dpi=150, bbox_inches=\"tight\")\n", + "plt.show()\n", + "print(f\"saved: {out_dir / 'loss_curves.png'}\")" + ] + }, + { + "cell_type": "markdown", + "id": "11", + "metadata": {}, + "source": [ + "## 5. Phase 15/16/17 합산 비교 (scale 영향 시각화)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "12", + "metadata": {}, + "outputs": [], + "source": [ + "# Phase 16 baseline 수치 — Notion 정리 페이지 출처 (Copilot #3315013726 — 향후 CSV 자동 로드 검토)\n", + "# 출처:\n", + "# Phase 16a: https://www.notion.so/36de8b70b7aa819aaa54d561fc222fa1\n", + "# Phase 16b: https://www.notion.so/36ee8b70b7aa811bb354c4fc98a484ed\n", + "# Config: hidden=128, n_layers=4, ffn=256 (16a) / 256↔128→256 (16b), 1500 step, seeds [42, 123]\n", + "p16a_baselines = {\n", + " \"dense\": 1.8999, # Phase 16a dense (ffn=256)\n", + " \"static_50\": 1.9777, # Phase 16a static_50\n", + " \"DST_RigL_50\": 1.9831, # Phase 16a DST_RigL_50 (period=50, swap=0.1) — Phase 17 p16hp 와 직접 비교\n", + "}\n", + "p16b_grown = 1.9428 # Phase 16b grown (ffn 128 → 256)\n", + "\n", + "# Phase 17 결과 — summary 에서 추출\n", + "# 비교 mapping: p16 의 DST_RigL_50 ↔ Phase 17 의 DST_RigL_p16hp (같은 hp, scale 만 다름)\n", + "p17 = {name: summary[name][0] for name in [m[\"name\"] for m in MODES]}\n", + "\n", + "fig, ax = plt.subplots(1, 1, figsize=(11, 5))\n", + "modes_plot = [\"dense\", \"static_prune_50\", \"DST_RigL (p16hp control)\", \"grown\"]\n", + "x = list(range(len(modes_plot)))\n", + "p16_vals = [\n", + " p16a_baselines[\"dense\"],\n", + " p16a_baselines[\"static_50\"],\n", + " p16a_baselines[\"DST_RigL_50\"],\n", + " p16b_grown,\n", + "]\n", + "# Phase 17 의 p16hp 가 Phase 16 와 같은 hp 이므로 직접 비교 (순수 scale 효과)\n", + "p17_vals = [\n", + " p17[\"dense_large\"],\n", + " p17[\"static_prune_50\"],\n", + " p17[\"DST_RigL_p16hp\"], # ← p16hp control 만 비교\n", + " p17[\"grown\"],\n", + "]\n", + "width = 0.35\n", + "ax.bar(\n", + " [i - width / 2 for i in x],\n", + " p16_vals,\n", + " width,\n", + " label=\"Phase 16 (~1M, 1500 step)\",\n", + " color=\"lightblue\",\n", + ")\n", + "ax.bar(\n", + " [i + width / 2 for i in x], p17_vals, width, label=\"Phase 17 (~5M, 5000 step)\", color=\"darkblue\"\n", + ")\n", + "ax.set_xticks(x)\n", + "ax.set_xticklabels(modes_plot, rotation=15)\n", + "ax.set_ylabel(\"final loss (mean over 2 seeds)\")\n", + "ax.set_title(\"Phase 17 vs Phase 16 — 순수 scale 효과 (같은 hp 로 비교)\")\n", + "ax.legend()\n", + "ax.grid(alpha=0.3, axis=\"y\")\n", + "plt.tight_layout()\n", + "fig.savefig(out_dir / \"phase16_vs_phase17.png\", dpi=150, bbox_inches=\"tight\")\n", + "plt.show()\n", + "print(f\"saved: {out_dir / 'phase16_vs_phase17.png'}\")\n", + "print(f\"\\nphase17 의 DST_RigL_p17hp (보수적 hp) = {p17['DST_RigL_p17hp']:.4f} (hp ablation 참고용)\")" + ] + }, + { + "cell_type": "markdown", + "id": "13", + "metadata": {}, + "source": [ + "## 6. 결론 / 다음 단계\n", + "\n", + "(셀 출력 보고 사용자가 채울 영역)\n", + "\n", + "**핵심 질문 답변**:\n", + "- DST_RigL advantage 가 scale-up 으로 발현되었나?\n", + "- grown 의 capacity gap 이 축소되었나?\n", + "- Phase 16 대비 모든 mode 의 절대 loss 가 명확히 낮아짐?\n", + "\n", + "**Phase 18 후보**:\n", + "- (advantage 발현 시) 16a + 16b 결합 — grow + DST 동시\n", + "- (여전히 미실현 시) dataset 확대 (OpenWebText subset) 또는 method 개선 (Net2WiderNet duplication / RigL ablation)\n", + "- (명백한 우수성 발견 시) scaling law 분석 + 결과 정리" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "GraphLM (uv .venv)", + "language": "python", + "name": "graphlm-uv-venv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file