{"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":"code","source":"import os, sys\nsys.path = ['../input/efficientnet-pytorch/EfficientNet-PyTorch/EfficientNet-PyTorch-master', ] + sys.path","metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Basic Python and Machine learning libraries\nimport random, cv2\nimport pandas as pd\nimport numpy as np\nimport skimage.io\nfrom tqdm.notebook import tqdm\n\n#Pytorch and Albumentations(Data Augmentation Library)\nimport torch\nimport albumentations\nfrom torch import nn\nfrom torch.utils.data import Dataset, DataLoader\n\nfrom efficientnet_pytorch import EfficientNet","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"CONFIG = {}\n    \n#change to choose coresponding dataset. VALID: 16, 25, 36\nCONFIG['data_dir'] = '../input/prostate-cancer-grade-assessment/'\nCONFIG['test_img_dir'] = os.path.join(CONFIG['data_dir'], 'test_images')\n\nCONFIG['backbone'] = 'efficientnet-b1'\nCONFIG['model_dir'] = ['../input/newpandamodels/efficientnet-b1_fold_0_epoch_7.pt',\n                       '../input/newpandamodels/efficientnet-b1_fold_1_epoch_8.pt',\n                       '../input/newpandamodels/efficientnet-b1_fold_2_epoch_9.pt',\n                       '../input/newpandamodels/efficientnet-b1_fold_3_epoch_8.pt',\n                       '../input/newpandamodels/efficientnet-b1_fold_4_epoch_8.pt']\n\n\n#Add to config understandable definition of target size for BCE or CCE\nCONFIG['sum_prediction'] = False\nCONFIG['out_dim'] = 5 if CONFIG['sum_prediction'] else 6\n\nCONFIG['image_size'] = 256\nCONFIG['tile_size'] = 256\nCONFIG['tile_mode'] = 0\nCONFIG['n_tiles'] = 36\nCONFIG['batch_size'] = 2\nCONFIG['num_workers'] = 4\n\nCONFIG['device'] = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n#Image-net standard mean and std\nCONFIG['mean'] = [0.485, 0.456, 0.406]\nCONFIG['std'] = [0.229, 0.224, 0.225]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(CONFIG['device'])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DataSet","metadata":{}},{"cell_type":"code","source":"def get_tiles(img, tile_size, n_tiles, mode=0):\n    result = []\n    h, w, c = img.shape\n    pad_h = (tile_size - h % tile_size) % tile_size + ((tile_size * mode) // 2)\n    pad_w = (tile_size - w % tile_size) % tile_size + ((tile_size * mode) // 2)\n\n    img = np.pad(img,[[pad_h // 2, pad_h - pad_h // 2], [pad_w // 2,pad_w - pad_w//2], [0,0]], constant_values=255)\n    img = img.reshape(\n            img.shape[0] // tile_size,\n            tile_size,\n            img.shape[1] // tile_size,\n            tile_size,\n            3\n        )\n    img = img.transpose(0,2,1,3,4).reshape(-1, tile_size, tile_size,3)\n    \n    if len(img) < n_tiles:\n        img = np.pad(img,[[0,n_tiles-len(img)],[0,0],[0,0],[0,0]], constant_values=255)\n    idxs = np.argsort(img.reshape(img.shape[0],-1).sum(-1))[:n_tiles]\n    img = img[idxs]\n    \n    for i in range(len(img)):\n        result.append({'img':img[i], 'idx':i})\n    \n    return result\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class PANDA_Dataset(Dataset):\n    def __init__(self,\n                 df,\n                 config,\n                 img_transform=None\n                ):\n\n        self.df = df.reset_index(drop=True)\n        self.config = config\n        self.img_transform = img_transform\n\n    def __len__(self):\n        return self.df.shape[0]\n\n    def __getitem__(self, index):\n        img_path = os.path.join(self.config['test_img_dir'], self.df['image_id'].values[index]) + '.tiff'\n        image_id = self.df['image_id'].values[index]\n        image = skimage.io.MultiImage(img_path)[1]\n        \n        tiles = get_tiles(image, self.config['tile_size'], self.config['n_tiles'], self.config['tile_mode'])\n        idxes = list(range(self.config['n_tiles']))\n        \n        n_row_tiles = int(np.sqrt(self.config['n_tiles']))\n        images = np.zeros((self.config['image_size'] * n_row_tiles, self.config['image_size'] * n_row_tiles, 3))\n        for h in range(n_row_tiles):\n            for w in range(n_row_tiles):\n                i = h * n_row_tiles + w\n                \n                tile_i = tiles[idxes[i]]['img']\n                \n                h1 = h * self.config['image_size']\n                w1 = w * self.config['image_size']\n                images[h1:h1+self.config['image_size'], w1:w1+self.config['image_size']] = tile_i\n        \n        if self.img_transform is not None:\n            images = images.astype(np.float32)\n            images = self.img_transform(image=images)['image']\n        else:\n            images = images.astype(np.float32)\n            images /= 255\n            \n        images = images.transpose(2, 0, 1)\n        \n        return torch.tensor(images), image_id","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"code","source":"class Model(nn.Module):\n    def __init__(self, backbone, out_dim=6):\n        super(Model, self).__init__()\n        self.enet = EfficientNet.from_name('efficientnet-b1')\n        \n        self.fc = nn.Linear(self.enet._fc.in_features, out_dim)\n        self.enet._fc = nn.Identity()\n    \n    def forward(self, x):\n        x = self.enet(x)\n        x = self.fc(x)\n        return x","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"models = []\nfor path in CONFIG['model_dir']:\n    model = Model(CONFIG['backbone'], CONFIG['out_dim'])\n    model.to(CONFIG['device'])\n    state_dict = torch.load(path, map_location=CONFIG['device'])\n    model.load_state_dict(state_dict)\n    model.eval()\n    models.append(model)\n\ndel state_dict","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prediction","metadata":{}},{"cell_type":"code","source":"test_img_transforms = albumentations.Compose([\n    albumentations.Normalize(mean=CONFIG['mean'], std=CONFIG['std'], always_apply=True)\n])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_path = os.path.join(CONFIG['data_dir'], 'sample_submission.csv')\nsub_df = pd.read_csv(sample_path)\nif os.path.exists(CONFIG['test_img_dir']):\n    \n    test_path = os.path.join(CONFIG['data_dir'], 'test.csv')\n    test_df = pd.read_csv(test_path)\n    \n    test_ds = PANDA_Dataset(test_df, CONFIG, test_img_transforms)\n    test_dl = DataLoader(test_ds, batch_size=CONFIG['batch_size'], num_workers=CONFIG['num_workers'], shuffle=False)\n    image_id_list, preds_list = [],[]\n\n    with torch.no_grad():\n        for data, image_id in tqdm(test_dl):\n            data = data.to(CONFIG['device'])\n            # NEW\n            data = torch.stack([data, data.flip(-1), data.flip(-2), data.flip(-1,-2),\n                                data.transpose(-1,-2), data.transpose(-1,-2).flip(-1),\n                                data.transpose(-1,-2).flip(-2),data.transpose(-1,-2).flip(-1,-2)],\n                               1)\n            data = data.view(-1, 3, 1536, 1536)\n            # OLD\n#             logits = model(data)\n#             preds = torch.argmax(logits, dim=1)\n\n#             image_id_list.append(image_id)\n#             preds_list.append(preds)\n            # NEW\n            preds = [model(data) for model in models]\n            preds = torch.stack(preds, 1)\n            preds = preds.view(CONFIG['batch_size'], 8*len(models), -1).mean(1).argmax(-1)\n            \n            image_id_list.append(image_id)\n            preds_list.append(preds)\n        \n    preds_list = torch.cat(preds_list).cpu().numpy()\n    image_id_list = np.concatenate(image_id_list)\n    \n    sub_df = pd.DataFrame({'image_id': image_id_list, 'isup_grade': preds_list})\n    sub_df.to_csv('submission.csv', index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df.to_csv(\"submission.csv\", index=False)\nsub_df.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}