{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import json\n\ndef patch_notebook(input_path, output_path):\n    with open(input_path, 'r', encoding='utf-8') as f:\n        nb = json.load(f)\n\n    for cell in nb['cells']:\n        if cell['cell_type'] != 'code':\n            continue\n            \n        source = \"\".join(cell[\"source\"])\n\n        # 1. EPOCHS and Augmentation constants\n        if \"EPOCHS = 10\" in source:\n            source = source.replace(\"EPOCHS = 10\", \"EPOCHS = 12\")\n            source = source.replace(\"AUG_ROT_DEG = 8.0\", \"AUG_ROT_DEG = 12.0\")\n            source = source.replace(\"AUG_INTENSITY = 0.10\", \"AUG_INTENSITY = 0.20\")\n        \n        # 2. RUNS definition\n        if 'RUNS = [\\n    {\"name\": \"r224\"' in source:\n            old_runs = \"\"\"RUNS = [\n    {\"name\": \"r224\", \"img\": 224},\n    {\"name\": \"r336\", \"img\": 336},\n]\"\"\"\n            new_runs = \"\"\"RUNS = [\n    {\"name\": f\"r256_fold{fold}\", \"img\": 256, \"fold\": fold} for fold in range(5)\n]\"\"\"\n            source = source.replace(old_runs, new_runs)\n\n        # 3. Model construction\n        if 'model = build_model(UNFREEZE_LAST).to(dev)' in source:\n            source = source.replace(\n                'model = build_model(UNFREEZE_LAST).to(dev)',\n                'model = build_model(UNFREEZE_LAST, variant=\"base\", pool=\"cls_mean_focal\").to(dev)'\n            )\n            \n        # 4. Fold splitting logic\n        if 'va = np.array([i for i in keep if grp[i] == 0])' in source:\n            full_old = \"\"\"    va = np.array([i for i in keep if grp[i] == 0])\n    tr = np.array([i for i in keep if grp[i] != 0])\n    if len(va) == 0 or len(tr) < BATCH_STUDIES:\n        cut = max(1, len(keep) // 5)\n        va, tr = keep[:cut], keep[cut:]\n    log(f\"train {len(tr)} / holdout {len(va)} studies\")\n\n    # The annotated studies stay in training - they are the highest-quality labels in\n    # the corpus and there are too few to discard - so the honest annotation check uses\n    # only the ones that fell in the holdout. Evaluating on the rest would be scoring the\n    # model against examples it was trained on, at triple weight, with the true answer.\n    gpos = {s: i for i, s in enumerate(st_tr)}\n    va_set = set(va.tolist())\n    gi = np.array([gpos[s] for s in gold.index if s in gpos and gpos[s] in va_set])\n    gold_y = gold.loc[[st_tr[i] for i in gi]].values.astype(int) if len(gi) else None\n    yv = (Y[va] > 0.5).astype(int)\n    log(f\"annotation check: {len(gi)} of {len(gold)} annotated studies are in the holdout\")\n\n    # ---- fine-tune -------------------------------------------------------- #\n    dev = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n    results, test_preds = {}, {}\n\n    for cfg in RUNS:\"\"\"\n\n            full_new = \"\"\"    # ---- fine-tune -------------------------------------------------------- #\n    dev = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n    results, test_preds = {}, {}\n    gpos = {s: i for i, s in enumerate(st_tr)}\n\n    for cfg in RUNS:\n        fold = cfg.get(\"fold\", 0)\n        va = np.array([i for i in keep if grp[i] == fold])\n        tr = np.array([i for i in keep if grp[i] != fold])\n        if len(va) == 0 or len(tr) < BATCH_STUDIES:\n            cut = max(1, len(keep) // 5)\n            va, tr = keep[:cut], keep[cut:]\n        \n        va_set = set(va.tolist())\n        gi = np.array([gpos[s] for s in gold.index if s in gpos and gpos[s] in va_set])\n        gold_y = gold.loc[[st_tr[i] for i in gi]].values.astype(int) if len(gi) else None\n        yv = (Y[va] > 0.5).astype(int)\n        log(f\"train {len(tr)} / holdout {len(va)} studies (fold {fold})\")\"\"\"\n            source = source.replace(full_old, full_new)\n\n        # 5. The submission logic fix\n        if 'sub = write_submission(test_preds[pick], st_te, test_df, \"submission.csv\")' in source:\n            source = source.replace(\n                'sub = write_submission(test_preds[pick], st_te, test_df, \"submission.csv\")',\n                'sub = write_submission(ens, st_te, test_df, \"submission.csv\")'\n            )\n            # update log line for clarity\n            source = source.replace(\n                'log(f\"submission.csv = {pick}; {sub.shape}; \"',\n                'log(f\"submission.csv = ENSEMBLE; {sub.shape}; \"'\n            )\n\n        # 6. Cutout in augment()\n        if '    x = (x * scale).clamp(0, 255)\\n    return x.reshape(*lead, *x.shape[-3:]).to(imgs.dtype)' in source:\n            old_aug = \"\"\"    x = (x * scale).clamp(0, 255)\n    return x.reshape(*lead, *x.shape[-3:]).to(imgs.dtype)\"\"\"\n            new_aug = \"\"\"    x = (x * scale).clamp(0, 255)\n\n    # Random Erasing / Cutout\n    cut_mask = torch.rand(n, device=dev) < 0.20\n    if cut_mask.any():\n        h, w = x.shape[-2:]\n        ch, cw = int(h * 0.2), int(w * 0.2)\n        for i in range(n):\n            if cut_mask[i]:\n                y1 = torch.randint(0, h - ch, (1,)).item()\n                x1 = torch.randint(0, w - cw, (1,)).item()\n                x[i, :, y1:y1+ch, x1:x1+cw] = 0.0\n\n    return x.reshape(*lead, *x.shape[-3:]).to(imgs.dtype)\"\"\"\n            source = source.replace(old_aug, new_aug)\n\n        # Reconstruct cell source lines properly\n        if \"\\n\" in source:\n            cell[\"source\"] = [line + \"\\n\" for line in source.split(\"\\n\")]\n            cell[\"source\"][-1] = cell[\"source\"][-1].rstrip(\"\\n\")\n        else:\n            cell[\"source\"] = [source]\n\n    with open(output_path, 'w', encoding='utf-8') as f:\n        json.dump(nb, f, indent=1)\n\nif __name__ == '__main__':\n    input_file = r\"C:\\Users\\lenovo\\Downloads\\rsna-knee-baseline-v1-fracture-tta-pool-probe.ipynb\"\n    output_file = r\"d:\\RSNA Knee Abnormality Detection\\rsna-knee-ultimate-v3.ipynb\"\n    patch_notebook(input_file, output_file)\n    print(f\"Generated {output_file}\")","metadata":{"_uuid":"5d167bf9-5860-4f4e-9657-74106e5dc461","_cell_guid":"53e975dc-d072-4927-8da7-a05c20dec8a9","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null}]}