{"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":14774,"databundleVersionId":875431}],"dockerImageVersionId":31286,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import torch\nimport numpy as np\nimport pandas as pd\nimport torch.nn as nn\nfrom PIL import Image\nimport os\nfrom pathlib import Path\nfrom torch.utils.data import Dataset\nfrom torch.utils.data import DataLoader\nfrom kaggle_secrets import UserSecretsClient\nfrom sklearn.model_selection import train_test_split\nimport os\nfrom torchvision import models\nimport shutil\nfrom sklearn.metrics import cohen_kappa_score, accuracy_score, f1_score\nfrom tqdm import tqdm\nimport pytorch_lightning as L\nfrom pytorch_lightning.callbacks import EarlyStopping, ModelCheckpoint ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-21T09:41:52.979216Z","iopub.execute_input":"2026-03-21T09:41:52.979435Z","iopub.status.idle":"2026-03-21T09:42:13.484384Z","shell.execute_reply.started":"2026-03-21T09:41:52.979415Z","shell.execute_reply":"2026-03-21T09:42:13.483530Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install -U albumentations","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-21T09:42:17.287620Z","iopub.execute_input":"2026-03-21T09:42:17.287920Z","iopub.status.idle":"2026-03-21T09:42:21.007800Z","shell.execute_reply.started":"2026-03-21T09:42:17.287891Z","shell.execute_reply":"2026-03-21T09:42:21.007125Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import albumentations as A\nfrom albumentations.pytorch import ToTensorV2\nimport cv2","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-21T09:42:22.845331Z","iopub.execute_input":"2026-03-21T09:42:22.845979Z","iopub.status.idle":"2026-03-21T09:42:23.781342Z","shell.execute_reply.started":"2026-03-21T09:42:22.845938Z","shell.execute_reply":"2026-03-21T09:42:23.780746Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class ImageDataset(Dataset):\n    \"\"\"/kaggle/input/competitions/aptos2019-blindness-detection/train_images\n       /kaggle/input/competitions/aptos2019-blindness-detection/test_images\"\"\"\n    def __init__(self, root_dir, csv_dir, transform=None, is_test=False):\n        self.root_dir = Path(root_dir)\n        self.transform = transform\n        self.images = []\n        self.labels = []\n        self.is_test = is_test\n        self.df = pd.read_csv(csv_dir)\n        for idx, row in self.df.iterrows():\n            id_i = row['id_code']\n            for end in ['.png', '.jpg', '.jpeg', '.tif']:\n                img = self.root_dir / f'{id_i}{end}'\n                if img.exists():\n                    self.images.append(img)\n                    if not is_test:\n                        self.labels.append(row['diagnosis'])\n    def __len__(self):\n        return len(self.images)\n    def __getitem__(self, idx):\n        img_path = self.images[idx]\n        label = self.labels[idx]\n        img = cv2.imread(str(img_path))\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        if self.transform:\n            transformed = self.transform(image=img)\n            img = transformed['image']\n        return img, label\n    def get_class_weights(self):\n        if self.is_test:\n            return None\n        class_counts = np.bincount(self.labels)\n        total = len(self.labels)\n        num_classes = len(class_counts)\n        weights = total / (num_classes * class_counts)\n        return torch.FloatTensor(weights)    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-21T09:42:27.045884Z","iopub.execute_input":"2026-03-21T09:42:27.046524Z","iopub.status.idle":"2026-03-21T09:42:27.054016Z","shell.execute_reply.started":"2026-03-21T09:42:27.046492Z","shell.execute_reply":"2026-03-21T09:42:27.053238Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class LData_Module(L.LightningDataModule):\n    def __init__(self):\n        self.batch_size = 16\n        self._log_hyperparams = False\n        self.allow_zero_length_dataloader_with_multiple_devices = False\n        self.prepare_data_per_node = False\n    def setup(self,stage=None):\n        df = pd.read_csv(\"/kaggle/input/competitions/aptos2019-blindness-detection/train.csv\")\n        df_train = df[2930:]\n        df_train.to_csv('df_train')\n        df_test = df[2930:]\n        df_test.to_csv('df_test')\n        f1 = Path('train')\n        f2 = Path('test')\n        f1.mkdir(exist_ok=True, parents=True)\n        f2.mkdir(exist_ok=True, parents=True)\n        files = [f for f in Path('/kaggle/input/competitions/aptos2019-blindness-detection/train_images').iterdir() if f.suffix.lower() == '.png']\n        files1 = files[:2930]\n        files2 = files[2930:]\n        for i, file_path in enumerate(files1):\n            destination = f1 / file_path.name\n            shutil.copy2(file_path, destination)\n        for i, file_path in enumerate(files2):\n            destination = f2 / file_path.name\n            shutil.copy2(file_path, destination)\n        train_transform = A.Compose([\n            A.RandomResizedCrop(size=[224, 224], scale=(0.8, 1.0), p=1.0),\n            A.HorizontalFlip(p=0.5),\n            A.ShiftScaleRotate(shift_limit=0.05, scale_limit=0.05, rotate_limit=10, p=0.5),\n            A.RandomBrightnessContrast(brightness_limit=0.1, contrast_limit=0.1, p=0.5),\n            A.GaussNoise(var_limit=(10.0, 30.0), p=0.3),\n            A.GaussianBlur(blur_limit=(3, 5), p=0.2),\n            A.CLAHE(clip_limit=2.0, tile_grid_size=(8, 8), p=0.3),\n            A.CoarseDropout(max_holes=8, max_height=16, max_width=16, fill_value=0, p=0.3),\n            A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n            ToTensorV2()\n        ])\n        test_transform = A.Compose([\n            A.Resize(256, 256),\n            A.CenterCrop(224, 224),\n            A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n            ToTensorV2()\n        ])\n        if stage == 'train' or stage==None:\n            self.t_dataset = ImageDataset(root_dir='/kaggle/working/train', csv_dir='/kaggle/working/df_train', transform=train_transform)\n        if stage == 'val' or stage == None:\n            self.v_dataset = ImageDataset(root_dir='/kaggle/working/test', csv_dir='/kaggle/working/df_test', transform=test_transform)\n    def train_dataloader(self):\n        return DataLoader(\n            self.t_dataset, batch_size=self.batch_size, shuffle=True, num_workers=2\n        )\n    def val_dataloader(self):\n        return DataLoader(\n            self.v_dataset, batch_size=self.batch_size, shuffle=False, num_workers=2\n        )\n    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-21T11:29:28.223891Z","iopub.execute_input":"2026-03-21T11:29:28.224305Z","iopub.status.idle":"2026-03-21T11:29:28.236280Z","shell.execute_reply.started":"2026-03-21T11:29:28.224273Z","shell.execute_reply":"2026-03-21T11:29:28.235526Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class LModel(L.LightningModule):\n    def __init__(self, num_classes):\n        super().__init__()\n        self.save_hyperparameters()\n        self.criterion = nn.CrossEntropyLoss()\n        self.backbone = models.resnet50(weights='DEFAULT')\n        in_features = self.backbone.fc.in_features\n        self.backbone.fc = nn.Linear(in_features, num_classes)\n        for param in self.backbone.parameters():\n            param.requires_grad = False\n        for param in self.backbone.layer4.parameters():\n            param.requires_grad = True\n\n    def forward(self,x):\n        return self.backbone(x)\n    def training_step(self, batch, batch_idx):\n        x, y = batch\n        logits = self(x)\n        loss = self.criterion(logits, y)\n        self.log('train_loss', loss, on_epoch=True, prog_bar=True)\n        return loss\n    def validation_step(self, batch, batch_idx):\n        x, y = batch\n        logits = self(x)\n        preds = torch.argmax(logits, dim=1)\n        loss = self.criterion(logits, y)\n        y = y.cpu().numpy()\n        preds = preds.cpu().numpy()\n        qwk = cohen_kappa_score(y, preds, weights='quadratic')\n        self.log('val_loss', loss, on_epoch=True, prog_bar=True)\n        self.log('qwk', qwk, on_epoch=True, prog_bar=True)\n        return {'val_loss': loss, 'qwk':qwk}\n    def configure_optimizers(self):\n        optimizer = torch.optim.Adam([\n        {'params': self.backbone.layer4.parameters(), 'lr': 1e-3}, \n        {'params': self.backbone.fc.parameters(), 'lr': 1e-2}])\n        scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min')\n        return {\n            'optimizer':optimizer,\n            'lr_scheduler':{\n                'scheduler':scheduler,\n                'monitor':'val_loss',\n                'frequency':1,\n                'strict':True}}\n        ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-21T11:29:49.255053Z","iopub.execute_input":"2026-03-21T11:29:49.255376Z","iopub.status.idle":"2026-03-21T11:29:49.263869Z","shell.execute_reply.started":"2026-03-21T11:29:49.255344Z","shell.execute_reply":"2026-03-21T11:29:49.263248Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train():\n    data_module = LData_Module()\n    data_module.setup()\n    model = LModel(5)\n    callback = [\n        EarlyStopping(\n            monitor='qwk',\n            mode='max',\n            patience=12,\n            min_delta=0.001\n        ),\n        ModelCheckpoint(\n            dirpath='checkpoints',\n            filename='{epoch:02d}-{qwk:.4f}',\n            monitor='qwk',\n            mode='max',\n            save_last=True\n        )\n    ]\n    trainer = L.Trainer(\n        max_epochs=10,\n        accelerator='auto',\n        callbacks=callback,\n        enable_progress_bar=True,\n        gradient_clip_val=1.0\n    )\n    trainer.fit(model,data_module)\n    print(f\"Лучший qwk: {trainer.checkpoint_callback.best_model_score:.4f}\")\n    return model, trainer","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-21T10:06:07.561984Z","iopub.execute_input":"2026-03-21T10:06:07.562687Z","iopub.status.idle":"2026-03-21T10:06:07.568126Z","shell.execute_reply.started":"2026-03-21T10:06:07.562653Z","shell.execute_reply":"2026-03-21T10:06:07.567456Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if __name__ == '__main__':\n    model, trainer = train()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-21T11:29:55.516552Z","iopub.execute_input":"2026-03-21T11:29:55.517449Z","iopub.status.idle":"2026-03-21T11:40:34.313649Z","shell.execute_reply.started":"2026-03-21T11:29:55.517404Z","shell.execute_reply":"2026-03-21T11:40:34.312992Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}