{"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":"gpu","dataSources":[{"sourceId":14774,"databundleVersionId":875431,"sourceType":"competition"}],"dockerImageVersionId":31260,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install -q timm\n\nimport os\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nimport timm\n\nfrom PIL import Image\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"CSV_PATH = \"/kaggle/input/aptos2019-blindness-detection/train.csv\"\nIMG_DIR  = \"/kaggle/input/aptos2019-blindness-detection/train_images\"\n\ndf = pd.read_csv(CSV_PATH)\nprint(df[\"diagnosis\"].value_counts())\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df, temp_df = train_test_split(\n    df,\n    test_size=0.30,\n    stratify=df[\"diagnosis\"],\n    random_state=42\n)\n\nval_df, test_df = train_test_split(\n    temp_df,\n    test_size=0.50,\n    stratify=temp_df[\"diagnosis\"],\n    random_state=42\n)\n\nprint(\"Train:\", len(train_df))\nprint(\"Val  :\", len(val_df))\nprint(\"Test :\", len(test_df))\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_tfms = transforms.Compose([\n    transforms.Resize((224,224)),\n    transforms.RandomHorizontalFlip(),\n    transforms.RandomRotation(20),\n    transforms.ToTensor()\n])\n\ntest_tfms = transforms.Compose([\n    transforms.Resize((224,224)),\n    transforms.ToTensor()\n])\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class APTOSDataset(Dataset):\n    def __init__(self, df, img_dir, tfms):\n        self.df = df.reset_index(drop=True)\n        self.img_dir = img_dir\n        self.tfms = tfms\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        img_id = self.df.loc[idx, \"id_code\"]\n        label  = self.df.loc[idx, \"diagnosis\"]\n\n        img = Image.open(\n            os.path.join(self.img_dir, img_id + \".png\")\n        ).convert(\"RGB\")\n\n        img = self.tfms(img)\n        return img, label\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_loader = DataLoader(\n    APTOSDataset(train_df, IMG_DIR, train_tfms),\n    batch_size=16,\n    shuffle=True\n)\n\nval_loader = DataLoader(\n    APTOSDataset(val_df, IMG_DIR, test_tfms),\n    batch_size=16\n)\n\ntest_loader = DataLoader(\n    APTOSDataset(test_df, IMG_DIR, test_tfms),\n    batch_size=16\n)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class DRModel(nn.Module):\n    def __init__(self, num_classes=5):\n        super().__init__()\n        self.backbone = timm.create_model(\n            \"efficientnetv2_rw_s\",\n            pretrained=True,\n            num_classes=0\n        )\n        self.fc = nn.Linear(self.backbone.num_features, num_classes)\n\n    def forward(self, x):\n        x = self.backbone(x)\n        return self.fc(x)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train_model(model, train_loader, val_loader, epochs=15):\n    device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n    model.to(device)\n\n    optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4)\n    criterion = nn.CrossEntropyLoss()\n\n    for epoch in range(epochs):\n        # -------- TRAIN --------\n        model.train()\n        train_loss = 0\n\n        for imgs, labels in train_loader:\n            imgs, labels = imgs.to(device), labels.to(device)\n\n            optimizer.zero_grad()\n            outputs = model(imgs)\n            loss = criterion(outputs, labels)\n            loss.backward()\n            optimizer.step()\n\n            train_loss += loss.item()\n\n        train_loss /= len(train_loader)\n\n        # -------- VALIDATION --------\n        model.eval()\n        y_true, y_pred = [], []\n\n        with torch.no_grad():\n            for imgs, labels in val_loader:\n                imgs = imgs.to(device)\n                outputs = model(imgs)\n                preds = outputs.argmax(1).cpu().numpy()\n\n                y_pred.extend(preds)\n                y_true.extend(labels.numpy())\n\n        val_acc = accuracy_score(y_true, y_pred)\n\n        print(\n            f\"Epoch [{epoch+1}/{epochs}] \"\n            f\"Train Loss: {train_loss:.4f} \"\n            f\"Val Accuracy: {val_acc:.4f}\"\n        )\n\n    return model\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = DRModel(num_classes=5)\nmodel = train_model(model, train_loader, val_loader, epochs=15)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}