{"cells":[{"metadata":{},"cell_type":"markdown","source":"### The code has been written in Pytorch and used EfficientNet for classification.\n### Custom Data of size 300 x 300 has been used, for fast loading of images, can be found:\nhttps://www.kaggle.com/bitthal/resize-jpg-siimisic-melanoma-classification\n\n### For EDA, refer:\nhttps://www.kaggle.com/bitthal/eda-working-with-dicom-images","execution_count":null},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\nimport os\n\nfrom PIL import Image\nfrom sklearn.model_selection import train_test_split\n\nfrom torchvision import datasets, transforms, models\nfrom torch.utils.data import DataLoader, Dataset\nimport torch.nn as nn\nfrom torchvision import transforms\nimport torch\nimport torchvision\n\n!pip install efficientnet_pytorch\nfrom efficientnet_pytorch import EfficientNet","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"os.listdir('/kaggle/input')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"PATH = '/kaggle/input/resize-jpg-siimisic-melanoma-classification/300x300'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df = pd.read_csv('/kaggle/input/siim-isic-melanoma-classification/train.csv')\nprint(df.shape)\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df = df.sort_values('target', ascending=False).iloc[:5000, :].reset_index()\ndf.groupby('target').count()['image_name']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"Total number of Images:\", df.shape[0])\nprint(\"Total number of Malignmat Images:\", df[df.target == 1].shape[0])\nprint(\"Total number of Benign Images:\", df[df.target == 0].shape[0])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df, val_df = train_test_split(df, stratify=df.target, test_size=0.10)\ntrain_df.reset_index(drop=True, inplace=True)\nval_df.reset_index(drop=True, inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def default_image_loader(path):\n    return Image.open(path).convert('RGB')\n\nclass ImageDataset(Dataset):\n    def __init__(self, data_path, df, transform):\n        self.df = df\n        self.loader = default_image_loader\n        self.transform = transform\n        self.dir = data_path\n\n    def __getitem__(self, index):\n        image_name = self.df.image_name[index]\n        image = self.loader(os.path.join(self.dir, image_name+'.jpg'))\n        image = self.transform(image)\n        \n        if self.dir.split('/')[-1] == 'train':\n            label = self.df.target[index]\n            return image, label\n            \n        return image, image_name\n            \n        \n    \n    def __len__(self):\n        return self.df.shape[0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_transform = transforms.Compose([\n                              transforms.Resize((300, 300)),\n                              transforms.RandomHorizontalFlip(),\n                              transforms.RandomRotation(20),\n                              transforms.ToTensor(),\n                              transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n                            ])\n\nval_transform = transforms.Compose([\n                              transforms.Resize((300, 300)),\n                              transforms.ToTensor(),\n                              transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n                            ])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img_dir = os.path.join(PATH, 'train')\n\ntrain_dataset = ImageDataset(img_dir, train_df, train_transform)\nval_dataset = ImageDataset(img_dir, val_df, val_transform)\n\ntrain_loader = DataLoader(train_dataset, batch_size=32, num_workers=4, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=32, num_workers=4)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\nfor i, l in train_loader:\n    print(l)\n    break","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class Model(nn.Module):\n    def __init__(self):\n        super(Model, self).__init__()\n        self.resnetmodel = EfficientNet.from_pretrained('efficientnet-b3')\n        \n        self.fc = nn.Sequential(nn.Linear(1000, 512), nn.ReLU(),\n                                  nn.Linear(512, 1))\n#                                 , nn.Sigmoid())\n        \n    def forward(self, x):\n        x = self.resnetmodel(x)\n        return self.fc(x)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = Model()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import math\nimport torch\nfrom torch.optim.optimizer import Optimizer, required\n\nclass RAdam(Optimizer):\n\n    def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8, weight_decay=0):\n        defaults = dict(lr=lr, betas=betas, eps=eps, weight_decay=weight_decay)\n        self.buffer = [[None, None, None] for ind in range(10)]\n        super(RAdam, self).__init__(params, defaults)\n\n    def __setstate__(self, state):\n        super(RAdam, self).__setstate__(state)\n\n    def step(self, closure=None):\n\n        loss = None\n        if closure is not None:\n            loss = closure()\n\n        for group in self.param_groups:\n\n            for p in group['params']:\n                if p.grad is None:\n                    continue\n                grad = p.grad.data.float()\n                if grad.is_sparse:\n                    raise RuntimeError('RAdam does not support sparse gradients')\n\n                p_data_fp32 = p.data.float()\n\n                state = self.state[p]\n\n                if len(state) == 0:\n                    state['step'] = 0\n                    state['exp_avg'] = torch.zeros_like(p_data_fp32)\n                    state['exp_avg_sq'] = torch.zeros_like(p_data_fp32)\n                else:\n                    state['exp_avg'] = state['exp_avg'].type_as(p_data_fp32)\n                    state['exp_avg_sq'] = state['exp_avg_sq'].type_as(p_data_fp32)\n\n                exp_avg, exp_avg_sq = state['exp_avg'], state['exp_avg_sq']\n                beta1, beta2 = group['betas']\n\n                exp_avg_sq.mul_(beta2).addcmul_(1 - beta2, grad, grad)\n                exp_avg.mul_(beta1).add_(1 - beta1, grad)\n\n                state['step'] += 1\n                buffered = self.buffer[int(state['step'] % 10)]\n                if state['step'] == buffered[0]:\n                    N_sma, step_size = buffered[1], buffered[2]\n                else:\n                    buffered[0] = state['step']\n                    beta2_t = beta2 ** state['step']\n                    N_sma_max = 2 / (1 - beta2) - 1\n                    N_sma = N_sma_max - 2 * state['step'] * beta2_t / (1 - beta2_t)\n                    buffered[1] = N_sma\n\n                    # more conservative since it's an approximated value\n                    if N_sma >= 5:\n                        step_size = group['lr'] * math.sqrt((1 - beta2_t) * (N_sma - 4) / (N_sma_max - 4) * (N_sma - 2) / N_sma * N_sma_max / (N_sma_max - 2)) / (1 - beta1 ** state['step'])\n                    else:\n                        step_size = group['lr'] / (1 - beta1 ** state['step'])\n                    buffered[2] = step_size\n\n                if group['weight_decay'] != 0:\n                    p_data_fp32.add_(-group['weight_decay'] * group['lr'], p_data_fp32)\n\n                # more conservative since it's an approximated value\n                if N_sma >= 5:                    \n                    denom = exp_avg_sq.sqrt().add_(group['eps'])\n                    p_data_fp32.addcdiv_(-step_size, exp_avg, denom)\n                else:\n                    p_data_fp32.add_(-step_size, exp_avg)\n\n                p.data.copy_(p_data_fp32)\n\n        return loss","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"criterion = nn.BCEWithLogitsLoss()\n# optimizer = torch.optim.Adam(model.parameters(), lr=0.001)\noptimizer = RAdam(model.parameters(), lr=0.001)\nscheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, 0.95)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.cuda()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for epoch in range(10):  # loop over the dataset multiple times\n\n    running_loss = 0.0\n    model.train()\n    correct = 0\n    total = 0\n    for images, labels in train_loader:\n        images = images.cuda()\n        labels = labels.cuda()\n        out = model(images)\n        labels = labels.unsqueeze(1).float()\n        loss = criterion(out, labels)\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n\n        running_loss += loss.item()\n        \n#         _, predicted = torch.max(out.data, 1)\n        total += labels.size(0)\n        out = torch.sigmoid(out)\n        correct += ((out > 0.6).int() == labels).sum().item()\n    \n    print(\"Epoch: {}, Loss: {}, Train Accuracy: {}\".format(epoch, running_loss, round(correct/total, 4)))\n    if epoch % 2 == 1:\n        scheduler.step()\n        \n    model.eval()\n    running_loss = 0\n    correct = 0\n    total = 0\n    \n    with torch.no_grad():\n        for images, labels in val_loader:\n            images = images.cuda()\n            labels = labels.cuda()\n            labels = labels.unsqueeze(1).float()\n            \n            out = model(images)\n            loss = criterion(out.data, labels)\n            \n            running_loss += loss.item()\n\n            total += labels.size(0)\n            out = torch.sigmoid(out)\n            correct += ((out > 0.6).int() == labels).sum().item()\n            \n    print(\"Epoch: {}, Loss: {}, Test Accuracy: {}\\n\".format(epoch, running_loss, round(correct/total, 4)))\n    \nprint('Finished Training')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df = pd.read_csv('/kaggle/input/siim-isic-melanoma-classification/test.csv')\ntest_df = test_df.reset_index(drop=True)\ntest_df.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img_dir = os.path.join(PATH, 'test')\n\ntest_dataset = ImageDataset(img_dir, test_df, val_transform)\ntest_loader = DataLoader(test_dataset, batch_size=64, num_workers=8)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for a, b in test_loader:\n#     print(b)\n    pass\n    break","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.eval()\nres_id = []\nres_prob = []\n\nwith torch.no_grad():\n    for images, ids in test_loader:\n        images = images.cuda()\n\n        out = model(images)\n        predicted = torch.sigmoid(out)\n        \n        res_id += ids\n        res_prob += predicted.cpu().numpy().tolist()\n        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"res_prob = [x[0] for x in res_prob]\nsum(res_prob)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sub = pd.DataFrame({\"image_name\":res_id, \"target\":res_prob})\nsub.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sub.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sub.to_csv('submission.csv', index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}