{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport cv2\nimport os\nfrom pathlib import Path\nimport matplotlib.pyplot as plt\nimport random\nimport json\n\nimport skimage.io\nfrom sklearn.preprocessing import OneHotEncoder #One-hot 인코더\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import cohen_kappa_score\n\nimport tensorflow as tf\nfrom tensorflow.keras import Model, Sequential\nfrom tensorflow.keras.models import load_model\nfrom tensorflow.keras.utils import Sequence\nfrom tensorflow.keras.layers import *\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau\nfrom tensorflow.keras.losses import categorical_crossentropy\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n\nfrom tensorflow.keras.applications import ResNet50\n\nimport albumentations as albu","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Variable Setting ","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"DATA_PATH = '../input/prostate-cancer-grade-assessment'\nMODELS_PATH = '.'\nIMG_SIZE = 56 \nSEQ_LEN = 16 # 16^2 = 256\nBATCH_SIZE = 16\nMDL_VERSION = 'v18'\nSEED = 80","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## IMG pre-processing","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"class DataGenPanda(Sequence):\n    #initialize\n    def __init__(self, imgs_path, df, batch_size=32, \n                 mode='fit', shuffle=False, aug=None, \n                 seq_len=12, img_size=128, n_classes=6):\n        self.imgs_path = imgs_path\n        self.df = df\n        self.shuffle = shuffle\n        self.mode = mode\n        self.aug = aug\n        self.batch_size = batch_size\n        self.img_size = img_size\n        self.seq_len = seq_len\n        self.n_classes = n_classes\n        self.side = int(seq_len ** .5)\n        self.on_epoch_end()\n    \n    def __len__(self):\n        return int(np.floor(len(self.df) / self.batch_size))\n    \n    def on_epoch_end(self):\n        self.indexes = np.arange(len(self.df))\n        if self.shuffle:\n            np.random.shuffle(self.indexes)\n            \n    def __getitem__(self, index):\n        X = np.zeros((self.batch_size, self.side * self.img_size, self.side * self.img_size, 3), dtype=np.float32)\n        imgs_batch = self.df[index * self.batch_size : (index + 1) * self.batch_size]['image_id'].values\n        for i, img_name in enumerate(imgs_batch):\n            img_path = '{}/{}.tiff'.format(self.imgs_path, img_name)\n            img_patches = self.get_patches(img_path)\n            X[i, ] = self.glue_to_one(img_patches)\n        if self.mode == 'fit':\n            y = np.zeros((self.batch_size, self.n_classes), dtype=np.float32)\n            lbls_batch = self.df[index * self.batch_size : (index + 1) * self.batch_size]['isup_grade'].values\n            for i in range(self.batch_size):\n                y[i, lbls_batch[i]] = 1\n            return X, y\n        elif self.mode == 'predict':\n            return X\n        else:\n            raise AttributeError('mode parameter error')\n            \n    def get_patches(self, img_path):\n        num_patches = self.seq_len\n        p_size = self.img_size\n        img = skimage.io.MultiImage(img_path)[-1] / 255\n        if self.aug:\n            img = self.aug(image=img)['image'] \n        pad0, pad1 = (p_size - img.shape[0] % p_size) % p_size, (p_size - img.shape[1] % p_size) % p_size\n        img = np.pad(\n            img,\n            [\n                [pad0 // 2, pad0 - pad0 // 2], \n                [pad1 // 2, pad1 - pad1 // 2], \n                [0, 0]\n            ],\n            constant_values=1\n        )\n        img = img.reshape(img.shape[0] // p_size, p_size, img.shape[1] // p_size, p_size, 3)\n        img = img.transpose(0, 2, 1, 3, 4).reshape(-1, p_size, p_size, 3)\n        if len(img) < num_patches:\n            img = np.pad(\n                img, \n                [\n                    [0, num_patches - len(img)],\n                    [0, 0],\n                    [0, 0],\n                    [0, 0]\n                ],\n                constant_values=1\n            )\n        idxs = np.argsort(img.reshape(img.shape[0], -1).sum(-1))[:num_patches]\n        return np.array(img[idxs])\n    def glue_to_one(self, imgs_seq):\n        img_glue = np.zeros((self.img_size * self.side, self.img_size * self.side, 3), dtype=np.float32)\n        #img_size * side 만큼 float32비트 형식으로 0으로 채움\n        \n        for i, ptch in enumerate(imgs_seq):\n            x = i // self.side\n            y = i % self.side\n            img_glue[x * self.img_size : (x + 1) * self.img_size, \n                     y * self.img_size : (y + 1) * self.img_size, :] = ptch\n        return img_glue","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#data augmentation 수행\naug = albu.Compose(\n    [\n        albu.HorizontalFlip(p=.25),\n        albu.VerticalFlip(p=.25),\n        albu.ShiftScaleRotate(shift_limit=.1, scale_limit=.1, rotate_limit=20, p=.25)\n    ]\n)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Build Model","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def kappa_score(y_true, y_pred):\n    \n    y_true=tf.math.argmax(y_true)\n    y_pred=tf.math.argmax(y_pred)\n    return tf.compat.v1.py_func(cohen_kappa_score ,(y_true, y_pred),tf.double)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pre_file = '../input/panda-resnet50-model-1/model_v18_resnet50.h5'\nresnet_weights_path = '../input/panda-resnet50-model-1/resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5'\ninput = Input(shape=(224, 224, 3))\nmodel = Sequential()\n\nbottleneck = ResNet50(weights=resnet_weights_path, include_top=False, pooling='avg', input_tensor=input)\nmodel.add(bottleneck)\nmodel.add(Flatten())\nmodel.add(Dense(1024, activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(Dropout(.25))\nmodel.add(Dense(6, activation='sigmoid'))\nmodel.summary()\n\nmodel.compile(\n    loss='binary_crossentropy',\n    optimizer=Adam(lr=1e-5),\n    metrics=['binary_crossentropy',kappa_score]\n)\nmodel.load_weights(pre_file)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Submit ","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"test = pd.read_csv('{}/test.csv'.format(DATA_PATH))\npreds = [[0] * 6] * len(test)\nif os.path.exists('../input/prostate-cancer-grade-assessment/test_images'):\n    subm_datagen = DataGenPanda(\n        imgs_path='{}/test_images'.format(DATA_PATH), \n        df=test,\n        batch_size=1,\n        mode='predict', \n        shuffle=False, \n        aug=None, \n        seq_len=SEQ_LEN, \n        img_size=IMG_SIZE, \n        n_classes=6\n    )\n    preds = model.predict_generator(subm_datagen)\n    print('preds done, total:', len(preds))\nelse:\n    print('preds are zeros')\ntest['isup_grade'] = np.argmax(preds, axis=1)\ntest.drop('data_provider', axis=1, inplace=True)\ntest.to_csv('submission.csv', index=False)\nprint('submission saved')","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}