{"cells":[{"metadata":{},"cell_type":"markdown","source":"# What is this kernel?","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"The 5-fold model have been trained with the cleaned labels. We show that by the cleaned label approach, we can get a 3rd PB by simple ensembling of efficienet models.","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"# arutema inference","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nimport sys\nsys.path = [\n    '../input/efficientnet-pytorch/EfficientNet-PyTorch/EfficientNet-PyTorch-master',\n] + sys.path","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sys.path = [\n    '../input/ttach-kaggle/ttach/',\n] + sys.path\nimport ttach as tta","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import skimage.io\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\nimport torchvision\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.data import DataLoader, Dataset\nfrom efficientnet_pytorch import model as enet\n\nimport matplotlib.pyplot as plt\nfrom tqdm import tqdm_notebook as tqdm","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data_dir = '../input/prostate-cancer-grade-assessment'\ndf_train = pd.read_csv(os.path.join(data_dir, 'train.csv'))\ndf_test = pd.read_csv(os.path.join(data_dir, 'test.csv'))\ndf_sub = pd.read_csv(os.path.join(data_dir, 'sample_submission.csv'))\n\nmodel_dir = '../input/panda-public-models'\nimage_folder = os.path.join(data_dir, 'test_images')\nis_test = os.path.exists(image_folder)  # IF test_images is not exists, we will use some train images.\nimage_folder = image_folder if is_test else os.path.join(data_dir, 'train_images')\n\ndf = df_test if is_test else df_train.loc[:16]\n\ntile_size = 256\nimage_size = 256\nn_tiles = 36\nbatch_size = 4\nnum_workers = 4\n\ndevice = torch.device('cuda')\n\nprint(image_folder)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class enetv3(nn.Module):\n    def __init__(self, modelname, out_dim=5, freeze_bn=True):\n        super(enetv3, self).__init__()\n           \n        from efficientnet_pytorch import EfficientNet\n        self.basemodel = EfficientNet.from_name(modelname) \n        self.myfc = nn.Linear(self.basemodel._fc.in_features, out_dim)\n        self.basemodel._fc = nn.Identity()     \n        self.basemodel._avg_pooling = nn.AdaptiveAvgPool2d(1) #GeM() \n\n            \n    def extract(self, x):\n        return self.basemodel(x)\n\n    def forward(self, x):\n        x = self.basemodel(x)\n        if not \"eff\" in modelname:\n            x = self.pool(x).squeeze(2).squeeze(2)\n            x = self.myfc(x)\n        else:\n            x = self.myfc(x)\n        return x\n    \ndef load_models(model_files):\n    models = []\n    for model_f in model_files:\n        model_f = os.path.join(\"../input/latesubspanda\", model_f)\n        if \"res\" in model_f:\n            model = enetv2(out_dim=5)\n        elif \"eff\" in model_f:\n            model = enetv3(modelname, out_dim=5)\n        model.load_state_dict(torch.load(model_f))\n        model.eval()\n        model.to(device)\n        models.append(model)\n        print(f'{model_f} loaded!')\n    return models\n\nmodelname=\"efficientnet-b0\"\n\n# load ensembles\nmodel_files2 = [\n    \"efficientnet-b0famlabelsmodelsub_avgpool_tile36_imsize256_mixup_final_epoch20_fold0.pth\",\n    \"efficientnet-b0famlabelsmodelsub_avgpool_tile36_imsize256_mixup_final_epoch20_fold1.pth\",\n    \"efficientnet-b0famlabelsmodelsub_avgpool_tile36_imsize256_mixup_final_epoch20_fold2.pth\",\n    \"efficientnet-b0famlabelsmodelsub_avgpool_tile36_imsize256_mixup_final_epoch20_fold3.pth\",\n    \"efficientnet-b0famlabelsmodelsub_avgpool_tile36_imsize256_mixup_final_epoch20_fold4.pth\"\n]\n\nmodels2 = load_models(model_files2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_tiles(img, 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        img2 = 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        img3 = img2.reshape(\n            img2.shape[0] // tile_size,\n            tile_size,\n            img2.shape[1] // tile_size,\n            tile_size,\n            3\n        )\n\n        img3 = img3.transpose(0,2,1,3,4).reshape(-1, tile_size, tile_size,3)\n        n_tiles_with_info = (img3.reshape(img3.shape[0],-1).sum(1) < tile_size ** 2 * 3 * 255).sum()\n        if len(img) < n_tiles:\n            img3 = np.pad(img3,[[0,N-len(img3)],[0,0],[0,0],[0,0]], constant_values=255)\n        idxs = np.argsort(img3.reshape(img3.shape[0],-1).sum(-1))[:n_tiles]\n        img3 = img3[idxs]\n        for i in range(len(img3)):\n            result.append({'img':img3[i], 'idx':i})\n        return result, n_tiles_with_info >= n_tiles\n\n\nclass PANDADataset(Dataset):\n    def __init__(self,\n                 df,\n                 image_size,\n                 n_tiles=n_tiles,\n                 tile_mode=0,\n                 rand=False,\n                 sub_imgs=False\n                ):\n\n        self.df = df.reset_index(drop=True)\n        self.image_size = image_size\n        self.n_tiles = n_tiles\n        self.tile_mode = tile_mode\n        self.rand = rand\n        self.sub_imgs = sub_imgs\n\n    def __len__(self):\n        return self.df.shape[0]\n\n    def __getitem__(self, index):\n        row = self.df.iloc[index]\n        img_id = row.image_id\n        \n        tiff_file = os.path.join(image_folder, f'{img_id}.tiff')\n        image = skimage.io.MultiImage(tiff_file)[1][:,:,::-1]\n        tiles, OK = get_tiles(image, self.tile_mode)\n\n        if self.rand:\n            idxes = np.random.choice(list(range(self.n_tiles)), self.n_tiles, replace=False)\n        else:\n            idxes = list(range(self.n_tiles))\n        idxes = np.asarray(idxes) + self.n_tiles if self.sub_imgs else idxes\n\n        n_row_tiles = int(np.sqrt(self.n_tiles))\n        images = np.zeros((image_size * n_row_tiles, 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                if len(tiles) > idxes[i]:\n                    this_img = tiles[idxes[i]]['img']\n                else:\n                    this_img = np.ones((self.image_size, self.image_size, 3)).astype(np.uint8) * 255\n                this_img = 255 - this_img\n                h1 = h * image_size\n                w1 = w * image_size\n                images[h1:h1+image_size, w1:w1+image_size] = this_img\n        #images = 255 - images\n        images = images.astype(np.float32)\n        images /= 255\n        images = images.transpose(2, 0, 1)\n\n        return torch.tensor(images)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if not is_test:\n    dataset_show = PANDADataset(df, image_size, n_tiles, 4)\n    from pylab import rcParams\n    rcParams['figure.figsize'] = 20,10\n    for i in range(2):\n        f, axarr = plt.subplots(1,5)\n        for p in range(5):\n            idx = np.random.randint(0, len(dataset_show))\n            img = dataset_show[idx]\n            axarr[p].imshow(1. - img.transpose(0, 1).transpose(1,2).squeeze())\n            axarr[p].set_title(str(idx))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Prepare tiles with different paddings, introducing slightly different tiles\ndataset = PANDADataset(df, image_size, n_tiles, 0)  # mode == 0\nloader = DataLoader(dataset, batch_size=batch_size, num_workers=num_workers, shuffle=False)\n\ndataset2 = PANDADataset(df, image_size, n_tiles, 2)  # mode == 2\nloader2 = DataLoader(dataset2, batch_size=batch_size, num_workers=num_workers, shuffle=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Setup TTA","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import ttach as tta\nif len(dataset) > 50:\n    transforms = tta.Compose(\n        [\n            tta.HorizontalFlip(),\n            tta.VerticalFlip(),\n            tta.Rotate90(angles=[0, 90, 180]),\n        ]\n    )\nelse:\n    # For commits\n    transforms = tta.Compose(\n        [\n            #tta.HorizontalFlip(),\n        ]\n    )\n    \ntta_models2 = []\n# TTA wrappers\nfor model in models2:\n    tta_models2.append(tta.ClassificationTTAWrapper(model, transforms))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"LOGITS = []\nLOGITS2 = []\nLOGITS12 = []\nLOGITS22 = []\n\nwith torch.no_grad():\n    for data in tqdm(loader):\n        data = data.to(device)\n\n        for i, tta_model in enumerate(tta_models2):\n            if i == 0:\n                logits = tta_model(data).sigmoid()\n            else:\n                logits = logits + tta_model(data).sigmoid()\n        LOGITS2.append(logits/5)\n        \n    for data in tqdm(loader2):\n        data = data.to(device)\n        \n        for i, tta_model in enumerate(tta_models2):\n            if i == 0:\n                logits = tta_model(data).sigmoid()\n            else:\n                logits = logits + tta_model(data).sigmoid()\n        LOGITS22.append(logits/5)\n\n\nLOGITS = (torch.cat(LOGITS2).cpu() + torch.cat(LOGITS22).cpu()) / 2","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"PREDS = LOGITS.sum(1).numpy()\ndf['isup_grade'] = PREDS\ndf","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df['isup_grade'] = df['isup_grade'].apply(lambda x: int(np.round(x)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df[['image_id', 'isup_grade']].to_csv('submission.csv', index=False)\nprint(df.head())\nprint()\nprint(df.isup_grade.value_counts())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.head(20)","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}