{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[],"dockerImageVersionId":28755,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import sys\nimport platform\nimport torch\n\nprint(\"=\" * 60)\nprint(\"Environment Information\")\nprint(\"=\" * 60)\n\nprint(f\"Python Version      : {sys.version.split()[0]}\")\nprint(f\"Platform            : {platform.platform()}\")\n\nprint(f\"\\nPyTorch Version     : {torch.__version__}\")\nprint(f\"CUDA Available      : {torch.cuda.is_available()}\")\n\nif torch.cuda.is_available():\n    print(f\"CUDA Version        : {torch.version.cuda}\")\n    print(f\"GPU Name            : {torch.cuda.get_device_name(0)}\")\n    print(f\"Number of GPUs      : {torch.cuda.device_count()}\")\nelse:\n    print(\"No CUDA device detected.\")\n\nprint(\"=\" * 60)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:35:39.886981Z","iopub.execute_input":"2026-07-11T17:35:39.887821Z","iopub.status.idle":"2026-07-11T17:35:42.021207Z","shell.execute_reply.started":"2026-07-11T17:35:39.887684Z","shell.execute_reply":"2026-07-11T17:35:42.020092Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from pathlib import Path\nimport shutil\nimport os\n\n# Root working directory\nWORK_DIR = Path(\"/kaggle/working\")\n\n# Project directory\nPROJECT_DIR = WORK_DIR / \"SlowFormer\"\n\n# Directory for outputs\nOUTPUT_DIR = WORK_DIR / \"outputs\"\n\n# Directory for checkpoints\nCHECKPOINT_DIR = OUTPUT_DIR / \"checkpoints\"\n\n# Directory for plots\nPLOT_DIR = OUTPUT_DIR / \"plots\"\n\n# Directory for csv results\nRESULT_DIR = OUTPUT_DIR / \"results\"\n\n# Remove any previous project clone\nif PROJECT_DIR.exists():\n    shutil.rmtree(PROJECT_DIR)\n\n# Create output folders\nfor d in [OUTPUT_DIR, CHECKPOINT_DIR, PLOT_DIR, RESULT_DIR]:\n    d.mkdir(parents=True, exist_ok=True)\n\nprint(\"Project directory :\", PROJECT_DIR)\nprint(\"Output directory  :\", OUTPUT_DIR)\n\nprint(\"\\nCreated folders:\")\nfor d in [CHECKPOINT_DIR, PLOT_DIR, RESULT_DIR]:\n    print(\"✓\", d)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:35:42.022801Z","iopub.execute_input":"2026-07-11T17:35:42.023265Z","iopub.status.idle":"2026-07-11T17:35:42.051916Z","shell.execute_reply.started":"2026-07-11T17:35:42.02324Z","shell.execute_reply":"2026-07-11T17:35:42.05107Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!git clone https://github.com/UCDvision/SlowFormer.git $PROJECT_DIR","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:35:42.052896Z","iopub.execute_input":"2026-07-11T17:35:42.053202Z","iopub.status.idle":"2026-07-11T17:35:42.563293Z","shell.execute_reply.started":"2026-07-11T17:35:42.053167Z","shell.execute_reply":"2026-07-11T17:35:42.562504Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from pathlib import Path\n\nprint(\"=\" * 60)\nprint(\"SlowFormer Repository Structure\")\nprint(\"=\" * 60)\n\nitems = sorted(PROJECT_DIR.iterdir())\n\nfor item in items:\n    symbol = \"📁\" if item.is_dir() else \"📄\"\n    print(f\"{symbol} {item.name}\")\n\nprint(\"\\nTotal Items:\", len(items))\nprint(\"=\" * 60)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:35:42.564442Z","iopub.execute_input":"2026-07-11T17:35:42.565249Z","iopub.status.idle":"2026-07-11T17:35:42.571149Z","shell.execute_reply.started":"2026-07-11T17:35:42.565218Z","shell.execute_reply":"2026-07-11T17:35:42.570207Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from pathlib import Path\n\nfor folder in [\"AdaptiveTokenSampling\", \"ada_vit\", \"avit\"]:\n    path = PROJECT_DIR / folder\n\n    print(\"\\n\" + \"=\"*60)\n    print(folder)\n    print(\"=\"*60)\n\n    if not path.exists():\n        print(\"Folder not found.\")\n        continue\n\n    for item in sorted(path.iterdir()):\n        symbol = \"📁\" if item.is_dir() else \"📄\"\n        print(f\"{symbol} {item.name}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:35:42.57334Z","iopub.execute_input":"2026-07-11T17:35:42.573651Z","iopub.status.idle":"2026-07-11T17:35:42.585465Z","shell.execute_reply.started":"2026-07-11T17:35:42.573628Z","shell.execute_reply":"2026-07-11T17:35:42.584846Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from pathlib import Path\n\nTOOLS_DIR = PROJECT_DIR / \"AdaptiveTokenSampling\" / \"tools\"\n\nprint(\"=\" * 60)\nprint(\"AdaptiveTokenSampling/tools\")\nprint(\"=\" * 60)\n\nfor item in sorted(TOOLS_DIR.iterdir()):\n    symbol = \"📁\" if item.is_dir() else \"📄\"\n    print(f\"{symbol} {item.name}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:35:42.5863Z","iopub.execute_input":"2026-07-11T17:35:42.586538Z","iopub.status.idle":"2026-07-11T17:35:42.597376Z","shell.execute_reply.started":"2026-07-11T17:35:42.586495Z","shell.execute_reply":"2026-07-11T17:35:42.596544Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Repository Analysis\n\nThe SlowFormer repository contains three independent attack implementations:\n\n- AdaptiveTokenSampling (ATS)\n- AdaViT\n- A-ViT\n\nUnlike the official ATS repository, the ATS implementation inside SlowFormer\nis self-contained and exposes a single entry point:\n\nAdaptiveTokenSampling/tools/train.py\n\nThis notebook reproduces the ATS attack using this implementation rather than\nthe standalone ATS repository.","metadata":{}},{"cell_type":"code","source":"from pathlib import Path\n\ntrain_file = PROJECT_DIR / \"AdaptiveTokenSampling\" / \"tools\" / \"train.py\"\n\nwith open(train_file, \"r\") as f:\n    lines = f.readlines()\n\nprint(\"=\" * 70)\nprint(\"First 120 lines of train.py\")\nprint(\"=\" * 70)\n\nfor i, line in enumerate(lines[:120], start=1):\n    print(f\"{i:03d}: {line.rstrip()}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:35:42.598384Z","iopub.execute_input":"2026-07-11T17:35:42.598724Z","iopub.status.idle":"2026-07-11T17:35:42.61087Z","shell.execute_reply.started":"2026-07-11T17:35:42.598673Z","shell.execute_reply":"2026-07-11T17:35:42.610125Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 8: Inspect _init_paths.py\n# ============================================================\n\nfrom pathlib import Path\n\npath_file = PROJECT_DIR / \"AdaptiveTokenSampling\" / \"tools\" / \"_init_paths.py\"\n\nwith open(path_file, \"r\") as f:\n    print(f.read())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:35:42.611932Z","iopub.execute_input":"2026-07-11T17:35:42.612274Z","iopub.status.idle":"2026-07-11T17:35:42.622046Z","shell.execute_reply.started":"2026-07-11T17:35:42.612242Z","shell.execute_reply":"2026-07-11T17:35:42.621307Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 9: Find dependency/configuration files\n# ============================================================\n\nfrom pathlib import Path\n\nprint(\"=\" * 60)\nprint(\"Dependency Files\")\nprint(\"=\" * 60)\n\npatterns = [\n    \"requirements*.txt\",\n    \"environment*.yml\",\n    \"*.yaml\",\n    \"*.yml\",\n    \"setup.py\",\n    \"pyproject.toml\"\n]\n\nfound = []\n\nfor pattern in patterns:\n    found.extend(PROJECT_DIR.rglob(pattern))\n\nif len(found) == 0:\n    print(\"No dependency files found.\")\nelse:\n    for f in sorted(found):\n        print(f.relative_to(PROJECT_DIR))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:35:42.622949Z","iopub.execute_input":"2026-07-11T17:35:42.623247Z","iopub.status.idle":"2026-07-11T17:35:42.65179Z","shell.execute_reply.started":"2026-07-11T17:35:42.623214Z","shell.execute_reply":"2026-07-11T17:35:42.651123Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Phase 2 — Dependency Installation\n\n## Objective\n\nThe SlowFormer repository does not provide a requirements file.\n\nTherefore, the dependencies will be reconstructed by inspecting the imported modules.\n\nThe installation strategy is:\n\n1. Install only the required libraries.\n2. Verify every import before running the model.\n3. Avoid unnecessary packages to maximize reproducibility.\n\n**Checkpoint:** All imports should succeed without errors before proceeding.","metadata":{}},{"cell_type":"code","source":"# ============================================================\n# Cell 11: Install Dependencies\n# ============================================================\n\n!pip install -q \\\ntimm==0.4.12 \\\ntensorboardX \\\nfvcore \\\neinops \\\ntorchprofile \\\ngdown","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:35:42.65249Z","iopub.execute_input":"2026-07-11T17:35:42.652679Z","iopub.status.idle":"2026-07-11T17:35:46.022616Z","shell.execute_reply.started":"2026-07-11T17:35:42.652662Z","shell.execute_reply":"2026-07-11T17:35:46.021791Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 12: Verify Dependencies\n# ============================================================\n\nimport importlib\n\nmodules = [\n    \"torch\",\n    \"timm\",\n    \"tensorboardX\",\n    \"fvcore\",\n    \"einops\",\n    \"torchprofile\",\n]\n\nprint(\"=\" * 60)\nprint(\"Dependency Verification\")\nprint(\"=\" * 60)\n\nfailed = []\n\nfor module in modules:\n    try:\n        importlib.import_module(module)\n        print(f\"✓ {module}\")\n    except Exception as e:\n        failed.append(module)\n        print(f\"✗ {module}\")\n        print(\" \", e)\n\nprint(\"=\" * 60)\n\nif len(failed) == 0:\n    print(\"All dependencies imported successfully.\")\nelse:\n    print(\"Failed modules:\", failed)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:35:46.023874Z","iopub.execute_input":"2026-07-11T17:35:46.024469Z","iopub.status.idle":"2026-07-11T17:35:55.758756Z","shell.execute_reply.started":"2026-07-11T17:35:46.024436Z","shell.execute_reply":"2026-07-11T17:35:55.758027Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 13: Repository Import Setup\n# ============================================================\n\nimport os\nimport sys\nfrom pathlib import Path\n\nATS_ROOT = PROJECT_DIR / \"AdaptiveTokenSampling\"\n\n# Change into the ATS directory\nos.chdir(ATS_ROOT)\n\n# Mimic _init_paths.py\nsys.path.insert(0, str(ATS_ROOT))\nsys.path.insert(0, str(ATS_ROOT / \"lib\"))\n\nprint(\"=\" * 60)\nprint(\"Current Working Directory\")\nprint(\"=\" * 60)\nprint(os.getcwd())\n\nprint(\"\\nPython Search Paths Added:\")\nprint(sys.path[0])\nprint(sys.path[1])\n\nassert Path(sys.path[0]).exists()\nassert Path(sys.path[1]).exists()\n\nprint(\"\\nRepository paths configured successfully.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:35:55.759661Z","iopub.execute_input":"2026-07-11T17:35:55.760217Z","iopub.status.idle":"2026-07-11T17:35:55.767031Z","shell.execute_reply.started":"2026-07-11T17:35:55.76019Z","shell.execute_reply":"2026-07-11T17:35:55.766333Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install -q tensorwatch","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:35:55.768195Z","iopub.execute_input":"2026-07-11T17:35:55.768495Z","iopub.status.idle":"2026-07-11T17:35:59.22906Z","shell.execute_reply.started":"2026-07-11T17:35:55.768461Z","shell.execute_reply":"2026-07-11T17:35:59.228208Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install -q ptflops","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:35:59.233078Z","iopub.execute_input":"2026-07-11T17:35:59.233439Z","iopub.status.idle":"2026-07-11T17:36:02.578791Z","shell.execute_reply.started":"2026-07-11T17:35:59.233408Z","shell.execute_reply":"2026-07-11T17:36:02.577525Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 14: Repository Import Smoke Test\n# ============================================================\n\nimport importlib\n\nmodules = [\n    \"utils\",\n    \"datasets\",\n    \"engine\",\n    \"losses\",\n    \"vit\",\n    \"samplers\",\n]\n\nprint(\"=\" * 60)\nprint(\"Repository Module Import Test\")\nprint(\"=\" * 60)\n\nfailed = []\n\nfor module in modules:\n    try:\n        importlib.import_module(module)\n        print(f\"✓ {module}\")\n    except Exception as e:\n        failed.append(module)\n        print(f\"✗ {module}\")\n        print(f\"  {type(e).__name__}: {e}\")\n\nprint(\"=\" * 60)\n\nif not failed:\n    print(\"All repository modules imported successfully.\")\nelse:\n    print(\"Failed modules:\", failed)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:02.580324Z","iopub.execute_input":"2026-07-11T17:36:02.580794Z","iopub.status.idle":"2026-07-11T17:36:04.89292Z","shell.execute_reply.started":"2026-07-11T17:36:02.580741Z","shell.execute_reply":"2026-07-11T17:36:04.892109Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 17: Inspect DynamicVisionTransformer\n# ============================================================\n\nimport inspect\nfrom lib.models.vit_model import DynamicVisionTransformer\n\nprint(\"=\" * 80)\nprint(\"DynamicVisionTransformer Constructor\")\nprint(\"=\" * 80)\n\nprint(inspect.signature(DynamicVisionTransformer.__init__))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:04.89402Z","iopub.execute_input":"2026-07-11T17:36:04.895004Z","iopub.status.idle":"2026-07-11T17:36:04.899503Z","shell.execute_reply.started":"2026-07-11T17:36:04.894975Z","shell.execute_reply":"2026-07-11T17:36:04.898858Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 20: Load Training Arguments\n# ============================================================\n\nimport sys\nfrom pathlib import Path\n\nTOOLS_DIR = PROJECT_DIR / \"AdaptiveTokenSampling\" / \"tools\"\n\nif str(TOOLS_DIR) not in sys.path:\n    sys.path.insert(0, str(TOOLS_DIR))\n\nfrom train import get_args_parser\n\nparser = get_args_parser()\nargs = parser.parse_args([])\n\nprint(\"=\" * 80)\nprint(\"Default Training Configuration\")\nprint(\"=\" * 80)\n\nfor key, value in sorted(vars(args).items()):\n    print(f\"{key:25} : {value}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:04.90044Z","iopub.execute_input":"2026-07-11T17:36:04.900852Z","iopub.status.idle":"2026-07-11T17:36:04.924612Z","shell.execute_reply.started":"2026-07-11T17:36:04.900814Z","shell.execute_reply":"2026-07-11T17:36:04.924037Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 23: Search for checkpoint references\n# ============================================================\n\nfrom pathlib import Path\nimport re\n\npatterns = [\n    \".pth\",\n    \".pth.tar\",\n    \"drive.google\",\n    \"gdown\",\n    \"download\",\n    \"checkpoint\"\n]\n\nprint(\"=\" * 80)\nprint(\"Searching repository for checkpoint references\")\nprint(\"=\" * 80)\n\nfor py_file in PROJECT_DIR.rglob(\"*\"):\n    if py_file.suffix not in [\".py\", \".md\", \".sh\"]:\n        continue\n\n    try:\n        text = py_file.read_text(errors=\"ignore\")\n\n        for pattern in patterns:\n            if pattern in text:\n                print(f\"\\n📄 {py_file.relative_to(PROJECT_DIR)}\")\n                break\n\n    except Exception:\n        pass","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:04.925508Z","iopub.execute_input":"2026-07-11T17:36:04.925828Z","iopub.status.idle":"2026-07-11T17:36:04.956033Z","shell.execute_reply.started":"2026-07-11T17:36:04.925804Z","shell.execute_reply":"2026-07-11T17:36:04.955389Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 24: Download DeiT-Small Checkpoint\n# ============================================================\n\nfrom pathlib import Path\nimport subprocess\n\nCHECKPOINT_NAME = \"deit_small_patch16_224-cd65a155.pth\"\nCHECKPOINT_PATH = CHECKPOINT_DIR / CHECKPOINT_NAME\n\nprint(\"=\" * 70)\nprint(\"Checking for DeiT-Small checkpoint\")\nprint(\"=\" * 70)\n\nif CHECKPOINT_PATH.exists():\n    print(f\"✓ Checkpoint already exists:\\n{CHECKPOINT_PATH}\")\nelse:\n    url = \"https://dl.fbaipublicfiles.com/deit/deit_small_patch16_224-cd65a155.pth\"\n\n    print(\"Downloading official DeiT-Small checkpoint...\\n\")\n\n    result = subprocess.run(\n        [\"wget\", \"-O\", str(CHECKPOINT_PATH), url],\n        text=True\n    )\n\n    if result.returncode != 0:\n        raise RuntimeError(\"Checkpoint download failed.\")\n\nprint(\"\\nFinal checkpoint location:\")\nprint(CHECKPOINT_PATH)\n\nassert CHECKPOINT_PATH.exists(), \"Checkpoint was not downloaded.\"\n\nsize_mb = CHECKPOINT_PATH.stat().st_size / (1024 * 1024)\nprint(f\"\\nCheckpoint Size : {size_mb:.2f} MB\")\n\nprint(\"\\n Checkpoint ready.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:04.956823Z","iopub.execute_input":"2026-07-11T17:36:04.957108Z","iopub.status.idle":"2026-07-11T17:36:04.964014Z","shell.execute_reply.started":"2026-07-11T17:36:04.957068Z","shell.execute_reply":"2026-07-11T17:36:04.963398Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 25: Inspect DeiT-S Checkpoint\n# ============================================================\n\nimport torch\n\nprint(\"=\" * 70)\nprint(\"Loading checkpoint\")\nprint(\"=\" * 70)\n\ncheckpoint = torch.load(CHECKPOINT_PATH, map_location=\"cpu\")\n\nprint(\"Checkpoint type :\", type(checkpoint))\n\nprint(\"\\nTop-level keys:\")\n\nif isinstance(checkpoint, dict):\n    for key in checkpoint.keys():\n        print(\" •\", key)\nelse:\n    print(\"Checkpoint is not a dictionary.\")\n\nprint(\"\\n============================================================\")\n\nassert isinstance(checkpoint, dict), \"Unexpected checkpoint format.\"\nassert \"model\" in checkpoint, \"'model' key not found in checkpoint.\"\n\nprint(\"Checkpoint format verified.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:04.964913Z","iopub.execute_input":"2026-07-11T17:36:04.965181Z","iopub.status.idle":"2026-07-11T17:36:05.04875Z","shell.execute_reply.started":"2026-07-11T17:36:04.965146Z","shell.execute_reply":"2026-07-11T17:36:05.04792Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 26: Build ATS Model and Load DeiT Weights\n# ============================================================\n\nimport torch\n\nfrom lib.models.vit_model import DynamicVisionTransformer\nfrom vit import checkpoint_filter_fn\n\nprint(\"=\" * 80)\nprint(\"Building DynamicVisionTransformer\")\nprint(\"=\" * 80)\n\n# ------------------------------------------------------------\n# Build model exactly like train.py\n# ------------------------------------------------------------\n\nif len(args.num_tokens) == 1:\n    num_tokens = args.num_tokens * len(args.stages)\nelse:\n    num_tokens = args.num_tokens\n\nmodel = DynamicVisionTransformer(\n    patch_size=16,\n    embed_dim=384,\n    depth=12,\n    num_heads=6,\n    mlp_ratio=4,\n    qkv_bias=True,\n    integrate_attn=args.integrate_attn,\n    stages=args.stages,\n    num_tokens=num_tokens,\n)\n\nprint(\"✓ Model constructed\")\n\n# ------------------------------------------------------------\n# Load checkpoint from disk\n# ------------------------------------------------------------\n\ncheckpoint = torch.load(CHECKPOINT_PATH, map_location=\"cpu\")\n\nprint(\"✓ Checkpoint loaded\")\n\n# ------------------------------------------------------------\n# Convert DeiT weights -> ATS weights\n# ------------------------------------------------------------\n\nckpt = checkpoint_filter_fn(\n    checkpoint,\n    model,\n    args.integrate_attn,\n    args.stages,\n)\n\nprint(\"✓ Checkpoint converted\")\n\n# ------------------------------------------------------------\n# Load weights into model\n# ------------------------------------------------------------\n\nload_result = model.load_state_dict(\n    ckpt,\n    strict=False,\n)\n\nprint(\"\\n\" + \"=\" * 80)\nprint(\"Load Report\")\nprint(\"=\" * 80)\n\nprint(\"Missing Keys:\", len(load_result.missing_keys))\nprint(\"Unexpected Keys:\", len(load_result.unexpected_keys))\n\nif load_result.missing_keys:\n    print(\"\\nFirst 20 Missing Keys:\")\n    for key in load_result.missing_keys[:20]:\n        print(\"  \", key)\n\nif load_result.unexpected_keys:\n    print(\"\\nUnexpected Keys:\")\n    for key in load_result.unexpected_keys:\n        print(\"  \", key)\n\nprint(\"\\n\" + \"=\" * 80)\n\nnum_params = sum(p.numel() for p in model.parameters())\ntrainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)\n\nprint(f\"Total Parameters     : {num_params:,}\")\nprint(f\"Trainable Parameters : {trainable_params:,}\")\n\nprint(\"\\nATS model initialized successfully.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:05.049793Z","iopub.execute_input":"2026-07-11T17:36:05.050278Z","iopub.status.idle":"2026-07-11T17:36:05.461743Z","shell.execute_reply.started":"2026-07-11T17:36:05.050251Z","shell.execute_reply":"2026-07-11T17:36:05.460781Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 27: Dummy Forward Pass\n# ============================================================\n\nimport torch\n\ndevice = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n\nmodel = model.to(device)\nmodel.eval()\n\ndummy = torch.randn(1, 3, 224, 224).to(device)\n\nprint(\"=\" * 80)\nprint(\"Running Dummy Forward Pass\")\nprint(\"=\" * 80)\n\nwith torch.no_grad():\n    outputs = model(dummy)\n\nprint(\"Forward pass completed.\\n\")\n\nprint(\"Output Type:\")\nprint(type(outputs))\n\nif isinstance(outputs, (list, tuple)):\n    print(f\"\\nNumber of outputs: {len(outputs)}\")\n\n    for i, out in enumerate(outputs):\n        print(f\"\\nOutput {i}:\")\n        print(f\"Type : {type(out)}\")\n\n        if torch.is_tensor(out):\n            print(f\"Shape: {tuple(out.shape)}\")\n        else:\n            print(out)\n\nelif torch.is_tensor(outputs):\n    print(\"Tensor Shape:\", tuple(outputs.shape))\n\nelse:\n    print(outputs)\n\nprint(\"\\nDummy inference successful.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:05.462904Z","iopub.execute_input":"2026-07-11T17:36:05.463232Z","iopub.status.idle":"2026-07-11T17:36:06.187691Z","shell.execute_reply.started":"2026-07-11T17:36:05.463188Z","shell.execute_reply":"2026-07-11T17:36:06.186773Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 28: Decode ATS Forward Outputs\n# ============================================================\n\n(\n    logits,\n    retained_tokens,\n    all_tokens,\n    aux_outputs,\n    policies,\n    selection_scores,\n    attention_maps,\n) = outputs\n\nprint(\"=\" * 80)\nprint(\"ATS Forward Output Summary\")\nprint(\"=\" * 80)\n\nprint(f\"Logits Shape           : {tuple(logits.shape)}\")\nprint(f\"Retained Tokens Shape  : {tuple(retained_tokens.shape)}\")\nprint(f\"All Tokens Shape       : {tuple(all_tokens.shape)}\")\n\nprint(\"\\nPolicy Information\")\n\nfor i, policy in enumerate(policies):\n\n    if policy is None:\n        print(f\" Stage {i}: None\")\n        continue\n\n    kept = int(policy.sum().item())\n    total = policy.numel()\n\n    print(f\" Stage {i}: {kept}/{total} tokens kept ({100*kept/total:.2f}%)\")\n\nprint(\"\\nSelection Scores\")\n\nfor i, score in enumerate(selection_scores):\n\n    if score is None:\n        print(f\" Stage {i}: None\")\n        continue\n\n    print(f\" Stage {i}\")\n    print(f\"    Shape : {tuple(score.shape)}\")\n    print(f\"    Min   : {score.min().item():.6f}\")\n    print(f\"    Mean  : {score.mean().item():.6f}\")\n    print(f\"    Max   : {score.max().item():.6f}\")\n\nprint(\"\\nAttention Maps\")\n\nfor i, attn in enumerate(attention_maps):\n\n    if attn is None:\n        print(f\" Stage {i}: None\")\n        continue\n\n    print(f\" Stage {i}:\")\n    print(f\"    Number of tensors : {len(attn)}\")\n\n    for j, tensor in enumerate(attn):\n        print(f\"      Tensor {j}: {tuple(tensor.shape)}\")\n\nprint(\"\\n\" + \"=\" * 80)\nprint(\"Forward outputs decoded successfully.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:06.188616Z","iopub.execute_input":"2026-07-11T17:36:06.189162Z","iopub.status.idle":"2026-07-11T17:36:06.209289Z","shell.execute_reply.started":"2026-07-11T17:36:06.189135Z","shell.execute_reply":"2026-07-11T17:36:06.208641Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 35: Build ImageNet Synset Mapping\n# ============================================================\n\nfrom pathlib import Path\n\n# ImageNet competition root\nIMAGENET_ROOT = Path(\n    \"/kaggle/input/competitions/imagenet-object-localization-challenge\"\n)\n\nMAPPING_FILE = IMAGENET_ROOT / \"LOC_synset_mapping.txt\"\n\nprint(\"=\" * 80)\nprint(\"Reading ImageNet Synset Mapping\")\nprint(\"=\" * 80)\n\nwith open(MAPPING_FILE, \"r\") as f:\n    lines = f.readlines()\n\nprint(f\"Total classes: {len(lines)}\")\n\nsynset_to_idx = {}\nidx_to_synset = {}\n\nfor idx, line in enumerate(lines):\n    synset = line.split()[0]\n    synset_to_idx[synset] = idx\n    idx_to_synset[idx] = synset\n\nprint(\"\\nFirst 10 mappings:\\n\")\n\nfor i in range(10):\n    print(f\"{i:3d} -> {idx_to_synset[i]}\")\n\nprint(\"\\nExample reverse lookup:\")\nexample = idx_to_synset[0]\nprint(example, \"->\", synset_to_idx[example])\n\nprint(\"\\nMapping created successfully.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:06.210063Z","iopub.execute_input":"2026-07-11T17:36:06.210258Z","iopub.status.idle":"2026-07-11T17:36:06.220633Z","shell.execute_reply.started":"2026-07-11T17:36:06.210238Z","shell.execute_reply":"2026-07-11T17:36:06.219991Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ==============================\n# Project Configuration\n# ==============================\n\nfrom pathlib import Path\n\nWORK_DIR = Path(\"/kaggle/working\")\nPROJECT_DIR = WORK_DIR / \"SlowFormer\"\n\nOUTPUT_DIR = WORK_DIR / \"outputs\"\nCHECKPOINT_DIR = OUTPUT_DIR / \"checkpoints\"\n\nIMAGENET_ROOT = Path(\n    \"/kaggle/input/competitions/imagenet-object-localization-challenge\"\n)\n\nILSVRC_ROOT = IMAGENET_ROOT / \"ILSVRC\"\n\nTRAIN_ROOT = ILSVRC_ROOT / \"Data\" / \"CLS-LOC\" / \"train\"\nVAL_ROOT = ILSVRC_ROOT / \"Data\" / \"CLS-LOC\" / \"val\"\n\nDEIT_CHECKPOINT = (\n    CHECKPOINT_DIR / \"deit_small_patch16_224-cd65a155.pth\"\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:06.221528Z","iopub.execute_input":"2026-07-11T17:36:06.221844Z","iopub.status.idle":"2026-07-11T17:36:06.231521Z","shell.execute_reply.started":"2026-07-11T17:36:06.221805Z","shell.execute_reply":"2026-07-11T17:36:06.230785Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from pathlib import Path\n\ntrain_root = ILSVRC_ROOT / \"Data\" / \"CLS-LOC\" / \"train\"\n\nprint(train_root.exists())\n\nclasses = list(train_root.iterdir())\n\nprint(\"Classes:\", len(classes))\nprint(\"First class:\", classes[0])\n\nfirst_images = list(classes[0].glob(\"*.JPEG\"))\n\nprint(\"Images in first class:\", len(first_images))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:06.232397Z","iopub.execute_input":"2026-07-11T17:36:06.232658Z","iopub.status.idle":"2026-07-11T17:36:06.255564Z","shell.execute_reply.started":"2026-07-11T17:36:06.232618Z","shell.execute_reply":"2026-07-11T17:36:06.255013Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 36: Test Repository Transform\n# ============================================================\n\nimport time\nfrom datasets import build_transform\n\nprint(\"=\" * 80)\nprint(\"Building Repository Transform\")\nprint(\"=\" * 80)\n\nstart = time.time()\n\ntransform = build_transform(\n    is_train=True,\n    args=args\n)\n\nprint(f\"✓ Transform built in {time.time()-start:.2f} seconds\\n\")\nprint(transform)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:06.25644Z","iopub.execute_input":"2026-07-11T17:36:06.257204Z","iopub.status.idle":"2026-07-11T17:36:06.264002Z","shell.execute_reply.started":"2026-07-11T17:36:06.257179Z","shell.execute_reply":"2026-07-11T17:36:06.263338Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport xml.etree.ElementTree as ET\nfrom pathlib import Path\nfrom tqdm.auto import tqdm\n\nVAL_IMG = Path(\"/kaggle/input/competitions/imagenet-object-localization-challenge/ILSVRC/Data/CLS-LOC/val\")\nVAL_XML = Path(\"/kaggle/input/competitions/imagenet-object-localization-challenge/ILSVRC/Annotations/CLS-LOC/val\")\n\nOUT = Path(\"/kaggle/working/imagenet_val_5k\")\n\nOUT.mkdir(parents=True, exist_ok=True)\n\nxml_files = sorted(VAL_XML.glob(\"*.xml\"))[:5000]\n\nlinked = 0\nskipped = 0\n\nfor xml_path in tqdm(xml_files):\n\n    tree = ET.parse(xml_path)\n    root = tree.getroot()\n\n    obj = root.find(\"object\")\n\n    if obj is None:\n        skipped += 1\n        continue\n\n    cls = obj.find(\"name\").text\n\n    cls_dir = OUT / cls\n    cls_dir.mkdir(exist_ok=True)\n\n    img_name = xml_path.stem + \".JPEG\"\n\n    src = VAL_IMG / img_name\n    dst = cls_dir / img_name\n\n    if not dst.exists():\n        os.symlink(src, dst)\n\n    linked += 1\n\nprint(\"=\" * 70)\nprint(\"Subset created\")\nprint(\"=\" * 70)\nprint(\"Linked :\", linked)\nprint(\"Skipped:\", skipped)\nprint(\"Output :\", OUT)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:06.264931Z","iopub.execute_input":"2026-07-11T17:36:06.265278Z","iopub.status.idle":"2026-07-11T17:36:18.242177Z","shell.execute_reply.started":"2026-07-11T17:36:06.265243Z","shell.execute_reply":"2026-07-11T17:36:18.241269Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torchvision.datasets import ImageFolder\n\nprint(\"=\" * 70)\nprint(\"Loading ImageFolder\")\nprint(\"=\" * 70)\n\ndataset = ImageFolder(\"/kaggle/working/imagenet_val_5k\")\n\nprint(\"Images :\", len(dataset))\nprint(\"Classes:\", len(dataset.classes))\n\nimg, label = dataset[0]\n\nprint(\"\\nFirst sample\")\nprint(\"Image:\", img)\nprint(\"Label:\", label)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:18.243141Z","iopub.execute_input":"2026-07-11T17:36:18.243995Z","iopub.status.idle":"2026-07-11T17:36:18.323754Z","shell.execute_reply.started":"2026-07-11T17:36:18.243968Z","shell.execute_reply":"2026-07-11T17:36:18.323009Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 39: Apply ATS Validation Transform\n# ============================================================\n\nfrom datasets import build_transform\nfrom torchvision.datasets import ImageFolder\n\nprint(\"=\" * 70)\nprint(\"Building validation transform\")\nprint(\"=\" * 70)\n\ntransform = build_transform(\n    is_train=False,\n    args=args\n)\n\ndataset = ImageFolder(\n    \"/kaggle/working/imagenet_val_5k\",\n    transform=transform\n)\n\nimg, label = dataset[0]\n\nprint(\"Image shape :\", img.shape)\nprint(\"Image dtype :\", img.dtype)\nprint(\"Label       :\", label)\nprint(\"Min         :\", img.min().item())\nprint(\"Max         :\", img.max().item())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:18.324592Z","iopub.execute_input":"2026-07-11T17:36:18.324867Z","iopub.status.idle":"2026-07-11T17:36:18.406209Z","shell.execute_reply.started":"2026-07-11T17:36:18.324844Z","shell.execute_reply":"2026-07-11T17:36:18.405495Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 40: Validation DataLoader\n# ============================================================\n\nfrom torch.utils.data import DataLoader\n\nval_loader = DataLoader(\n    dataset,\n    batch_size=64,\n    shuffle=False,\n    num_workers=4,\n    pin_memory=True,\n)\n\nimages, labels = next(iter(val_loader))\n\nprint(\"=\" * 70)\nprint(\"Validation Batch\")\nprint(\"=\" * 70)\n\nprint(\"Images :\", images.shape)\nprint(\"Labels :\", labels.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:18.406986Z","iopub.execute_input":"2026-07-11T17:36:18.407202Z","iopub.status.idle":"2026-07-11T17:36:20.393778Z","shell.execute_reply.started":"2026-07-11T17:36:18.40718Z","shell.execute_reply":"2026-07-11T17:36:20.392801Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 41: ATS Forward Pass on Real ImageNet\n# ============================================================\n\nmodel.eval()\n\nimages = images.cuda(non_blocking=True)\nlabels = labels.cuda(non_blocking=True)\n\nwith torch.no_grad():\n    outputs = model(images)\n\nprint(\"=\" * 70)\nprint(\"Forward Pass Successful\")\nprint(\"=\" * 70)\n\nprint(\"Output type :\", type(outputs))\nprint(\"Tuple length:\", len(outputs))\n\n(\n    logits,\n    retained_tokens,\n    all_tokens,\n    aux_outputs,\n    policies,\n    selection_scores,\n    attention_maps,\n) = outputs\n\nprint(\"\\nLogits           :\", logits.shape)\nprint(\"Retained Tokens  :\", retained_tokens.shape)\nprint(\"All Tokens       :\", all_tokens.shape)\n\nprint(\"\\nPolicy Shape\")\nfor i, p in enumerate(policies):\n    if p is None:\n        print(f\" Stage {i}: None\")\n    else:\n        print(f\" Stage {i}: {tuple(p.shape)}\")\n\nprint(\"\\nSelection Scores\")\nfor i, s in enumerate(selection_scores):\n    if s is None:\n        print(f\" Stage {i}: None\")\n    else:\n        print(f\" Stage {i}: {tuple(s.shape)}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:20.395241Z","iopub.execute_input":"2026-07-11T17:36:20.395629Z","iopub.status.idle":"2026-07-11T17:36:20.561747Z","shell.execute_reply.started":"2026-07-11T17:36:20.395599Z","shell.execute_reply":"2026-07-11T17:36:20.560742Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Cell 42: Baseline ATS Statistics\n# ============================================================\n\nimport torch\n\npolicy = policies[0]\n\ntokens_kept = policy.sum(dim=1).float()\n\nprint(\"=\" * 70)\nprint(\"Baseline Token Statistics\")\nprint(\"=\" * 70)\n\nprint(f\"Average Tokens Kept : {tokens_kept.mean().item():.2f}\")\nprint(f\"Minimum             : {tokens_kept.min().item():.2f}\")\nprint(f\"Maximum             : {tokens_kept.max().item():.2f}\")\n\nprint(f\"\\nRetention Ratio : {tokens_kept.mean().item()/108:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:20.56285Z","iopub.execute_input":"2026-07-11T17:36:20.563195Z","iopub.status.idle":"2026-07-11T17:36:20.648496Z","shell.execute_reply.started":"2026-07-11T17:36:20.563169Z","shell.execute_reply":"2026-07-11T17:36:20.647853Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# SlowFormer Attack: Initialize adversarial perturbation\n# ============================================================\n\nfrom lib.models.patch import Patch\nimport torch\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n# Freeze ATS model\nmodel.eval()\nfor p in model.parameters():\n    p.requires_grad_(False)\n\n# Full-image perturbation (original SlowFormer)\nadv_patch = Patch(\n    w=224,\n    h=224,\n    is_patch=False,\n    eps=8/255,          # Original epsilon budget\n).to(device)\n\n# Optimizer (only perturbation)\noptimizer = torch.optim.Adam(\n    adv_patch.parameters(),\n    lr=1e-2\n)\n\nprint(\"=\" * 60)\nprint(\"Trainable Parameters\")\nprint(\"=\" * 60)\n\nprint(\"Model trainable:\",\n      sum(p.requires_grad for p in model.parameters()))\n\nprint(\"Patch trainable:\",\n      sum(p.requires_grad for p in adv_patch.parameters()))\n\nprint(\"\\nPerturbation shape:\",\n      tuple(adv_patch.adv_patch.shape))\n\nprint(\"Perturbation range:\",\n      float(adv_patch.adv_patch.min()),\n      float(adv_patch.adv_patch.max()))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:20.649491Z","iopub.execute_input":"2026-07-11T17:36:20.64981Z","iopub.status.idle":"2026-07-11T17:36:20.666354Z","shell.execute_reply.started":"2026-07-11T17:36:20.649775Z","shell.execute_reply":"2026-07-11T17:36:20.665465Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Single attack optimization step\n# ============================================================\n\nfrom engine import HLoss\n\nadv_loss = HLoss()\n\nimages, labels = next(iter(val_loader))\nimages = images.to(device)\nlabels = labels.to(device)\n\noptimizer.zero_grad()\n\n# Apply perturbation\nx_adv = adv_patch(images)\n\n# Forward\noutputs = model(x_adv)\n\ncls_attn = outputs[-2]\n\n# Original SlowFormer loss\nloss = 0.0\nloss_coef = [1.0, 0.2, 0.05, 0.01, 0.005, 0.005, 0.005]\n\nfor i in range(len(cls_attn)):\n    loss += loss_coef[i] * adv_loss(cls_attn[i])\n\nprint(f\"Loss before backward: {loss.item():.6f}\")\n\n# Backprop\nloss.backward()\n\nprint(\"Patch grad norm:\",\n      adv_patch.adv_patch.grad.norm().item())\n\noptimizer.step()\n\nprint(\"Optimization step completed.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:20.667571Z","iopub.execute_input":"2026-07-11T17:36:20.667879Z","iopub.status.idle":"2026-07-11T17:36:22.804204Z","shell.execute_reply.started":"2026-07-11T17:36:20.667855Z","shell.execute_reply":"2026-07-11T17:36:22.803406Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Verify optimizer updates the perturbation\n# ============================================================\n\nbefore = adv_patch.adv_patch.detach().clone()\n\noptimizer.zero_grad()\n\nx_adv = adv_patch(images)\noutputs = model(x_adv)\n\ncls_attn = outputs[-2]\n\nloss = 0.0\nloss_coef = [1.0, 0.2, 0.05, 0.01, 0.005, 0.005, 0.005]\n\nfor i in range(len(cls_attn)):\n    loss += loss_coef[i] * adv_loss(cls_attn[i])\n\nloss.backward()\noptimizer.step()\n\nafter = adv_patch.adv_patch.detach()\n\ndelta = (after - before).abs()\n\nprint(\"=\" * 60)\nprint(\"Perturbation Update Check\")\nprint(\"=\" * 60)\nprint(f\"Max update : {delta.max().item():.8f}\")\nprint(f\"Mean update: {delta.mean().item():.8f}\")\nprint(f\"Pixels changed: {(delta > 0).sum().item()} / {delta.numel()}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:22.805489Z","iopub.execute_input":"2026-07-11T17:36:22.8059Z","iopub.status.idle":"2026-07-11T17:36:23.059105Z","shell.execute_reply.started":"2026-07-11T17:36:22.805869Z","shell.execute_reply":"2026-07-11T17:36:23.058376Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# SlowFormer Attack Epoch\n# ============================================================\n\nfrom engine import HLoss\nfrom tqdm.auto import tqdm\n\nadv_loss = HLoss()\n\nloss_coef = [1.0, 0.2, 0.05, 0.01, 0.005, 0.005, 0.005]\n\nmodel.eval()\n\nrunning_loss = 0.0\n\nfor images, labels in tqdm(val_loader):\n\n    images = images.to(device)\n    labels = labels.to(device)\n\n    optimizer.zero_grad()\n\n    x_adv = adv_patch(images)\n\n    outputs = model(x_adv)\n\n    cls_attn = outputs[-2]\n\n    loss = 0.0\n\n    for i in range(len(cls_attn)):\n        loss += loss_coef[i] * adv_loss(cls_attn[i])\n\n    loss.backward()\n\n    optimizer.step()\n\n    running_loss += loss.item()\n\nprint(\"=\" * 60)\nprint(\"Attack Epoch Finished\")\nprint(\"=\" * 60)\nprint(\"Average HLoss:\", running_loss / len(val_loader))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:23.060097Z","iopub.execute_input":"2026-07-11T17:36:23.060415Z","iopub.status.idle":"2026-07-11T17:36:46.541547Z","shell.execute_reply.started":"2026-07-11T17:36:23.060379Z","shell.execute_reply":"2026-07-11T17:36:46.54063Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Evaluate optimized perturbation\n# ============================================================\n\nfrom tqdm.auto import tqdm\nimport torch\n\nmodel.eval()\n\ntop1 = 0\ntop5 = 0\ntotal = 0\n\nretained = []\nall_tokens = []\n\nwith torch.no_grad():\n\n    for images, labels in tqdm(val_loader):\n\n        images = images.to(device)\n        labels = labels.to(device)\n\n        x_adv = adv_patch(images)\n\n        outputs = model(x_adv)\n\n        logits = outputs[0]\n        kept = outputs[1]\n        total_tok = outputs[2]\n\n        retained.append(kept.float().mean().item())\n        all_tokens.append(total_tok.float().mean().item())\n\n        _, pred = logits.topk(5, dim=1)\n\n        total += labels.size(0)\n\n        top1 += (pred[:, 0] == labels).sum().item()\n\n        top5 += (pred == labels.unsqueeze(1)).any(dim=1).sum().item()\n\navg_kept = sum(retained) / len(retained)\navg_total = sum(all_tokens) / len(all_tokens)\nratio = avg_kept / avg_total\n\nprint(\"=\" * 60)\nprint(\"Attack Evaluation\")\nprint(\"=\" * 60)\n\nprint(f\"Top-1 Accuracy : {100*top1/total:.2f}%\")\nprint(f\"Top-5 Accuracy : {100*top5/total:.2f}%\")\n\nprint()\n\nprint(f\"Average Tokens Kept : {avg_kept:.2f}\")\nprint(f\"Retention Ratio     : {ratio:.4f}\")\n\nprint()\n\nbaseline = 76.41\nprint(f\"Baseline Tokens : {baseline:.2f}\")\nprint(f\"Increase        : {avg_kept-baseline:.2f}\")\nprint(f\"Percent Increase: {(avg_kept-baseline)/baseline*100:.2f}%\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:36:46.543266Z","iopub.execute_input":"2026-07-11T17:36:46.543571Z","iopub.status.idle":"2026-07-11T17:37:07.712406Z","shell.execute_reply.started":"2026-07-11T17:36:46.543528Z","shell.execute_reply":"2026-07-11T17:37:07.711297Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"images, _ = next(iter(val_loader))\nimages = images.to(device)\n\nwith torch.no_grad():\n    outputs = model(images)\n\nprint(\"=\"*80)\n\nfor i, out in enumerate(outputs):\n\n    print(f\"\\nOUTPUT {i}\")\n\n    if torch.is_tensor(out):\n        print(\"Tensor\", tuple(out.shape))\n\n    elif isinstance(out, list):\n        print(f\"List length = {len(out)}\")\n\n        for j, item in enumerate(out):\n\n            if item is None:\n                print(f\" [{j}] None\")\n\n            elif torch.is_tensor(item):\n                print(f\" [{j}] Tensor {tuple(item.shape)}\")\n\n            elif isinstance(item, list):\n                print(f\" [{j}] Nested list length = {len(item)}\")\n\n                for k, z in enumerate(item):\n                    if torch.is_tensor(z):\n                        print(f\"     [{k}] Tensor {tuple(z.shape)}\")\n                    else:\n                        print(f\"     [{k}] {type(z)}\")\n\n            else:\n                print(f\" [{j}] {type(item)}\")\n\n    else:\n        print(type(out))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:37:54.251165Z","iopub.execute_input":"2026-07-11T17:37:54.251582Z","iopub.status.idle":"2026-07-11T17:37:56.251923Z","shell.execute_reply.started":"2026-07-11T17:37:54.251543Z","shell.execute_reply":"2026-07-11T17:37:56.251047Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"=\"*80)\n\nfor i, x in enumerate(outputs):\n\n    print(f\"\\nOUTPUT {i}\")\n\n    if torch.is_tensor(x):\n        print(type(x))\n        print(\"shape:\", tuple(x.shape))\n\n    elif isinstance(x, list):\n\n        print(\"LIST\")\n        print(\"length:\", len(x))\n\n        for j, y in enumerate(x):\n\n            print(f\" [{j}] ->\", type(y))\n\n            if y is None:\n                print(\"      None\")\n                continue\n\n            if torch.is_tensor(y):\n                print(\"      shape:\", tuple(y.shape))\n                print(\"      mean :\", y.float().mean().item())\n\n    else:\n        print(type(x))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:38:01.864127Z","iopub.execute_input":"2026-07-11T17:38:01.864946Z","iopub.status.idle":"2026-07-11T17:38:01.87289Z","shell.execute_reply.started":"2026-07-11T17:38:01.864907Z","shell.execute_reply":"2026-07-11T17:38:01.872237Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Correct ATS token statistics\n# ============================================================\n\nfrom tqdm.auto import tqdm\n\nmodel.eval()\n\ntop1 = 0\ntop5 = 0\ntotal = 0\n\nkept_tokens = []\n\nwith torch.no_grad():\n\n    for images, labels in tqdm(val_loader):\n\n        images = images.to(device)\n        labels = labels.to(device)\n\n        outputs = model(adv_patch(images))\n\n        logits = outputs[0]\n\n        policy = outputs[4][0]          # (B,108,1)\n\n        kept = policy.squeeze(-1).sum(dim=1)\n\n        kept_tokens.extend(kept.cpu().tolist())\n\n        _, pred = logits.topk(5, dim=1)\n\n        total += labels.size(0)\n\n        top1 += (pred[:,0] == labels).sum().item()\n        top5 += (pred == labels.unsqueeze(1)).any(dim=1).sum().item()\n\navg_kept = sum(kept_tokens) / len(kept_tokens)\n\nprint(\"=\"*60)\nprint(\"Correct Evaluation\")\nprint(\"=\"*60)\n\nprint(f\"Top1 : {100*top1/total:.2f}%\")\nprint(f\"Top5 : {100*top5/total:.2f}%\")\nprint()\nprint(f\"Average Tokens Kept : {avg_kept:.2f}\")\nprint(f\"Retention Ratio     : {avg_kept/108:.4f}\")\nprint()\nprint(f\"Baseline            : 76.41\")\nprint(f\"Increase            : {avg_kept-76.41:.2f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:38:04.483923Z","iopub.execute_input":"2026-07-11T17:38:04.484713Z","iopub.status.idle":"2026-07-11T17:38:25.952188Z","shell.execute_reply.started":"2026-07-11T17:38:04.484668Z","shell.execute_reply":"2026-07-11T17:38:25.951048Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Inject selection_score into TokenSampling.forward()\n# ============================================================\n\nfrom pathlib import Path\n\npath = Path(\"/kaggle/working/SlowFormer/AdaptiveTokenSampling/lib/models/TokenSampler.py\")\n\ntext = path.read_text()\n\nold = \"\"\"            selection_score = selection_score / selection_score.sum(\n                dim=1, keepdim=True\n            )  # [B x T-1]\"\"\"\n\nnew = \"\"\"            selection_score = selection_score / selection_score.sum(\n                dim=1, keepdim=True\n            )  # [B x T-1]\n\n            self.selection_score = selection_score\"\"\"\n\nif \"self.selection_score = selection_score\" not in text:\n    text = text.replace(old, new)\n    path.write_text(text)\n    print(\"Patched.\")\nelse:\n    print(\"Already patched.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:38:42.619234Z","iopub.execute_input":"2026-07-11T17:38:42.61958Z","iopub.status.idle":"2026-07-11T17:38:42.627897Z","shell.execute_reply.started":"2026-07-11T17:38:42.619539Z","shell.execute_reply":"2026-07-11T17:38:42.627203Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import importlib\nimport lib.models.TokenSampler\n\nimportlib.reload(lib.models.TokenSampler)\n\nprint(\"Reloaded.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:38:43.050504Z","iopub.execute_input":"2026-07-11T17:38:43.051399Z","iopub.status.idle":"2026-07-11T17:38:43.061777Z","shell.execute_reply.started":"2026-07-11T17:38:43.051364Z","shell.execute_reply":"2026-07-11T17:38:43.060965Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from pathlib import Path\n\npath = \"/kaggle/working/SlowFormer/AdaptiveTokenSampling/lib/models/TokenSampler.py\"\n\nwith open(path, \"r\") as f:\n    txt = f.read()\n\ntxt = txt.replace(\n    \"self.selection_score = selection_score\",\n    \"\"\"self.selection_score = selection_score\n            print(\"DEBUG:\",\n                  selection_score.shape,\n                  selection_score.mean().item(),\n                  selection_score.sum(dim=1).mean().item())\"\"\"\n)\n\nwith open(path, \"w\") as f:\n    f.write(txt)\n\nprint(\"Debug print inserted.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:38:43.238872Z","iopub.execute_input":"2026-07-11T17:38:43.23929Z","iopub.status.idle":"2026-07-11T17:38:43.246469Z","shell.execute_reply.started":"2026-07-11T17:38:43.23926Z","shell.execute_reply":"2026-07-11T17:38:43.245787Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Monkey-patch the live TokenSampling object\n# ============================================================\n\nimport types\n\nattn = model.blocks[3].attn\n\nold_forward = attn.forward\n\ndef debug_forward(self, x, n, raw_x, policy):\n    print(\">>> LIVE TOKENSAMPLING FORWARD <<<\")\n    out = old_forward(x, n, raw_x, policy)\n    print(\">>> FORWARD FINISHED <<<\")\n    return out\n\nattn.forward = types.MethodType(debug_forward, attn)\n\nprint(\"Monkey patch installed.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:38:43.426644Z","iopub.execute_input":"2026-07-11T17:38:43.427147Z","iopub.status.idle":"2026-07-11T17:38:43.433445Z","shell.execute_reply.started":"2026-07-11T17:38:43.427118Z","shell.execute_reply":"2026-07-11T17:38:43.432684Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"images, _ = next(iter(val_loader))\nimages = images.to(device)\n\nwith torch.no_grad():\n    _ = model(images)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:38:43.595587Z","iopub.execute_input":"2026-07-11T17:38:43.596048Z","iopub.status.idle":"2026-07-11T17:38:45.365027Z","shell.execute_reply.started":"2026-07-11T17:38:43.596016Z","shell.execute_reply":"2026-07-11T17:38:45.364099Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from pathlib import Path\n\npath = Path(\"/kaggle/working/SlowFormer/AdaptiveTokenSampling/lib/models/TokenSampler.py\")\n\ntext = path.read_text()\n\nold = \"return x, selected_x, None, policy, cls_attn, [q,k]\"\nnew = \"return x, selected_x, None, policy, cls_attn, [q, k, selection_score]\"\n\ntext = text.replace(old, new)\n\npath.write_text(text)\n\nprint(\"Patched return.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:38:47.862884Z","iopub.execute_input":"2026-07-11T17:38:47.863728Z","iopub.status.idle":"2026-07-11T17:38:47.869993Z","shell.execute_reply.started":"2026-07-11T17:38:47.863675Z","shell.execute_reply":"2026-07-11T17:38:47.869179Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Show current environment\n# ============================================================\n\nimport os\nimport sys\n\nprint(\"CWD:\")\nprint(os.getcwd())\n\nprint(\"\\nPython path:\")\nfor p in sys.path[:10]:\n    print(\" \", p)\n\nprint(\"\\nModel class:\")\nprint(type(model))\n\nprint(\"\\nBlock 3:\")\nprint(type(model.blocks[3]))\nprint(type(model.blocks[3].attn))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:38:49.655586Z","iopub.execute_input":"2026-07-11T17:38:49.656313Z","iopub.status.idle":"2026-07-11T17:38:49.662835Z","shell.execute_reply.started":"2026-07-11T17:38:49.656282Z","shell.execute_reply":"2026-07-11T17:38:49.662037Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import inspect\n\nprint(inspect.getfile(model.blocks[3].attn.__class__))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:39:45.495542Z","iopub.execute_input":"2026-07-11T17:39:45.49625Z","iopub.status.idle":"2026-07-11T17:39:45.50092Z","shell.execute_reply.started":"2026-07-11T17:39:45.496221Z","shell.execute_reply":"2026-07-11T17:39:45.500027Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from pathlib import Path\n\np = Path(\"/kaggle/working/SlowFormer/AdaptiveTokenSampling/lib/models/TokenSampler.py\")\n\nprint(p.resolve())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:39:51.090368Z","iopub.execute_input":"2026-07-11T17:39:51.090862Z","iopub.status.idle":"2026-07-11T17:39:51.096518Z","shell.execute_reply.started":"2026-07-11T17:39:51.090831Z","shell.execute_reply":"2026-07-11T17:39:51.095575Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import inspect\n\nsrc = inspect.getsource(model.blocks[3].attn.forward)\n\nprint(src[-500:])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:39:57.670441Z","iopub.execute_input":"2026-07-11T17:39:57.671226Z","iopub.status.idle":"2026-07-11T17:39:57.676535Z","shell.execute_reply.started":"2026-07-11T17:39:57.671193Z","shell.execute_reply":"2026-07-11T17:39:57.675901Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"images, _ = next(iter(val_loader))\nimages = images.to(device)\n\nwith torch.no_grad():\n    outputs = model(images)\n\nprint(type(outputs[6]))\nprint(len(outputs[6]))\n\nprint(type(outputs[6][0]))\nprint(len(outputs[6][0]))\n\nfor i, t in enumerate(outputs[6][0]):\n    print(f\"\\nTensor {i}\")\n    print(type(t))\n    if torch.is_tensor(t):\n        print(t.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:40:55.264175Z","iopub.execute_input":"2026-07-11T17:40:55.264579Z","iopub.status.idle":"2026-07-11T17:40:57.206564Z","shell.execute_reply.started":"2026-07-11T17:40:55.264548Z","shell.execute_reply":"2026-07-11T17:40:57.205757Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import types\nimport torch\n\ndef debug_forward(self, x, n, raw_x, policy):\n\n    B, N, C = x.shape\n    if isinstance(N, torch.Tensor):\n        N = N.item()\n\n    if n <= 1.0:\n        n = max(round(n * N), 8)\n\n    qkv = (\n        self.qkv(x)\n        .reshape(B, N, 3, self.num_heads, C // self.num_heads)\n        .permute(2, 0, 3, 1, 4)\n    )\n\n    qkv = qkv * policy.unsqueeze(0).unsqueeze(2)\n    q, k, v = qkv\n\n    attn = self.softmax_with_policy(\n        (q @ k.transpose(-2, -1)) * self.scale,\n        policy,\n    )\n\n    cls_attn = attn[:, :, 0]\n\n    v_norm = torch.linalg.norm(\n        v.transpose(1, 2).reshape(B, attn.shape[2], C),\n        ord=2,\n        dim=2,\n    )\n\n    selection_score = cls_attn.sum(dim=1)\n    selection_score *= v_norm\n    selection_score = selection_score[:, 1:]\n    selection_score /= selection_score.sum(dim=1, keepdim=True)\n\n    self.selection_score = selection_score\n\n    return old_forward(x, n, raw_x, policy)\n\nmodel.blocks[3].attn.forward = types.MethodType(\n    debug_forward,\n    model.blocks[3].attn,\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:41:36.224507Z","iopub.execute_input":"2026-07-11T17:41:36.224964Z","iopub.status.idle":"2026-07-11T17:41:36.233248Z","shell.execute_reply.started":"2026-07-11T17:41:36.224933Z","shell.execute_reply":"2026-07-11T17:41:36.232511Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"_ = model(images)\n\nprint(model.blocks[3].attn.selection_score.shape)\nprint(model.blocks[3].attn.selection_score.sum(dim=1).mean())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:41:44.163045Z","iopub.execute_input":"2026-07-11T17:41:44.163486Z","iopub.status.idle":"2026-07-11T17:41:44.381829Z","shell.execute_reply.started":"2026-07-11T17:41:44.163442Z","shell.execute_reply":"2026-07-11T17:41:44.381151Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Loss on ATS selection distribution\n# ============================================================\n\nimport torch\nimport torch.nn as nn\n\nclass SelectionScoreLoss(nn.Module):\n    def __init__(self):\n        super().__init__()\n\n    def forward(self, score):\n        # score: [B, 196]\n\n        target = torch.full_like(score, 1.0 / score.shape[1])\n\n        loss = ((score - target) ** 2).sum(dim=1).mean()\n\n        return loss\n\nselection_loss = SelectionScoreLoss()\n\nprint(selection_loss)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:42:02.838484Z","iopub.execute_input":"2026-07-11T17:42:02.83893Z","iopub.status.idle":"2026-07-11T17:42:02.845382Z","shell.execute_reply.started":"2026-07-11T17:42:02.838901Z","shell.execute_reply":"2026-07-11T17:42:02.84455Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"optimizer.zero_grad()\n\nx_adv = adv_patch(images)\n\n_ = model(x_adv)\n\nscore = model.blocks[3].attn.selection_score\n\nloss = selection_loss(score)\n\nprint(\"Loss:\", loss.item())\n\nloss.backward()\n\noptimizer.step()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:42:16.404329Z","iopub.execute_input":"2026-07-11T17:42:16.40493Z","iopub.status.idle":"2026-07-11T17:42:16.720093Z","shell.execute_reply.started":"2026-07-11T17:42:16.404899Z","shell.execute_reply":"2026-07-11T17:42:16.719321Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Verify SelectionScoreLoss backpropagates\n# ============================================================\n\nimages, labels = next(iter(val_loader))\nimages = images.to(device)\n\noptimizer.zero_grad()\n\nx_adv = adv_patch(images)\n\n_ = model(x_adv)\n\nscore = model.blocks[3].attn.selection_score\n\nloss = selection_loss(score)\n\nprint(f\"Selection Loss : {loss.item():.8f}\")\n\nloss.backward()\n\ngrad_norm = adv_patch.adv_patch.grad.norm().item()\n\nprint(f\"Patch Grad Norm : {grad_norm:.8e}\")\n\noptimizer.step()\n\nprint(\"Step completed.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:42:39.075453Z","iopub.execute_input":"2026-07-11T17:42:39.076302Z","iopub.status.idle":"2026-07-11T17:42:41.390424Z","shell.execute_reply.started":"2026-07-11T17:42:39.076271Z","shell.execute_reply":"2026-07-11T17:42:41.389565Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Attack Epoch (SelectionScoreLoss)\n# ============================================================\n\nfrom tqdm.auto import tqdm\n\nmodel.eval()\n\nrunning_loss = 0.0\n\nfor images, labels in tqdm(val_loader):\n\n    images = images.to(device)\n\n    optimizer.zero_grad()\n\n    x_adv = adv_patch(images)\n\n    _ = model(x_adv)\n\n    score = model.blocks[3].attn.selection_score\n\n    loss = selection_loss(score)\n\n    loss.backward()\n\n    optimizer.step()\n\n    running_loss += loss.item()\n\nprint(\"=\" * 60)\nprint(\"SelectionScore Attack Finished\")\nprint(\"=\" * 60)\nprint(\"Average Loss:\", running_loss / len(val_loader))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:43:19.112254Z","iopub.execute_input":"2026-07-11T17:43:19.11277Z","iopub.status.idle":"2026-07-11T17:43:44.675892Z","shell.execute_reply.started":"2026-07-11T17:43:19.112686Z","shell.execute_reply":"2026-07-11T17:43:44.674675Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tqdm.auto import tqdm\nimport traceback\n\nmodel.eval()\n\nrunning_loss = 0.0\n\ntry:\n    for batch_idx, (images, labels) in enumerate(tqdm(val_loader)):\n\n        images = images.to(device)\n\n        optimizer.zero_grad()\n\n        x_adv = adv_patch(images)\n\n        _ = model(x_adv)\n\n        score = model.blocks[3].attn.selection_score\n\n        loss = selection_loss(score)\n\n        loss.backward()\n\n        optimizer.step()\n\n        running_loss += loss.item()\n\nexcept Exception as e:\n    print(f\"\\nFAILED AT BATCH {batch_idx}\")\n    traceback.print_exc()\n    raise","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:44:15.592851Z","iopub.execute_input":"2026-07-11T17:44:15.593295Z","iopub.status.idle":"2026-07-11T17:44:40.576322Z","shell.execute_reply.started":"2026-07-11T17:44:15.593251Z","shell.execute_reply":"2026-07-11T17:44:40.575297Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Evaluate SelectionScore Attack\n# ============================================================\n\nfrom tqdm.auto import tqdm\n\nmodel.eval()\n\ntop1 = 0\ntop5 = 0\ntotal = 0\n\nkept_tokens = []\n\nwith torch.no_grad():\n\n    for images, labels in tqdm(val_loader):\n\n        images = images.to(device)\n        labels = labels.to(device)\n\n        outputs = model(adv_patch(images))\n\n        logits = outputs[0]\n        policy = outputs[4][0]          # (B,108,1)\n\n        kept = policy.squeeze(-1).sum(dim=1)\n\n        kept_tokens.extend(kept.cpu().tolist())\n\n        _, pred = logits.topk(5, dim=1)\n\n        total += labels.size(0)\n\n        top1 += (pred[:, 0] == labels).sum().item()\n        top5 += (pred == labels.unsqueeze(1)).any(dim=1).sum().item()\n\navg_kept = sum(kept_tokens) / len(kept_tokens)\n\nprint(\"=\" * 60)\nprint(\"SelectionScore Attack Evaluation\")\nprint(\"=\" * 60)\n\nprint(f\"Top-1 Accuracy      : {100*top1/total:.2f}%\")\nprint(f\"Top-5 Accuracy      : {100*top5/total:.2f}%\")\nprint(f\"Average Tokens Kept : {avg_kept:.2f}\")\nprint(f\"Retention Ratio     : {avg_kept/108:.4f}\")\n\nprint()\nprint(f\"Baseline Tokens     : 76.41\")\nprint(f\"Token Change        : {avg_kept-76.41:.2f}\")\nprint(f\"Percent Change      : {(avg_kept-76.41)/76.41*100:.2f}%\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:44:43.749474Z","iopub.execute_input":"2026-07-11T17:44:43.750067Z","iopub.status.idle":"2026-07-11T17:45:05.853011Z","shell.execute_reply.started":"2026-07-11T17:44:43.75002Z","shell.execute_reply":"2026-07-11T17:45:05.852137Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Inspect inverse_transform_sampling()\n# ============================================================\n\nimport inspect\n\nprint(\"=\" * 100)\nprint(\"inverse_transform_sampling\")\nprint(\"=\" * 100)\n\nprint(inspect.getsource(model.blocks[3].attn.inverse_transform_sampling))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:47:13.006407Z","iopub.execute_input":"2026-07-11T17:47:13.006952Z","iopub.status.idle":"2026-07-11T17:47:13.014579Z","shell.execute_reply.started":"2026-07-11T17:47:13.006906Z","shell.execute_reply":"2026-07-11T17:47:13.013785Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# Inject duplicate statistics into inverse_transform_sampling()\n# ============================================================\n\nfrom pathlib import Path\n\npath = Path(\"/kaggle/working/SlowFormer/AdaptiveTokenSampling/lib/models/TokenSampler.py\")\n\ntext = path.read_text()\n\nold = \"\"\"        unique_indices = self.get_unique_indices(\n            indices=tokens_to_pick_ind, max_value=N - 1\n        )[:, : N - 1]\n\n        # Prune the attention matrix and input tokens.\n\"\"\"\n\nnew = \"\"\"        unique_indices = self.get_unique_indices(\n            indices=tokens_to_pick_ind, max_value=N - 1\n        )[:, : N - 1]\n\n        # ============================================================\n        # DEBUG: Duplicate statistics\n        # ============================================================\n        requested = tokens_to_pick_ind.shape[1]\n\n        unique_per_sample = torch.stack([\n            torch.unique(tokens_to_pick_ind[b]).numel()\n            for b in range(tokens_to_pick_ind.shape[0])\n        ])\n\n        duplicates = requested - unique_per_sample\n\n        print(\"=\" * 60)\n        print(\"Inverse Transform Sampling Debug\")\n        print(\"=\" * 60)\n        print(f\"Requested samples        : {requested}\")\n        print(f\"Average unique samples   : {unique_per_sample.float().mean().item():.2f}\")\n        print(f\"Average duplicate samples: {duplicates.float().mean().item():.2f}\")\n        print(f\"Max duplicates           : {duplicates.max().item()}\")\n        print(f\"Min duplicates           : {duplicates.min().item()}\")\n\n        # Prune the attention matrix and input tokens.\n\"\"\"\n\nif \"Average duplicate samples\" not in text:\n    text = text.replace(old, new)\n    path.write_text(text)\n    print(\"Duplicate statistics inserted.\")\nelse:\n    print(\"Duplicate statistics already present.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:52:02.880732Z","iopub.execute_input":"2026-07-11T17:52:02.881175Z","iopub.status.idle":"2026-07-11T17:52:02.88851Z","shell.execute_reply.started":"2026-07-11T17:52:02.881145Z","shell.execute_reply":"2026-07-11T17:52:02.88793Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"images, _ = next(iter(val_loader))\nimages = images.to(device)\n\nwith torch.no_grad():\n    _ = model(images)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:52:12.911758Z","iopub.execute_input":"2026-07-11T17:52:12.91203Z","iopub.status.idle":"2026-07-11T17:52:14.971646Z","shell.execute_reply.started":"2026-07-11T17:52:12.912005Z","shell.execute_reply":"2026-07-11T17:52:14.970556Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import inspect\n\nprint(inspect.getsource(model.blocks[3].attn.inverse_transform_sampling))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T17:54:36.161074Z","iopub.execute_input":"2026-07-11T17:54:36.161673Z","iopub.status.idle":"2026-07-11T17:54:36.169127Z","shell.execute_reply.started":"2026-07-11T17:54:36.161635Z","shell.execute_reply":"2026-07-11T17:54:36.168226Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"baseline_tokens = 76.41\nbaseline_tokens = 76.41  # Baseline ATS result\nprint(\"=\" * 70)\nprint(\"SlowFormer Attack Results\")\nprint(\"=\" * 70)\n\nprint(f\"{'Metric':<30}{'Value'}\")\nprint(\"-\" * 70)\n\nprint(f\"{'Top-1 Accuracy':<30}{100*top1/total:.2f}%\")\nprint(f\"{'Top-5 Accuracy':<30}{100*top5/total:.2f}%\")\nprint(f\"{'Average Tokens Kept':<30}{avg_kept:.2f}\")\nprint(f\"{'Retention Ratio':<30}{avg_kept/108:.4f}\")\nprint(f\"{'Token Change':<30}{avg_kept-baseline_tokens:+.2f}\")\nprint(f\"{'Percentage Change':<30}{(avg_kept-baseline_tokens)/baseline_tokens*100:+.2f}%\")\n\nprint(\"=\" * 70)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T18:01:16.197915Z","iopub.execute_input":"2026-07-11T18:01:16.198676Z","iopub.status.idle":"2026-07-11T18:01:16.205052Z","shell.execute_reply.started":"2026-07-11T18:01:16.198644Z","shell.execute_reply":"2026-07-11T18:01:16.204301Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from fvcore.nn import FlopCountAnalysis\n\nmodel.eval()\n\nimages, _ = next(iter(val_loader))\nimages = images[:1].to(device)\n\nwith torch.no_grad():\n    flops = FlopCountAnalysis(model, adv_patch(images))\n\nprint(\"=\" * 60)\nprint(f\"GFLOPs: {flops.total() / 1e9:.3f}\")\nprint(\"=\" * 60)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T18:03:18.933461Z","iopub.execute_input":"2026-07-11T18:03:18.934195Z","iopub.status.idle":"2026-07-11T18:03:21.330861Z","shell.execute_reply.started":"2026-07-11T18:03:18.934164Z","shell.execute_reply":"2026-07-11T18:03:21.32944Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"baseline_gflops = flops.total() / 1e9","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T18:03:33.073473Z","iopub.execute_input":"2026-07-11T18:03:33.073936Z","iopub.status.idle":"2026-07-11T18:03:33.078749Z","shell.execute_reply.started":"2026-07-11T18:03:33.0739Z","shell.execute_reply":"2026-07-11T18:03:33.077968Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"attack_gflops = flops.total() / 1e9","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T18:03:39.596925Z","iopub.execute_input":"2026-07-11T18:03:39.597441Z","iopub.status.idle":"2026-07-11T18:03:39.602464Z","shell.execute_reply.started":"2026-07-11T18:03:39.597412Z","shell.execute_reply":"2026-07-11T18:03:39.60177Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"=\" * 60)\nprint(\"GFLOPs Comparison\")\nprint(\"=\" * 60)\nprint(f\"Baseline GFLOPs : {baseline_gflops:.3f}\")\nprint(f\"Attack GFLOPs   : {attack_gflops:.3f}\")\nprint(f\"Change          : {attack_gflops - baseline_gflops:+.3f}\")\nprint(f\"Percent Change  : {(attack_gflops - baseline_gflops) / baseline_gflops * 100:+.2f}%\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T18:03:45.496445Z","iopub.execute_input":"2026-07-11T18:03:45.497239Z","iopub.status.idle":"2026-07-11T18:03:45.502384Z","shell.execute_reply.started":"2026-07-11T18:03:45.497209Z","shell.execute_reply":"2026-07-11T18:03:45.501561Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nmethods = [\"Baseline\", \"HLoss\", \"SelectionScore\"]\ntokens = [76.41, 72.57, 72.04]\n\nplt.figure(figsize=(6,4))\nbars = plt.bar(methods, tokens)\n\nplt.ylabel(\"Average Tokens Retained\")\nplt.title(\"Average Tokens Retained per Image\")\n\nfor b in bars:\n    plt.text(\n        b.get_x()+b.get_width()/2,\n        b.get_height()+0.2,\n        f\"{b.get_height():.2f}\",\n        ha=\"center\"\n    )\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T18:05:46.835324Z","iopub.execute_input":"2026-07-11T18:05:46.836059Z","iopub.status.idle":"2026-07-11T18:06:27.079678Z","shell.execute_reply.started":"2026-07-11T18:05:46.836029Z","shell.execute_reply":"2026-07-11T18:06:27.078913Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nmethods = [\"HLoss\", \"SelectionScore\"]\ntop1 = [54.40, 52.80]\n\nplt.figure(figsize=(6,4))\nbars = plt.bar(methods, top1)\n\nplt.ylabel(\"Top-1 Accuracy (%)\")\nplt.title(\"Classification Accuracy\")\n\nfor b in bars:\n    plt.text(\n        b.get_x()+b.get_width()/2,\n        b.get_height()+0.3,\n        f\"{b.get_height():.2f}%\",\n        ha=\"center\"\n    )\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T18:06:49.306953Z","iopub.execute_input":"2026-07-11T18:06:49.307809Z","iopub.status.idle":"2026-07-11T18:06:49.425956Z","shell.execute_reply.started":"2026-07-11T18:06:49.307778Z","shell.execute_reply":"2026-07-11T18:06:49.425134Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nmethods = [\"Baseline\", \"HLoss\", \"SelectionScore\"]\nratio = [0.7075, 0.6719, 0.6670]\n\nplt.figure(figsize=(6,4))\nbars = plt.bar(methods, ratio)\n\nplt.ylabel(\"Retention Ratio\")\nplt.title(\"Fraction of Tokens Retained\")\n\nfor b in bars:\n    plt.text(\n        b.get_x()+b.get_width()/2,\n        b.get_height()+0.005,\n        f\"{b.get_height():.4f}\",\n        ha=\"center\"\n    )\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-11T18:06:55.682347Z","iopub.execute_input":"2026-07-11T18:06:55.682876Z","iopub.status.idle":"2026-07-11T18:06:55.815879Z","shell.execute_reply.started":"2026-07-11T18:06:55.682847Z","shell.execute_reply":"2026-07-11T18:06:55.815142Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}