{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nimport os\nprint(os.listdir(\"../input\"))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nfrom PIL import Image\nfrom zipfile import ZipFile\nimport matplotlib.pyplot as plt\nimport cv2\nfrom imgaug import augmenters as iaa\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d512398f4bec8d381707802eef91c7f37602a691"},"cell_type":"code","source":"os.listdir('../input')\nPATH_BASE = '../input/'\nTRAIN_BASE = 'human-protein-atlas-image-classification/'\nMODEL_BASE = 'inceptionresnetv2-pre-train-model/'\nPATH_TRAIN = PATH_BASE+TRAIN_BASE+'train/'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3dd480d82d43108ac3e1e61d31d31b6ca294a823"},"cell_type":"code","source":"raw_labels = pd.read_csv(PATH_BASE+TRAIN_BASE+'train.csv')\ndata_names = os.listdir(PATH_TRAIN)\n#extract label names and labels array[{name: ,label:}]\nlabels = []\nfor name, label in zip(raw_labels['Id'],raw_labels['Target'].str.split(\" \")):\n    labels.append({\n        'name':name,\n        'label':label\n    })\n\nfrom sklearn.model_selection import train_test_split\ntrain_idx, test_idx = train_test_split(labels, test_size=0.2)\nprint('train: ' + str(len(train_idx)) + '\\n'+ 'validation: ' + str(len(test_idx)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e2ad4127435d793888f7963f951e239295bc1a8b"},"cell_type":"code","source":"#Define data_generator\n\nclass data_generator:\n    \n    def __init__(self):\n        pass\n    \n    def batch_train(self, idx, batch_size, shape, augment=True):\n        #extract eandom name and corresponding label\n        while True:\n            name_list = []\n            label_list = []\n\n            for n in np.random.choice(idx, batch_size):\n                name_list.append(n['name'])\n                int_label = list(map(int, n['label']))\n                label_list.append(int_label)\n\n            #batch_images = 提取images存成array, shape=(batch_size, shpae[0], shape[1], shpae[2]) = batch_images(能夠改名字嗎?例如trainX之類的)\n            batch_images = np.zeros((batch_size, shape[0], shape[1], shape[2]))\n            i = 0\n            for name in name_list:\n                image = self.load_img(name, shape)\n                if augment:\n                    image = self.augment(image)\n                batch_images[i] = image\n                i+=1\n\n            #batch_labels = 提取labels轉換為multiple one-hot, shape=(batch_size, 28)\n            batch_labels = np.zeros((batch_size, 28))\n            j = 0\n            for label in label_list:\n                batch_labels[j][label] = 1\n                j+=1\n\n            yield batch_images, batch_labels\n        \n    def load_img(self, name, shape):\n        R = np.array(Image.open(PATH_TRAIN+name+'_red.png'))\n        G = np.array(Image.open(PATH_TRAIN+name+'_green.png'))\n        B = np.array(Image.open(PATH_TRAIN+name+'_blue.png'))\n        Y = np.array(Image.open(PATH_TRAIN+name+'_yellow.png'))\n        BY = (B+Y)\n        BY[BY>255] = 255\n        image = np.stack((R, G, BY) ,axis=-1)\n        image = cv2.resize(image, (shape[0], shape[1]))\n        image = np.divide(image, 255)\n        return image\n    \n    def augment(self, image):\n        aug = iaa.OneOf([\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        ])\n        image = aug.augment_image(image)\n        return image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"86b3ade5e1baa609259cdb264da7a2d7af566f78"},"cell_type":"code","source":"#test block\ngenerator_test = data_generator()\n#np.random.seed(43) #just for test purpose\nK0 = generator_test.batch_train(train_idx, 1,(500,500,3),True)\na,b = next(K0)\nA = np.squeeze(a)\nplt.figure(figsize=(20,10))\nplt.imshow(A)\nb","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2e30a7411f47ab0aadf41796f1e8ba937ec8787c"},"cell_type":"code","source":"from keras import applications\nfrom keras.models import Model, Sequential, load_model\nfrom keras.layers import Input, Dense, Conv2D, MaxPooling2D, Activation, Flatten, Dropout, BatchNormalization\nfrom keras.callbacks import ModelCheckpoint\nfrom keras.optimizers import Adam, SGD\nimport tensorflow as tf\nimport keras.backend as K\nK.clear_session()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c7177377df5df9783bdb6c4728ede93ebb2e60e7"},"cell_type":"code","source":"SHAPE = (299,299,3)\nBATCH_SIZE = 10\n\ndef f1(y_true, y_pred):\n    tp = K.sum(K.cast(y_true*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)\n\ndef show_history(history):\n    fig, ax = plt.subplots(1, 3, figsize=(15,5))\n    ax[0].set_title('loss')\n    ax[0].plot(history.epoch, history.history[\"loss\"], label=\"Train loss\")\n    ax[0].plot(history.epoch, history.history[\"val_loss\"], label=\"Validation loss\")\n    ax[1].set_title('f1')\n    ax[1].plot(history.epoch, history.history[\"f1\"], label=\"Train f1\")\n    ax[1].plot(history.epoch, history.history[\"val_f1\"], label=\"Validation f1\")\n    ax[2].set_title('acc')\n    ax[2].plot(history.epoch, history.history[\"acc\"], label=\"Train acc\")\n    ax[2].plot(history.epoch, history.history[\"val_acc\"], label=\"Validation acc\")\n    ax[0].legend()\n    ax[1].legend()\n    ax[2].legend()\n    \ndef f1_loss(y_true, y_pred):\n    K_epsilon = K.epsilon()\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)\n\ndef binary_focal_loss(y_true, y_pred, gamma=2.0, alpha=0.25):\n    \"\"\"\n    Implementation of Focal Loss from the paper in multiclass classification\n    Formula:\n        loss = -alpha_t*((1-p_t)^gamma)*log(p_t)\n        \n        p_t = y_pred, if y_true = 1\n        p_t = 1-y_pred, otherwise\n        \n        alpha_t = alpha, if y_true=1\n        alpha_t = 1-alpha, otherwise\n        \n        cross_entropy = -log(p_t)\n    Parameters:\n        alpha -- the same as wighting factor in balanced cross entropy\n        gamma -- focusing parameter for modulating factor (1-p)\n    Default value:\n        gamma -- 2.0 as mentioned in the paper\n        alpha -- 0.25 as mentioned in the paper\n    \"\"\"\n\n    # Define epsilon so that the backpropagation will not result in NaN\n    # for 0 divisor case\n    epsilon = K.epsilon()\n    # Add the epsilon to prediction value\n    #y_pred = y_pred + epsilon\n    # Clip the prediciton value\n    y_pred = K.clip(y_pred, epsilon, 1.0-epsilon)\n    # Calculate p_t\n    p_t = tf.where(K.equal(y_true, 1), y_pred, 1-y_pred)\n    # Calculate alpha_t\n    alpha_factor = K.ones_like(y_true)*alpha\n    alpha_t = tf.where(K.equal(y_true, 1), alpha_factor, 1-alpha_factor)\n    # Calculate cross entropy\n    cross_entropy = -K.log(p_t)\n    weight = alpha_t * K.pow((1-p_t), gamma)\n    # Calculate focal loss\n    loss = weight * cross_entropy\n    # Sum the losses in mini_batch\n    loss = K.sum(loss, axis=1)\n    \n    return loss","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"4248f34c866b3074eb459876534d4fce209b767d"},"cell_type":"code","source":"#Use this cell to read model & weight\nmodel = load_model(PATH_BASE+MODEL_BASE+'fine_tune_weights.hdf5', custom_objects={'f1':f1})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a5b5158a9ce9ad1902b13882b2b8245e25ab44a3"},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1512b8b7b0ce3b0675710e5e71e0d4684200dcf7"},"cell_type":"code","source":"for layer in model.layers[:780]:\n    layer.trainable =False\nfor layer in model.layers[:]:\n    layer.trainable =True\nmodel.layers[167].trainable","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ab93c88c242201414178ee9fd762e56f7e0c1a85"},"cell_type":"code","source":"model.compile(\n    loss=[binary_focal_loss],  \n    optimizer=Adam(1e-4),\n    metrics=['acc', f1])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f88b296c679f6ed8fc3237c59793bd35cb325cbd"},"cell_type":"code","source":"checkpointer = ModelCheckpoint('fine_tune_weights.hdf5', verbose=2, monitor='val_acc', save_best_only=True)\n\ngenerator = data_generator()\ntrain_generator = generator.batch_train(train_idx, BATCH_SIZE, SHAPE, augment=True)\nvalidation_generator = generator.batch_train(test_idx, 256, SHAPE, augment=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ba328b8aa7d75041ed26f9dc07dc8b65c7139f19"},"cell_type":"code","source":"history = model.fit_generator(\n    train_generator,\n    steps_per_epoch=100,\n    validation_data=next(validation_generator),\n    epochs=120, \n    verbose=1,\n    callbacks=[checkpointer])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ad78f237ee2e17ff0d4de8c44a561b86c49a2470"},"cell_type":"code","source":"submit = pd.read_csv(PATH_BASE+TRAIN_BASE+'sample_submission.csv')\nfrom tqdm import tqdm","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"bb09ee822546021376b859e42be67149b847df10"},"cell_type":"code","source":"%%time\nPATH_TRAIN = PATH_BASE+TRAIN_BASE+'test/'\ngenerator = data_generator()\npredicted = []\n\nfor name in tqdm(submit['Id']):\n    #path = os.path.join('../input/test/', name)\n    image = generator.load_img(name, SHAPE)\n    score_predict = model.predict(image[np.newaxis,:])[0]\n    label_predict = np.arange(28)[score_predict>=0.2]\n    str_predict_label = ' '.join(str(l) for l in label_predict)\n    predicted.append(str_predict_label)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"fe851df2699669e4057bf4450c54c30713f6fad0"},"cell_type":"code","source":"submit['Predicted'] = predicted\nsubmit.to_csv('focal_loss_with_pre_train_V2_submission.csv', index=False)","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}