{"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":10338,"databundleVersionId":862042,"isSourceIdPinned":false}],"dockerImageVersionId":31329,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\n# import os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install -q \\\nopen_clip_torch \\\npydicom \\\nscikit-learn","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-12T03:13:18.405187Z","iopub.execute_input":"2026-05-12T03:13:18.405496Z","iopub.status.idle":"2026-05-12T03:13:24.501964Z","shell.execute_reply.started":"2026-05-12T03:13:18.405463Z","shell.execute_reply":"2026-05-12T03:13:24.500879Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport torch\nimport open_clip\nimport pandas as pd\nimport pydicom\nfrom PIL import Image\nfrom tqdm import tqdm\nfrom sklearn.model_selection import train_test_split\nfrom torch.utils.data import Dataset, DataLoader","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-12T03:13:49.287372Z","iopub.execute_input":"2026-05-12T03:13:49.287950Z","iopub.status.idle":"2026-05-12T03:14:16.920920Z","shell.execute_reply.started":"2026-05-12T03:13:49.287912Z","shell.execute_reply":"2026-05-12T03:14:16.919768Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"DEVICE = \"cuda\" if torch.cuda.is_available() else \"cpu\"\nDATASET_PATH = \"/kaggle/input/competitions/rsna-pneumonia-detection-challenge\"\n\nIMAGE_DIR = os.path.join(\n    DATASET_PATH,\n    \"stage_2_train_images\"\n)\n\nCSV_PATH = os.path.join(\n    DATASET_PATH,\n    \"stage_2_train_labels.csv\"\n)\n\nMODEL_NAME = \"hf-hub:microsoft/BiomedCLIP-PubMedBERT_256-vit_base_patch16_224\"\nBATCH_SIZE = 16\nprint(\"DEVICE:\", DEVICE)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-12T03:15:29.682723Z","iopub.execute_input":"2026-05-12T03:15:29.683662Z","iopub.status.idle":"2026-05-12T03:15:29.690056Z","shell.execute_reply.started":"2026-05-12T03:15:29.683629Z","shell.execute_reply":"2026-05-12T03:15:29.688654Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.read_csv(CSV_PATH)\nprint(df.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-12T03:15:32.463324Z","iopub.execute_input":"2026-05-12T03:15:32.464160Z","iopub.status.idle":"2026-05-12T03:15:32.555283Z","shell.execute_reply.started":"2026-05-12T03:15:32.464122Z","shell.execute_reply":"2026-05-12T03:15:32.554518Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = df.groupby(\"patientId\")[\"Target\"].max().reset_index()\nprint(\"\\nGrouped Data:\")\nprint(df.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-12T03:15:36.196638Z","iopub.execute_input":"2026-05-12T03:15:36.197344Z","iopub.status.idle":"2026-05-12T03:15:36.252410Z","shell.execute_reply.started":"2026-05-12T03:15:36.197287Z","shell.execute_reply":"2026-05-12T03:15:36.251566Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_small, _ = train_test_split(\n    df,\n    train_size=0.1,\n    stratify=df[\"Target\"],\n    random_state=42\n)\nprint(\"\\nFULL DATA :\", len(df))\nprint(\"10% DATA  :\", len(df_small))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-12T03:15:44.594104Z","iopub.execute_input":"2026-05-12T03:15:44.594865Z","iopub.status.idle":"2026-05-12T03:15:44.620064Z","shell.execute_reply.started":"2026-05-12T03:15:44.594834Z","shell.execute_reply":"2026-05-12T03:15:44.619123Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model, preprocess_train, preprocess_val = open_clip.create_model_and_transforms(\n    MODEL_NAME\n)\n\ntokenizer = open_clip.get_tokenizer(\n    MODEL_NAME\n)\n\nmodel = model.to(DEVICE)\nmodel.eval()\nprint(\"\\nBiomedCLIP loaded.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-12T03:16:02.344610Z","iopub.execute_input":"2026-05-12T03:16:02.345245Z","iopub.status.idle":"2026-05-12T03:16:13.055800Z","shell.execute_reply.started":"2026-05-12T03:16:02.345207Z","shell.execute_reply":"2026-05-12T03:16:13.054798Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class RSNADataset(Dataset):\n\n    def __init__(\n        self,\n        dataframe,\n        image_dir,\n        transform=None\n    ):\n\n        self.df = dataframe\n        self.image_dir = image_dir\n        self.transform = transform\n\n    def __len__(self):\n\n        return len(self.df)\n\n    def __getitem__(self, idx):\n\n        row = self.df.iloc[idx]\n        patient_id = row[\"patientId\"]\n        label = row[\"Target\"]\n        dicom_path = os.path.join(\n            self.image_dir,\n            f\"{patient_id}.dcm\"\n        )\n\n        dicom = pydicom.dcmread(dicom_path)\n        image = dicom.pixel_array\n        image = image - image.min()\n        image = image / (image.max() + 1e-8)\n        image = (image * 255).astype(\"uint8\")\n        image = Image.fromarray(image).convert(\"RGB\")\n\n        if self.transform:\n            image = self.transform(image)\n\n        return image, label\n\n\ndataset = RSNADataset(\n    dataframe=df_small,\n    image_dir=IMAGE_DIR,\n    transform=preprocess_val\n)\n\nloader = DataLoader(\n    dataset,\n    batch_size=BATCH_SIZE,\n    shuffle=False\n)\n\nprint(\"\\nDataset ready.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-12T03:16:29.170035Z","iopub.execute_input":"2026-05-12T03:16:29.170936Z","iopub.status.idle":"2026-05-12T03:16:29.179410Z","shell.execute_reply.started":"2026-05-12T03:16:29.170897Z","shell.execute_reply":"2026-05-12T03:16:29.178679Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"labels = [\n    \"normal chest x-ray\",\n    \"pneumonia chest x-ray\"\n]\n\ntext = tokenizer(labels).to(DEVICE)\nwith torch.no_grad():\n\n    text_features = model.encode_text(text)\n\n    text_features /= text_features.norm(\n        dim=-1,\n        keepdim=True\n    )\n\nprint(\"\\nText embeddings ready.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-12T03:16:36.103115Z","iopub.execute_input":"2026-05-12T03:16:36.103666Z","iopub.status.idle":"2026-05-12T03:16:36.634037Z","shell.execute_reply.started":"2026-05-12T03:16:36.103633Z","shell.execute_reply":"2026-05-12T03:16:36.633234Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"correct = 0\ntotal = 0\n\nall_preds = []\nall_labels = []\n\nprint(\"\\nRunning zero-shot inference...\\n\")\n\nwith torch.no_grad():\n\n    for images, labels_batch in tqdm(loader):\n\n        images = images.to(DEVICE)\n        image_features = model.encode_image(images)\n        image_features /= image_features.norm(\n            dim=-1,\n            keepdim=True\n        )\n        similarity = image_features @ text_features.T\n        preds = similarity.argmax(dim=1).cpu()\n        correct += (preds == labels_batch).sum().item()\n        total += len(labels_batch)\n        all_preds.extend(preds.tolist())\n        all_labels.extend(labels_batch.tolist())\n\n\naccuracy = correct / total\nprint(\"\\nZero-shot Accuracy:\", round(accuracy, 4))\nprint(\"\\nSample Predictions:\\n\")\n\nfor i in range(10):\n\n    pred = all_preds[i]\n    true = all_labels[i]\n\n    print(\n        f\"Sample {i} | \"\n        f\"Pred: {labels[pred]} | \"\n        f\"True: {labels[true]}\"\n    )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-12T03:16:39.931837Z","iopub.execute_input":"2026-05-12T03:16:39.932477Z","iopub.status.idle":"2026-05-12T03:18:34.097757Z","shell.execute_reply.started":"2026-05-12T03:16:39.932443Z","shell.execute_reply":"2026-05-12T03:18:34.096786Z"}},"outputs":[],"execution_count":null}]}