{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceType":"competition","sourceId":5048,"databundleVersionId":868335,"isSourceIdPinned":false}],"dockerImageVersionId":31329,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!git clone https://github.com/nxtruoong/DoAnCS231 /kaggle/working/code","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-05-15T07:30:34.483346Z","iopub.execute_input":"2026-05-15T07:30:34.483624Z","iopub.status.idle":"2026-05-15T07:30:35.316179Z","shell.execute_reply.started":"2026-05-15T07:30:34.483590Z","shell.execute_reply":"2026-05-15T07:30:35.315199Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"  !cd /kaggle/working/code && python data_prep.py \\\n      --data-root /kaggle/input/competitions/state-farm-distracted-driver-detection \\\n      --out-dir /kaggle/working/splits \\\n      --batch-size 64 --num-workers 4","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-15T07:31:31.831505Z","iopub.execute_input":"2026-05-15T07:31:31.832183Z","iopub.status.idle":"2026-05-15T07:33:41.395643Z","shell.execute_reply.started":"2026-05-15T07:31:31.832144Z","shell.execute_reply":"2026-05-15T07:33:41.394605Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"  !cd /kaggle/working/code && git pull && python train.py \\\n      --data-root /kaggle/input/competitions/state-farm-distracted-driver-detection \\\n      --splits-dir /kaggle/working/splits \\\n      --out-dir /kaggle/working/run5 \\\n      --epochs 80 \\\n      --lr 0.03 \\\n      --warmup-epochs 2 \\\n      --ema-decay 0.99 \\\n      --img-size 320 \\\n      --trivialaugment \\\n      --early-stop-min-delta 0.005 \\\n      --data-parallel","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-15T08:23:34.148344Z","iopub.execute_input":"2026-05-15T08:23:34.149038Z","iopub.status.idle":"2026-05-15T09:46:45.987839Z","shell.execute_reply.started":"2026-05-15T08:23:34.148984Z","shell.execute_reply":"2026-05-15T09:46:45.987193Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"  !cd /kaggle/working/code && git pull && python eval.py \\\n      --ckpt /kaggle/working/run5/best.pt \\\n      --data-root /kaggle/input/competitions/state-farm-distracted-driver-detection \\\n      --splits-dir /kaggle/working/splits \\\n      --out-dir /kaggle/working/run5/eval \\\n      --history-json /kaggle/working/run5/history.json \\\n      --img-size 320","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-15T09:59:47.660582Z","iopub.execute_input":"2026-05-15T09:59:47.661109Z","iopub.status.idle":"2026-05-15T10:00:34.990392Z","shell.execute_reply.started":"2026-05-15T09:59:47.661074Z","shell.execute_reply":"2026-05-15T10:00:34.989324Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"  import json, torch\n  ckpt = torch.load(\"/kaggle/working/run5/best.pt\", map_location=\"cpu\", weights_only=False)\n  print(\"best_val_acc saved in ckpt:\", ckpt[\"best_val_acc\"])\n  hist = json.load(open(\"/kaggle/working/run5/history.json\"))\n  print(\"best EMA val acc:\", max(h[\"ema_val_acc\"] for h in hist))\n  print(\"best raw val acc:\", max(h[\"val_acc\"] for h in hist))\n  print(\"stop epoch:\", hist[-1][\"epoch\"])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-15T10:02:46.819113Z","iopub.execute_input":"2026-05-15T10:02:46.819748Z","iopub.status.idle":"2026-05-15T10:02:48.726232Z","shell.execute_reply.started":"2026-05-15T10:02:46.819713Z","shell.execute_reply":"2026-05-15T10:02:48.725432Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"  from IPython.display import Image, display, Markdown\n  from pathlib import Path\n  import json\n\n  EVAL = Path(\"/kaggle/working/run5/eval\")\n\n  # 1. Final metrics summary\n  hist = json.load(open(\"/kaggle/working/run5/history.json\"))\n  best_raw = max(h[\"val_acc\"] for h in hist)\n  best_ema = max(h[\"ema_val_acc\"] for h in hist)\n  display(Markdown(f\"\"\"\n  ## Run 5 — Final results\n  - **Best raw val acc:** {best_raw:.4f}\n  - **Best EMA val acc:** {best_ema:.4f}\n  - **Stopped at epoch:** {hist[-1]['epoch']} / 80\n  - **Total epochs run:** {len(hist)}\n  \"\"\"))\n\n  # 2. Classification report\n  display(Markdown(\"## Per-class metrics\"))\n  print(open(EVAL / \"classification_report.txt\").read())\n\n  # 3. metrics.json (overall accuracy + macro/weighted F1)\n  if (EVAL / \"metrics.json\").exists():\n      display(Markdown(\"## metrics.json\"))\n      print(json.dumps(json.load(open(EVAL / \"metrics.json\")), indent=2))\n\n  # 4. Training curves\n  display(Markdown(\"## Training curves\"))\n  display(Image(filename=str(EVAL / \"training_curves.png\")))\n\n  # 5. Confusion matrix\n  display(Markdown(\"## Confusion matrix\"))\n  display(Image(filename=str(EVAL / \"confusion_matrix.png\")))\n\n  # 6. Per-driver accuracy\n  display(Markdown(\"## Per-driver accuracy (held-out drivers)\"))\n  display(Image(filename=str(EVAL / \"per_driver_accuracy.png\")))\n  import pandas as pd\n  print(pd.read_csv(EVAL / \"per_driver_accuracy.csv\").to_string(index=False))\n\n  # 7. Attention grid (CBAM SAM heatmap, 1 per class)\n  display(Markdown(\"## CBAM spatial attention (1 per class)\"))\n  display(Image(filename=str(EVAL / \"attention_grid.png\")))\n\n  # 8. Failure cases\n  display(Markdown(\"## Failure cases (12 misclassified)\"))\n  display(Image(filename=str(EVAL / \"failures.png\")))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-15T10:03:30.746850Z","iopub.execute_input":"2026-05-15T10:03:30.747888Z","iopub.status.idle":"2026-05-15T10:03:31.127135Z","shell.execute_reply.started":"2026-05-15T10:03:30.747856Z","shell.execute_reply":"2026-05-15T10:03:31.126163Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n  !cd /kaggle/working && zip -r run5_artifacts.zip \\\n      run5/best.pt \\\n      run5/final.pt \\\n      run5/history.json \\\n      run5/eval \\\n      splits/stats.json \\\n      splits/train.csv \\\n      splits/val.csv","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-15T10:05:46.502632Z","iopub.execute_input":"2026-05-15T10:05:46.503186Z","iopub.status.idle":"2026-05-15T10:06:01.082295Z","shell.execute_reply.started":"2026-05-15T10:05:46.503154Z","shell.execute_reply":"2026-05-15T10:06:01.081101Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"  !cd /kaggle/working/code && git pull && python eval.py \\\n      --ckpt /kaggle/working/run5/best.pt \\\n      --data-root /kaggle/input/competitions/state-farm-distracted-driver-detection \\\n      --splits-dir /kaggle/working/splits \\\n      --out-dir /kaggle/working/run5/eval_v2 \\\n      --history-json /kaggle/working/run5/history.json \\\n      --img-size 320","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-15T10:18:00.639323Z","iopub.execute_input":"2026-05-15T10:18:00.640139Z","iopub.status.idle":"2026-05-15T10:18:44.447811Z","shell.execute_reply.started":"2026-05-15T10:18:00.640099Z","shell.execute_reply":"2026-05-15T10:18:44.447012Z"}},"outputs":[],"execution_count":null}]}