{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Summary\n\nWon't waste your time. To train larger models in almost 2x speed, try to take the advantage of the GPU T4 x2. For more about the new gpu option, check this [discussion](https://www.kaggle.com/product-feedback/361104). In this notebook, I have trained a large vision model called [\"Efficientnet B6\"](https://pytorch.org/vision/main/models/generated/torchvision.models.efficientnet_b6.html) using pytorch lightning. PyTorch lightning makes it easier to use multiple gpus for training","metadata":{}},{"cell_type":"code","source":"import pathlib\n\nimport pandas as pd\nimport numpy as np\nimport cv2\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader, WeightedRandomSampler\n\nimport pytorch_lightning as pl\nfrom torchvision import models","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-01-23T11:19:19.369535Z","iopub.execute_input":"2023-01-23T11:19:19.370398Z","iopub.status.idle":"2023-01-23T11:19:27.880775Z","shell.execute_reply.started":"2023-01-23T11:19:19.370287Z","shell.execute_reply":"2023-01-23T11:19:27.879584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Config:\n    IMG_DIR = pathlib.Path('/kaggle/input/rsna-mammography-images-as-pngs/'\n                           'images_as_pngs_cv2_256/train_images_processed_cv2_256')\n    TRAIN_SAMPLES = 10_000\n    VAL_SAMPLES = 5_000\n    TRAIN_BATCH_SIZE = 32\n    VAL_BATCH_SIZE = 32\n    MAX_EPOCHS = 100","metadata":{"execution":{"iopub.status.busy":"2023-01-23T11:19:27.887765Z","iopub.execute_input":"2023-01-23T11:19:27.888558Z","iopub.status.idle":"2023-01-23T11:19:27.8962Z","shell.execute_reply.started":"2023-01-23T11:19:27.888489Z","shell.execute_reply":"2023-01-23T11:19:27.894124Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class RSNADataset(Dataset):\n    \n    def __init__(self, X, y, config):\n        self.config = config\n        self.X = X.reset_index()\n        self.y = y.values\n    \n    def __len__(self):\n        return len(self.X)\n    \n    def __getitem__(self, idx):\n        x = self.X.iloc[idx]\n        fp = self.config.IMG_DIR / x.patient_id / x.image_id\n        fp = fp.as_posix() +  '.png'\n        img = cv2.imread(fp)\n        img = cv2.resize(img, (224, 224))\n        img = img / np.max(img)\n        img = img.astype('float32')\n        img = img.transpose([2, 0, 1])\n        return img, self.y[idx]","metadata":{"execution":{"iopub.status.busy":"2023-01-23T11:19:27.898066Z","iopub.execute_input":"2023-01-23T11:19:27.898467Z","iopub.status.idle":"2023-01-23T11:19:27.915291Z","shell.execute_reply.started":"2023-01-23T11:19:27.898427Z","shell.execute_reply":"2023-01-23T11:19:27.914141Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\ndef get_train_val_datasets(path):\n    train_df = pd.read_csv(path)\n    train_df['patient_id'] = train_df['patient_id'].astype(str)\n    train_df['image_id'] = train_df['image_id'].astype(str)\n    train_df['weights'] = np.ones(len(train_df))\n    train_df.loc[train_df['cancer'] == 1, 'weights'] = 46.\n    X = train_df[['patient_id', 'image_id', 'weights']]\n    y = train_df[['cancer']]\n    X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, stratify=y['cancer'])\n    train_ds = RSNADataset(X_train, y_train.astype('float32'), Config)\n    val_ds = RSNADataset(X_val, y_val.astype('float32'), Config)\n    \n    train_sampler = WeightedRandomSampler(X_train['weights'].values, Config.TRAIN_SAMPLES)\n    val_sampler = WeightedRandomSampler(X_val['weights'].values, Config.VAL_SAMPLES)\n    \n    return train_ds, val_ds, train_sampler, val_sampler\n    \noutput = get_train_val_datasets('/kaggle/input/rsna-breast-cancer-detection/train.csv')\ntrain_ds, val_ds, train_sampler, val_sampler = output","metadata":{"execution":{"iopub.status.busy":"2023-01-23T11:19:27.918719Z","iopub.execute_input":"2023-01-23T11:19:27.919151Z","iopub.status.idle":"2023-01-23T11:19:29.763803Z","shell.execute_reply.started":"2023-01-23T11:19:27.919114Z","shell.execute_reply":"2023-01-23T11:19:29.762725Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class RSNADataModule(pl.LightningDataModule):\n    def __init__(self, path):\n        super().__init__()\n        output = get_train_val_datasets(path)\n        self.train_ds = output[0]\n        self.val_ds = output[1]\n        self.train_sampler = output[2]\n        self.val_sampler = output[3]\n    \n    def train_dataloader(self):\n        return DataLoader(self.train_ds,\n                          batch_size=Config.TRAIN_BATCH_SIZE,\n                          num_workers=2, \n                          pin_memory=True,\n                          sampler=self.train_sampler)\n    \n    def val_dataloader(self):\n        return DataLoader(self.val_ds,\n                          batch_size=Config.VAL_BATCH_SIZE,\n                          num_workers=2, \n                          pin_memory=True,\n                          sampler=self.val_sampler)","metadata":{"execution":{"iopub.status.busy":"2023-01-23T11:19:29.766562Z","iopub.execute_input":"2023-01-23T11:19:29.76734Z","iopub.status.idle":"2023-01-23T11:19:29.775623Z","shell.execute_reply.started":"2023-01-23T11:19:29.767278Z","shell.execute_reply":"2023-01-23T11:19:29.774561Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class model(pl.LightningModule): \n    def __init__(self): \n        super().__init__() \n#         model = models.resnet50(pretrained=True)\n#         in_features = model.fc.in_features\n#         model.fc = nn.Linear(in_features, 1)\n        \n        model = models.efficientnet_b6(pretrained=True)\n        self.model = model\n        self.clf = nn.Linear(1000, 1)\n        self.loss = nn.BCEWithLogitsLoss()\n  \n    def forward(self, x): \n        return self.clf(F.relu(self.model(x)))\n  \n    def configure_optimizers(self): \n        return torch.optim.Adam(self.parameters())\n  \n    def training_step(self, train_batch, batch_idx): \n        x, y = train_batch \n        logits = self.forward(x) \n        loss = self.loss(logits, y)\n        return {\"loss\": loss} \n  \n    def validation_step(self, valid_batch, batch_idx): \n        x, y = valid_batch \n        logits = self.forward(x) \n        loss = self.loss(logits, y)\n        self.log('val_loss', loss, sync_dist=True)\n        return {\"val_loss\": loss}","metadata":{"execution":{"iopub.status.busy":"2023-01-23T11:19:29.777542Z","iopub.execute_input":"2023-01-23T11:19:29.777958Z","iopub.status.idle":"2023-01-23T11:19:29.794117Z","shell.execute_reply.started":"2023-01-23T11:19:29.777917Z","shell.execute_reply":"2023-01-23T11:19:29.793179Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"clf = model()\nrsna = RSNADataModule('/kaggle/input/rsna-breast-cancer-detection/train.csv')","metadata":{"execution":{"iopub.status.busy":"2023-01-23T11:19:29.796056Z","iopub.execute_input":"2023-01-23T11:19:29.796519Z","iopub.status.idle":"2023-01-23T11:19:32.112172Z","shell.execute_reply.started":"2023-01-23T11:19:29.796479Z","shell.execute_reply":"2023-01-23T11:19:32.111098Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from pytorch_lightning.callbacks.early_stopping import EarlyStopping\n\nearly_stop_callback = EarlyStopping(monitor=\"val_loss\",\n                                    min_delta=0.00,\n                                    patience=3,\n                                    verbose=False,\n                                    mode=\"min\")\n\n# device =-1 means to use all available gpus\ntrainer = pl.Trainer(accelerator=\"gpu\", devices=-1, precision=16,\n                     strategy=\"ddp_notebook\",\n                     callbacks=[early_stop_callback],\n                     max_epochs=Config.MAX_EPOCHS, log_every_n_steps=10)\n\ntrainer.fit(clf, rsna)","metadata":{"execution":{"iopub.status.busy":"2023-01-23T11:19:32.113941Z","iopub.execute_input":"2023-01-23T11:19:32.114355Z","iopub.status.idle":"2023-01-23T11:29:42.766754Z","shell.execute_reply.started":"2023-01-23T11:19:32.114296Z","shell.execute_reply":"2023-01-23T11:29:42.765272Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainer.validate(clf, rsna)","metadata":{"execution":{"iopub.status.busy":"2023-01-23T11:31:14.434297Z","iopub.execute_input":"2023-01-23T11:31:14.435625Z","iopub.status.idle":"2023-01-23T11:32:33.028189Z","shell.execute_reply.started":"2023-01-23T11:31:14.435578Z","shell.execute_reply":"2023-01-23T11:32:33.026886Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}