{"cells":[{"metadata":{"trusted":true,"_uuid":"2a8dcdaa7d95e991052e48ebe8ca007be415dad7"},"cell_type":"code","source":"import os, sys\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport skimage.io\nfrom skimage.transform import resize\nfrom imgaug import augmenters as iaa\n\nimport PIL\nfrom PIL import Image\nimport cv2\nfrom sklearn.utils import class_weight, shuffle\nimport keras\nimport warnings\nfrom keras.utils import Sequence\nwarnings.filterwarnings(\"ignore\")\nSIZE = 299\nSEED = 777\nTHRESHOLD = 0.2","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"85cc78b0d4b913729217a989e4cde2ca63f5d331"},"cell_type":"code","source":"# Load dataset info\nDIR = '../input/'\ndata = pd.read_csv('../input/train.csv')\n\n# train_dataset_info = []\n# for name, labels in zip(data['Id'], data['Target'].str.split(' ')):\n#     train_dataset_info.append({\n#         'path':os.path.join(path_to_train, name),\n#         'labels':np.array([int(label) for label in labels])})\n# train_dataset_info = np.array(train_dataset_info)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5a22490bd981772f66776868d52a667718380b3d"},"cell_type":"code","source":"def getTrainDataset():\n    \n    path_to_train = DIR + '/train/'\n    data = pd.read_csv(DIR + '/train.csv')\n\n    paths = []\n    labels = []\n    \n    for name, lbl in zip(data['Id'], data['Target'].str.split(' ')):\n        y = np.zeros(28)\n        for key in lbl:\n            y[int(key)] = 1\n        paths.append(os.path.join(path_to_train, name))\n        labels.append(y)\n\n    return np.array(paths), np.array(labels)\n\ndef getTestDataset():\n    \n    path_to_test = DIR + '/test/'\n    data = pd.read_csv(DIR + '/sample_submission.csv')\n\n    paths = []\n    labels = []\n    \n    for name in data['Id']:\n        y = np.ones(28)\n        paths.append(os.path.join(path_to_test, name))\n        labels.append(y)\n\n    return np.array(paths), np.array(labels)\npaths, labels = getTrainDataset()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"19a4d4d6e1364825c338f6cfe9f5ce0db281be53"},"cell_type":"code","source":"# credits: https://github.com/keras-team/keras/blob/master/keras/utils/data_utils.py#L302\n# credits: https://stanford.edu/~shervine/blog/keras-how-to-generate-data-on-the-fly\nfrom random import randint\nclass ProteinDataGenerator(keras.utils.Sequence):\n            \n    def __init__(self, paths, labels, batch_size, shape, channels = [], shuffle = False, use_cache = False, augmentor = False):\n        self.paths, self.labels = paths, labels\n        self.batch_size = batch_size\n        self.shape = shape\n        self.shuffle = shuffle\n        self.use_cache = use_cache\n        self.channels = channels\n        self.augmentor = augmentor\n        self.clahe = cv2.createCLAHE()\n        if use_cache == True:\n            self.cache = np.zeros((paths.shape[0], shape[0], shape[1], len(channels)))\n            self.is_cached = np.zeros((paths.shape[0]))\n        self.on_epoch_end()\n    \n    def __len__(self):\n        return int(np.ceil(len(self.paths) / float(self.batch_size)))\n    \n    def __getitem__(self, idx):\n        indexes = self.indexes[idx * self.batch_size : (idx+1) * self.batch_size]\n\n        paths = self.paths[indexes]\n        X = np.zeros((paths.shape[0], self.shape[0], self.shape[1], len(self.channels)))\n        # Generate data\n        if self.use_cache == True:\n            X = self.cache[indexes]\n            for i, path in enumerate(paths[np.where(self.is_cached[indexes] == 0)]):\n                image = self.__load_image(path)\n                self.is_cached[indexes[i]] = 1\n                self.cache[indexes[i]] = image\n                X[i] = image\n        else:\n            for i, path in enumerate(paths):\n                X[i] = self.__load_image(path)\n\n        y = self.labels[indexes]\n        \n        return X, y\n    \n    def on_epoch_end(self):\n        \n        # Updates indexes after each epoch\n        self.indexes = np.arange(len(self.paths))\n        if self.shuffle == True:\n            np.random.shuffle(self.indexes)\n\n    def __iter__(self):\n        \"\"\"Create a generator that iterate over the Sequence.\"\"\"\n        for item in (self[i] for i in range(len(self))):\n            if self.augmentor == True:\n                item = self.augment(item)\n            yield item\n            \n    def __load_image(self, path):\n        images = []\n        for channel in self.channels:\n            im = np.array(Image.open(path + '_' + channel + '.png'))\n            \n#             im = clahe.apply(im)\n            images.append(im)\n            \n        if len(self.channels) >= 2:\n            im = np.stack((\n                images\n            ), -1)\n            im = cv2.resize(im, (SIZE,SIZE))\n            im = np.divide(im, 255)\n\n        else:\n            im = images[0]\n            im = cv2.resize(im, (SIZE,SIZE))\n            im = np.divide(im, 255)\n            im = np.expand_dims(im, 2)\n        return im\n    def augment(self, image):\n        if randint(0,1) == 1:\n            augment_img = iaa.Sequential([\n                iaa.OneOf([\n                    iaa.Fliplr(0.5), # horizontal flips\n                    iaa.Flipud(0.5), # horizontal flips\n                    iaa.Crop(percent=(0, 0.1)), # random crops\n                    # Small gaussian blur with random sigma between 0 and 0.5.\n                    # But we only blur about 50% of all images.\n                    iaa.Sometimes(0.5,\n                        iaa.GaussianBlur(sigma=(0, 0.5))\n                    ),\n                    # Make some images brighter and some darker.\n                    # In 20% of all cases, we sample the multiplier once per channel,\n                    # which can end up changing the color of the images.\n                    iaa.Multiply((0.8, 1.2), per_channel=0.2),\n                    # Apply affine transformations to each image.\n                    # Scale/zoom them, translate/move them, rotate them and shear them.\n                    iaa.Affine(\n                        scale={\"x\": (0.9, 1.1), \"y\": (0.9, 1.1)},\n                        translate_percent={\"x\": (-0.1, 0.1), \"y\": (-0.1, 0.1)},\n                        rotate=(-180, 180),\n                        shear=(-4, 4)\n                    )\n                ])], random_order=True)\n\n\n            image_aug = augment_img.augment_image(image)\n            return image_aug\n        else:\n            return image\n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"4692eb5b10c2f52a42deafc11374937e1ad272de"},"cell_type":"code","source":"SHAPE = (299, 299, 4)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ce6689de82e28bead3e82e331b67802c5c73d189"},"cell_type":"code","source":"# channels = [\"red\", \"green\", \"blue\"]\n# for path in paths[0:10]:\n#     images = []\n#     for channel in channels:\n#         im = np.array(Image.open(path + '_' + channel + '.png'))\n# #         im = cv2.equalizeHist(im)\n#         clahe = cv2.createCLAHE()\n#         im = clahe.apply(im)\n# #         plt.imshow(im)\n#         images.append(im)\n\n#     if len(channels) >= 2:\n#         im = np.stack((\n#             images\n#         ), -1)\n#         im = cv2.resize(im, (SIZE,SIZE))\n#         im = np.divide(im, 255)\n        \n        \n#     else:\n#         im = images[0]\n#         im = cv2.resize(im, (SIZE,SIZE))\n#         im = np.divide(im, 255)\n#         im = np.expand_dims(im, 2)\n#     plt.imshow(augment(im))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ef7e10c56fb4274c2a8a122ece4586f613c56771"},"cell_type":"code","source":"\n# class data_generator:\n    \n#     def create_train(dataset_info, batch_size, shape, augument=True):\n#         assert shape[2] == 3\n#         while True:\n#             dataset_info = shuffle(dataset_info)\n#             for start in range(0, len(dataset_info), batch_size):\n#                 end = min(start + batch_size, len(dataset_info))\n#                 batch_images = []\n#                 X_train_batch = dataset_info[start:end]\n#                 batch_labels = np.zeros((len(X_train_batch), 28))\n#                 for i in range(len(X_train_batch)):\n#                     image = data_generator.load_image(\n#                         X_train_batch[i]['path'], shape)   \n#                     if augument:\n#                         image = data_generator.augment(image)\n#                     batch_images.append(image/255.)\n#                     batch_labels[i][X_train_batch[i]['labels']] = 1\n#                 yield np.array(batch_images, np.float32), batch_labels\n\n#     def load_image(path, shape):\n#         image_red_ch = Image.open(path+'_red.png')\n#         image_yellow_ch = Image.open(path+'_yellow.png')\n#         image_green_ch = Image.open(path+'_green.png')\n#         image_blue_ch = Image.open(path+'_blue.png')\n#         image = np.stack((\n#         np.array(image_red_ch), \n#         np.array(image_green_ch), \n#         np.array(image_blue_ch)), -1)\n#         image = cv2.resize(image, (shape[0], shape[1]))\n#         return image\n\n#     def augment(image):\n#         augment_img = iaa.Sequential([\n#             iaa.OneOf([\n#                 iaa.Affine(rotate=0),\n#                 iaa.Affine(rotate=90),\n#                 iaa.Affine(rotate=180),\n#                 iaa.Affine(rotate=270),\n#                 iaa.Fliplr(0.5),\n#                 iaa.Flipud(0.5),\n#             ])], random_order=True)\n\n#         image_aug = augment_img.augment_image(image)\n#         return image_aug","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"268da56908b0cc2cb7ce09f9b4d527b6e39d5c42"},"cell_type":"code","source":"from keras.preprocessing.image import ImageDataGenerator\nfrom keras.models import Sequential, load_model\nfrom keras.layers import Activation, Dropout, Flatten, Dense, GlobalMaxPooling2D, BatchNormalization, Input, Conv2D, MaxPooling2D\nfrom keras.applications.inception_v3 import InceptionV3\nfrom keras.callbacks import ModelCheckpoint\nfrom keras import metrics\nfrom keras.optimizers import Adam \nfrom keras import backend as K\nimport keras\nfrom keras.models import Model\nfrom keras.utils import multi_gpu_model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"aa85354448c686edb78403a94f98c8c94989d175"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"aaac4ad1c3dce72722594efb5f128e2e7163c4a6"},"cell_type":"code","source":"def create_model(input_shape, n_out, channels):\n    input_tensor = Input(shape=(299,299,len(channels)))\n\n    base_model = InceptionV3(include_top=False,\n                   weights='imagenet',\n                   input_shape=(299,299,3)\n                            )\n    bn = BatchNormalization()(input_tensor)\n    x = Conv2D(3, kernel_size=(1,1), activation='relu', padding = \"same\")(bn)\n    x = base_model(x)\n    bn = BatchNormalization()(x)\n    x = Conv2D(128, kernel_size=(1,1), activation='relu')(x)\n    x = Flatten()(x)\n    x = Dropout(0.5)(x)\n    x = Dense(1024, activation='relu')(x)\n    x = Dropout(0.5)(x)\n#     output = Dense(n_out, activation='sigmoid')(x)\n    output = Dense(n_out, activation='sigmoid')(x)\n    model = Model(input_tensor, output)\n    \n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"66d746e6fd138c41a5bda8c689cf1cbf15c0524a"},"cell_type":"code","source":"def simple_model(input_shape, n_out, channels):\n    input_tensor = Input(shape=(299,299,len(channels)))\n    bn = BatchNormalization()(input_tensor)\n    x = Conv2D(8, kernel_size=(3,3), activation='relu', padding = \"same\")(bn)\n    x = Conv2D(8, kernel_size=(3,3), activation='relu', padding = \"same\")(x)\n    x = MaxPooling2D(pool_size = (2,2))(x)\n    x = Conv2D(16, kernel_size=(3,3), activation='relu', padding = \"same\")(x)\n    x = Conv2D(16, kernel_size=(3,3), activation='relu', padding = \"same\")(x)\n    x = MaxPooling2D(pool_size = (2,2))(x)\n    x = Conv2D(32, kernel_size=(3,3), activation='relu', padding = \"same\")(x)\n    x = Conv2D(32, kernel_size=(3,3), activation='relu', padding = \"same\")(x)\n    x = MaxPooling2D(pool_size = (2,2))(x)\n    x = Conv2D(64, kernel_size=(3,3), activation='relu', padding = \"same\")(x)\n    x = Conv2D(64, kernel_size=(3,3), activation='relu', padding = \"same\")(x)\n    x = MaxPooling2D(pool_size = (2,2))(x)\n    x = Conv2D(128, kernel_size=(3,3), activation='relu', padding = \"same\")(x)\n    x = Conv2D(128, kernel_size=(3,3), activation='relu', padding = \"same\")(x)\n    x = MaxPooling2D(pool_size = (2,2))(x)\n    x = Conv2D(256, kernel_size=(3,3), activation='relu', padding = \"valid\")(x)\n    x = Conv2D(256, kernel_size=(3,3), activation='relu', padding = \"valid\")(x)\n    x = MaxPooling2D(pool_size = (2,2))(x)\n    x = Flatten()(x)\n    x = Dropout(0.5)(x)\n    x = Dense(256, activation='relu')(x)\n    x = Dropout(0.5)(x)\n#     output = Dense(n_out, activation='sigmoid')(x)\n    output = Dense(n_out, activation=\"sigmoid\")(x)\n    model = Model(input_tensor, output)\n    \n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"df003d1d1058d3dee2e227338e64a3e6604e25c4"},"cell_type":"code","source":"def f1(y_true, y_pred):\n    #y_pred = K.round(y_pred)\n    y_pred = K.cast(K.greater(K.clip(y_pred, 0, 1), THRESHOLD), K.floatx())\n    tp = K.sum(K.cast(y_true*y_pred, 'float'), axis=0)\n    tn = K.sum(K.cast((1-y_true)*(1-y_pred), 'float'), axis=0)\n    fp = K.sum(K.cast((1-y_true)*y_pred, 'float'), axis=0)\n    fn = K.sum(K.cast(y_true*(1-y_pred), 'float'), axis=0)\n\n    p = tp / (tp + fp + K.epsilon())\n    r = tp / (tp + fn + K.epsilon())\n\n    f1 = 2*p*r / (p+r+K.epsilon())\n    f1 = tf.where(tf.is_nan(f1), tf.zeros_like(f1), f1)\n    return K.mean(f1)\ndef f1_loss(y_true, y_pred):\n    \n    #y_pred = K.cast(K.greater(K.clip(y_pred, 0, 1), THRESHOLD), K.floatx())\n    tp = K.sum(K.cast(y_true*y_pred, 'float'), axis=0)\n    tn = K.sum(K.cast((1-y_true)*(1-y_pred), 'float'), axis=0)\n    fp = K.sum(K.cast((1-y_true)*y_pred, 'float'), axis=0)\n    fn = K.sum(K.cast(y_true*(1-y_pred), 'float'), axis=0)\n\n    p = tp / (tp + fp + K.epsilon())\n    r = tp / (tp + fn + K.epsilon())\n\n    f1 = 2*p*r / (p+r+K.epsilon())\n    f1 = tf.where(tf.is_nan(f1), tf.zeros_like(f1), f1)\n    return 1-K.mean(f1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3c4d8f8faea5dc3592ced67de01e29458c0044ca"},"cell_type":"code","source":"# create callbacks list\nfrom keras.callbacks import ModelCheckpoint, LearningRateScheduler, EarlyStopping, ReduceLROnPlateau\nfrom sklearn.model_selection import train_test_split\n\nepochs = 10; batch_size = 128;VAL_RATIO = .1;DEBUG = False\n# split data into train, valid\npaths, labels = getTrainDataset()\n\n# divide to \nkeys = np.arange(paths.shape[0], dtype=np.int)  \nnp.random.seed(SEED)\nnp.random.shuffle(keys)\nlastTrainIndex = int((1-VAL_RATIO) * paths.shape[0])\n\nif DEBUG == True:  # use only small subset for debugging, Kaggle's RAM is limited\n    pathsTrain = paths[0:256]\n    labelsTrain = labels[0:256]\n    pathsVal = paths[lastTrainIndex:lastTrainIndex+256]\n    labelsVal = labels[lastTrainIndex:lastTrainIndex+256]\n    use_cache = True\nelse:\n    pathsTrain = paths[0:lastTrainIndex]\n    labelsTrain = labels[0:lastTrainIndex]\n    pathsVal = paths[lastTrainIndex:]\n    labelsVal = labels[lastTrainIndex:]\n    use_cache = False\n\nprint(paths.shape, labels.shape)\nprint(pathsTrain.shape, labelsTrain.shape, pathsVal.shape, labelsVal.shape)\nuse_cache = True\nchannels = [\"green\", \"blue\", \"red\", \"yellow\"]\ntg = ProteinDataGenerator(pathsTrain, labelsTrain, batch_size, SHAPE, channels, use_cache=False, augmentor = False)\nvg = ProteinDataGenerator(pathsVal, labelsVal, batch_size, SHAPE, channels, use_cache=False, augmentor = False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d89378d30de38288610c2677d5bec2ed7896bb01"},"cell_type":"code","source":"# create train and valid datagens\n# train_generator = data_generator.create_train(\n#     train_dataset_info[train_indexes], batch_size, (SIZE,SIZE,3), augument=True)\n# validation_generator = data_generator.create_train(\n#     train_dataset_info[valid_indexes], 32, (SIZE,SIZE,3), augument=False)\nlen(channels)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ed5e6ce1bf3e9a874e47637da09784573bf16448"},"cell_type":"code","source":"checkpoint = ModelCheckpoint('../working/InceptionV3.h5', monitor='val_f1', verbose=1, \n                             save_best_only=True, mode='max', save_weights_only = False)\nreduceLROnPlat = ReduceLROnPlateau(monitor='val_f1', factor=0.5, patience=10, \n                                   verbose=1, mode='max', epsilon=0.0001)\ncallbacks_list = [checkpoint, reduceLROnPlat]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a1c0652801a28a070d91ac24dea3d23e12e09ca7"},"cell_type":"code","source":"def focal_loss(gamma=2., alpha=.25):\n    def focal_loss_fixed(y_true, y_pred):\n        pt_1 = tf.where(tf.equal(y_true, 1), y_pred, tf.ones_like(y_pred))\n        pt_0 = tf.where(tf.equal(y_true, 0), y_pred, tf.zeros_like(y_pred))\n\n        pt_1 = K.clip(pt_1, 1e-3, .999)\n        pt_0 = K.clip(pt_0, 1e-3, .999)\n\n        return -K.sum(alpha * K.pow(1. - pt_1, gamma) * K.log(pt_1))-K.sum((1-alpha) * K.pow( pt_0, gamma) * K.log(1. - pt_0))\n    return focal_loss_fixed\ndef KerasFocalLoss(target, input):\n    \n    gamma = 2.\n    input = tf.cast(input, tf.float32)\n    \n    max_val = K.clip(-input, 0, 1)\n    loss = input - input * target + max_val + K.log(K.exp(-max_val) + K.exp(-input - max_val))\n    invprobs = tf.log_sigmoid(-input * (target * 2.0 - 1.0))\n    loss = K.exp(invprobs * gamma) * loss\n    \n    return K.mean(K.sum(loss, axis=1))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a73884dbcce60fb89d9835543329250dd7f41919"},"cell_type":"code","source":"len([color])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"dec9b69ad9774787812a16f50e575fcfb55bccc1"},"cell_type":"code","source":"\"\".join(colors)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"711359c8a0e3b4c4207519968efd1192d2cf834a"},"cell_type":"code","source":"history = {}\ncolorslist = [\"green\", \"red\", \"blue\", \"yellow\"]\nfrom itertools import combinations\ncomb = combinations( colorslist, 2)\nfor colors in comb:\n    colorset = \"\".join(colors)\n    SHAPE = (299,299, len([colors]))\n    checkpointer = ModelCheckpoint('../working/' + colorset + '.model', verbose=2, save_best_only=True)\n    model = simple_model(\n    input_shape=(299,299,len(colors)), \n    n_out=28, channels = colors)\n\n    model.compile(\n        loss='binary_crossentropy', \n        optimizer='adam',\n        metrics=['acc', f1])\n\n    model.summary()\n    tg = ProteinDataGenerator(pathsTrain, labelsTrain, batch_size, SHAPE, colors, use_cache=False, augmentor = False)\n    vg = ProteinDataGenerator(pathsVal, labelsVal, batch_size, SHAPE, colors, use_cache=False, augmentor = False)\n    # train model\n    history[colorset] = model.fit_generator(\n        tg,\n        steps_per_epoch=(len(pathsTrain)//batch_size)/8,\n        validation_data=vg,\n        validation_steps=(len(pathsVal)//batch_size)/8,\n        epochs=5, \n        verbose=1,\n        callbacks=[checkpointer])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3973b261e80054b701c1d5dd55a6d5787003cb5a"},"cell_type":"code","source":"comb = combinations( ['red', 'green', 'blue', 'yellow'], 2)\nfor colors in comb:\n    colorset = \"\".join(colors)\n    history1 = history[colorset]\n    fig, ax = plt.subplots(1, 3, figsize=(15,5))\n    ax[0].set_title(colorset + 'loss')\n    ax[0].plot(history1.epoch, history1.history[\"loss\"], label=\"Train loss\")\n    ax[0].plot(history1.epoch, history1.history[\"val_loss\"], label=\"Validation loss\")\n    ax[1].set_title('acc')\n    ax[1].plot(history1.epoch, history1.history[\"acc\"], label=\"Train acc\")\n    ax[1].plot(history1.epoch, history1.history[\"val_acc\"], label=\"Validation acc\")\n    ax[2].set_title('F1')\n    ax[2].plot(history1.epoch, history1.history[\"f1\"], label=\"Train F1\")\n    ax[2].plot(history1.epoch, history1.history[\"val_f1\"], label=\"Validation F1\")\n    ax[0].legend()\n    _ = ax[1].legend()","execution_count":null,"outputs":[]},{"metadata":{"trusted":false,"_uuid":"54da0cde70b1341842d710fe2ec6bdab57e16824"},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.6.6"}},"nbformat":4,"nbformat_minor":1}