| """ |
| patch_notebook_v2.py |
| ==================== |
| Correctly patches Video_Deepfake_Detection_Cloud.ipynb to fix the following: |
| |
| 1. ZeroDivisionError in Cell 12 when DATASET_ROOT has no labeled videos. |
| 2. prob_real / prob_fake key-swap bug in the predict_single() return dict |
| (Cell 8). The notebook displayed correct labels in the console table, |
| but saved swapped values in the JSON result file. |
| |
| Run from the video_detection/ folder: |
| python patch_notebook_v2.py |
| |
| After running, re-upload the patched .ipynb to Colab or Kaggle and re-run |
| Cell 8 onward to produce correct JSON exports and Cell 12 evaluation. |
| """ |
| import json |
| import os |
| import sys |
|
|
| NB_PATH = os.path.join( |
| os.path.dirname(os.path.abspath(__file__)), |
| "notebooks", |
| "Video_Deepfake_Detection_Cloud.ipynb", |
| ) |
|
|
|
|
| def load_notebook(path): |
| with open(path, "r", encoding="utf-8") as f: |
| return json.load(f) |
|
|
|
|
| def save_notebook(nb, path): |
| with open(path, "w", encoding="utf-8") as f: |
| json.dump(nb, f, indent=2, ensure_ascii=False) |
| print("[OK] Saved:", path) |
|
|
|
|
| def patch_notebook(): |
| if not os.path.exists(NB_PATH): |
| print("[ERR] Notebook not found:", NB_PATH) |
| sys.exit(1) |
|
|
| nb = load_notebook(NB_PATH) |
| total_patches = 0 |
|
|
| for cell in nb["cells"]: |
| if cell["cell_type"] != "code": |
| continue |
|
|
| source_lines = cell["source"] |
| joined = "".join(source_lines) |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| OLD_PROB = ( |
| " prob_fake = 1.0 - y_val if label == 'REAL' else y_val\n" |
| " prob_real = 1.0 - prob_fake" |
| ) |
| NEW_PROB = ( |
| " # y_val is always P(fake) from max_prediction_value()\n" |
| " prob_fake = y_val\n" |
| " prob_real = 1.0 - prob_fake" |
| ) |
|
|
| if OLD_PROB in joined: |
| patched = joined.replace(OLD_PROB, NEW_PROB, 1) |
| lines = patched.splitlines(keepends=True) |
| |
| if lines and lines[-1].endswith("\n"): |
| lines[-1] = lines[-1][:-1] |
| cell["source"] = lines |
| total_patches += 1 |
| |
| joined = "".join(cell["source"]) |
| print("[OK] Patch 1 applied: fixed prob_real/prob_fake swap in predict_single()") |
|
|
| |
| |
| |
| OLD_ZERO_DIV = ( |
| "print(f'\\n\U0001f4ca Results:" |
| " Acc={correct/total:.1%}" |
| " TPR={tp/(tp+fn):.1%}" |
| " FPR={fp/(fp+tn):.1%}')" |
| ) |
| |
| OLD_ZERO_DIV_ASCII = ( |
| "print(f'\\n Results:" |
| " Acc={correct/total:.1%}" |
| " TPR={tp/(tp+fn):.1%}" |
| " FPR={fp/(fp+tn):.1%}')" |
| ) |
| NEW_ZERO_DIV = ( |
| "if total == 0:\n" |
| " print('[WARN] No labeled videos processed. " |
| "Check DATASET_ROOT structure.')\n" |
| " print(' Expected: DATASET_ROOT/real/*.mp4" |
| " and DATASET_ROOT/fake/*.mp4')\n" |
| " else:\n" |
| " acc = correct / total\n" |
| " tpr = tp / (tp + fn) if (tp + fn) > 0 else 0.0\n" |
| " fpr = fp / (fp + tn) if (fp + tn) > 0 else 0.0\n" |
| " print(f'\\n[RESULTS]" |
| " Acc={acc:.1%} TPR={tpr:.1%} FPR={fpr:.1%}')" |
| ) |
|
|
| matched_old = OLD_ZERO_DIV if OLD_ZERO_DIV in joined else ( |
| OLD_ZERO_DIV_ASCII if OLD_ZERO_DIV_ASCII in joined else None |
| ) |
| if matched_old: |
| patched = joined.replace(matched_old, NEW_ZERO_DIV, 1) |
| lines = patched.splitlines(keepends=True) |
| if lines and lines[-1].endswith("\n"): |
| lines[-1] = lines[-1][:-1] |
| cell["source"] = lines |
| total_patches += 1 |
| print("[OK] Patch 2 applied: ZeroDivisionError guard in Cell 12") |
|
|
| if total_patches == 0: |
| print("[INFO] No patches needed (already applied or pattern not found).") |
| else: |
| save_notebook(nb, NB_PATH) |
| print() |
| print("[DONE]", total_patches, "patch(es) applied successfully.") |
| print(" Re-upload", os.path.basename(NB_PATH), |
| "to Colab/Kaggle and re-run from Cell 8.") |
|
|
|
|
| if __name__ == "__main__": |
| patch_notebook() |
|
|