{"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 all files under the input directory\n\n# import os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"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\nimport imgaug as ia\nfrom tqdm import tqdm\nimport PIL\nfrom PIL import Image, ImageOps\nimport cv2\nfrom sklearn.utils import class_weight, shuffle\nfrom keras.losses import binary_crossentropy\nfrom keras.applications.resnet50 import preprocess_input\nfrom keras.preprocessing.image import ImageDataGenerator\nimport keras.backend as K\nimport tensorflow as tf\nfrom sklearn.metrics import f1_score, fbeta_score, cohen_kappa_score, confusion_matrix, classification_report\nfrom keras.utils import Sequence\nfrom keras.utils import to_categorical\nfrom keras import layers\nfrom keras import models\nfrom sklearn.model_selection import train_test_split\nfrom keras.callbacks import ModelCheckpoint\nfrom keras import regularizers, optimizers\nfrom keras.callbacks import (ModelCheckpoint, LearningRateScheduler,\n                             EarlyStopping, ReduceLROnPlateau,CSVLogger)\nfrom keras.layers import Dropout\nfrom keras.utils import np_utils\nfrom keras.losses import binary_crossentropy, categorical_crossentropy\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")\n\nfrom keras import backend as K\nK.tensorflow_backend._get_available_gpus()\n\nIMG_SIZE = 256\nNUM_CLASSES = 5\nSEED = 26","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_dir = os.path.join('/kaggle/input','train_images/')\ndf = pd.read_csv(os.path.join('/kaggle/input', 'train.csv'))\ndf['path'] = df['id_code'].map(lambda x: os.path.join(train_dir,'{}.png'.format(x)))\n# df = df.drop(columns=['id_code'])\ndf = df.sample(frac=1).reset_index(drop=True) #shuffle dataframe\ndf.head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_bin_train = df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_bin_train['diagnosis'] = df_bin_train['diagnosis'].map({0:0, 1: 1, 2: 1, 3: 1, 4: 1})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_bin_train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"(train, valid) = train_test_split(df_bin_train, test_size=549, random_state=SEED)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(train)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(valid)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_dir = os.path.join('/kaggle/input','test_images/')\ntest_df = pd.read_csv(os.path.join('/kaggle/input', 'test.csv'))\ntest_df['path'] = test_df['id_code'].map(lambda x: os.path.join(test_dir,'{}.png'.format(x)))\n# test_df = test_df.drop(columns=['id_code'])\n# test_df = test_df.sample(frac=1).reset_index(drop=True) #shuffle dataframe\ntest_df.head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# cast 'diagnosis' as type string\ndf_bin_train['diagnosis'] = df_bin_train['diagnosis'].astype('str')\ndf_bin_train['diagnosis'].value_counts(normalize=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train['diagnosis'] = train['diagnosis'].astype('str')\nvalid['diagnosis'] = valid['diagnosis'].astype('str')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_bin_train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# img = cv2.imread(image_path)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def display_samples(df, columns=4, rows=3):\n    fig=plt.figure(figsize=(5*columns, 4*rows))\n\n    for i in range(columns*rows):\n        image_path = df.loc[i,'path']\n        image_id = df.loc[i,'diagnosis']\n        img = cv2.imread(image_path)\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        \n        fig.add_subplot(rows, columns, i+1)\n        plt.title(image_id)\n        plt.imshow(img)\n    \n    plt.tight_layout()\n\ndisplay_samples(df)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"total_count = df_bin_train['diagnosis'].sum()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_bin_train['diagnosis'].unique()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# class_weight = class_weight.compute_class_weight('balanced',['0', '1', '2', '3', '4'],df['diagnosis'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# class_weight = {0: -0.601, 1: -0.392, 2: -.833, 3: 0.164, 4: 1.662}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# class_weight = {0: 0.205913, 1: 0.130705, 2: 0.568465, 3: 0.052703, 4: 0.080557}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"datagen=ImageDataGenerator(featurewise_center=True,\n                           featurewise_std_normalization=True,\n                           rotation_range=20,\n                           width_shift_range=0.1,\n                           height_shift_range=0.1,\n                           shear_range=16,\n                           zoom_range=[0.9, 1.1],\n                           fill_mode=\"constant\",\n                           cval=255,\n                           horizontal_flip=True,\n                           vertical_flip=True,\n                           rescale=1./255.)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"datagen2 = datagen=ImageDataGenerator(featurewise_center=True,\n                           featurewise_std_normalization=True,\n                           rotation_range=20,\n                           width_shift_range=0.1,\n                           height_shift_range=0.1,\n                           shear_range=16,\n                           zoom_range=[0.9, 1.1],\n                           fill_mode=\"constant\",\n                           cval=255,\n                           horizontal_flip=True,\n                           vertical_flip=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# seq.augment_image(datagen)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_generator = datagen.flow_from_dataframe(\n                                            dataframe=train,\n                                            directory=None,\n                                            x_col=\"path\",\n                                            y_col=\"diagnosis\",\n#                                             subset=\"training\",\n                                            batch_size=32,\n                                            seed=SEED,\n                                            shuffle=True,\n                                            class_mode=\"binary\",\n                                            interpolation=\"bilinear\",\n                                            target_size=(IMG_SIZE, IMG_SIZE))\nvalid_generator = datagen2.flow_from_dataframe(\n                                            dataframe=valid,\n                                            directory=None,\n                                            x_col=\"path\",\n                                            y_col=\"diagnosis\",\n#                                             subset=\"validation\",\n                                            batch_size=1,\n                                            seed=SEED,\n                                            shuffle=False,\n                                            class_mode=\"binary\",\n                                            interpolation=\"bilinear\",\n                                            target_size=(IMG_SIZE, IMG_SIZE))\ntest_datagen=ImageDataGenerator(rescale=1./255.)\ntest_generator=test_datagen.flow_from_dataframe(\n                                            dataframe=test_df,\n                                            directory=None,\n                                            x_col=\"path\",\n                                            y_col=None,\n                                            batch_size=32,\n                                            seed=SEED,\n                                            shuffle=False,\n                                            class_mode=None,\n                                            target_size=(IMG_SIZE, IMG_SIZE))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"y_test = np_utils.to_categorical(valid_generator.classes, 2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(y_test)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"y_test","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(valid_generator.classes)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# method to define kaggle quadratic weighted kappa score\n\nfrom keras.callbacks import Callback\nclass QWKEvaluation(Callback):\n    def __init__(self, validation_data=(), batch_size=64, interval=1):\n        super(Callback, self).__init__()\n\n        self.interval = interval\n        self.batch_size = batch_size\n        self.valid_generator, self.y_val = validation_data\n        self.history = []\n\n    def on_epoch_end(self, epoch, logs={}):\n        if epoch % self.interval == 0:\n            y_pred = self.model.predict_generator(generator=self.valid_generator,\n#                                                   steps=np.ceil(float(len(self.y_val)) / float(self.batch_size)),\n                                                  steps=18,\n                                                  workers=1, use_multiprocessing=False,\n                                                  verbose=1)\n            def flatten(y):\n                return np.argmax(y, axis=1).reshape(-1)\n            try:\n                score = cohen_kappa_score(self.y_val,\n                                          flatten(y_pred),\n                                          labels=[0,1,2,3,4],\n                                          weights='quadratic')\n                \n                print(\"\\n epoch: %d - QWK_score: %.6f \\n\" % (epoch+1, score))\n                self.history.append(score)\n                if score >= max(self.history):\n                    print('saving checkpoint: ', score)\n                    self.model.save('../working/densenet_bestqwk.h5')\n            except:\n                pass\n\nqwk = QWKEvaluation(validation_data=(valid_generator, valid_generator.classes), batch_size=64, interval=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# reference link: https://www.kaggle.com/christofhenkel/weighted-kappa-loss-for-keras-tensorflow\ndef kappa_loss(y_true, y_pred, y_pow=2, eps=1e-12, N=5, bsize=32, name='kappa'):\n    \"\"\"A continuous differentiable approximation of discrete kappa loss.\n        Args:\n            y_pred: 2D tensor or array, [batch_size, num_classes]\n            y_true: 2D tensor or array,[batch_size, num_classes]\n            y_pow: int,  e.g. y_pow=2\n            N: typically num_classes of the model\n            bsize: batch_size of the training or validation ops\n            eps: a float, prevents divide by zero\n            name: Optional scope/name for op_scope.\n        Returns:\n            A tensor with the kappa loss.\"\"\"\n\n    with tf.name_scope(name):\n        y_true = tf.to_float(y_true)\n        repeat_op = tf.to_float(tf.tile(tf.reshape(tf.range(0, N), [N, 1]), [1, N]))\n        repeat_op_sq = tf.square((repeat_op - tf.transpose(repeat_op)))\n        weights = repeat_op_sq / tf.to_float((N - 1) ** 2)\n    \n        pred_ = y_pred ** y_pow\n        try:\n            pred_norm = pred_ / (eps + tf.reshape(tf.reduce_sum(pred_, 1), [-1, 1]))\n        except Exception:\n            pred_norm = pred_ / (eps + tf.reshape(tf.reduce_sum(pred_, 1), [bsize, 1]))\n    \n        hist_rater_a = tf.reduce_sum(pred_norm, 0)\n        hist_rater_b = tf.reduce_sum(y_true, 0)\n    \n        conf_mat = tf.matmul(tf.transpose(pred_norm), y_true)\n    \n        nom = tf.reduce_sum(weights * conf_mat)\n        denom = tf.reduce_sum(weights * tf.matmul(\n            tf.reshape(hist_rater_a, [N, 1]), tf.reshape(hist_rater_b, [1, N])) /\n                              tf.to_float(bsize))\n    \n        return nom*0.5 / (denom + eps) + categorical_crossentropy(y_true, y_pred)*0.5","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# callbacks list\n\nearly = EarlyStopping(monitor=\"val_loss\", \n                      mode=\"min\", \n                      patience=9)\ncheckpoint = ModelCheckpoint('../working/densenet_.h5', monitor='val_loss', verbose=1, \n                             save_best_only=True, mode='min', save_weights_only = True)\nreduceLROnPlat = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=4, \n                                   verbose=1, mode='auto', epsilon=0.0001)\ncsv_logger = CSVLogger(filename='../working/training_log.csv',\n                       separator=',',\n                       append=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# define metrics for model evaluation\ndef recall_m(y_true, y_pred):\n        true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))\n        possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))\n        recall = true_positives / (possible_positives + K.epsilon())\n        return recall\n\ndef precision_m(y_true, y_pred):\n        true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))\n        predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))\n        precision = true_positives / (predicted_positives + K.epsilon())\n        return precision\n\ndef f1_m(y_true, y_pred):\n    precision = precision_m(y_true, y_pred)\n    recall = recall_m(y_true, y_pred)\n    return 2*((precision*recall)/(precision+recall+K.epsilon()))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# get the step sizes\n\nSTEP_SIZE_TRAIN = train_generator.n // train_generator.batch_size\nSTEP_SIZE_VALID = valid_generator.n // valid_generator.batch_size\nSTEP_SIZE_TEST = test_generator.n // test_generator.batch_size","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# add convolutions\n\nmodel = models.Sequential()\nmodel.add(layers.Conv2D(16, (3, 3), activation='relu', input_shape=(IMG_SIZE, IMG_SIZE, 3)))\nmodel.add(layers.MaxPooling2D(2, 2))\nmodel.add(Dropout(0.25))\n\nmodel.add(layers.Conv2D(32, (3, 3), activation='relu'))\nmodel.add(layers.Conv2D(32, (3, 3), activation='relu'))\nmodel.add(layers.MaxPooling2D(2, 2))\nmodel.add(Dropout(0.25))\n\nmodel.add(layers.Conv2D(64, (3, 3), activation='relu'))\nmodel.add(layers.Conv2D(64, (3, 3), activation='relu'))\nmodel.add(layers.MaxPooling2D(2, 2))\nmodel.add(Dropout(0.4))\n\nmodel.add(layers.Conv2D(128, (3, 3), activation='relu'))\nmodel.add(layers.MaxPooling2D(2, 2))\nmodel.add(Dropout(0.4))\nmodel.add(layers.BatchNormalization())\n\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# add dense layers\n\nmodel.add(layers.Flatten()) #flatten 3D outputs to 1D\nmodel.add(layers.Dense(128, activation='relu'))\nmodel.add(Dropout(rate=0.3))\n# model.add(layers.Dense(64, activation='relu'))\n# model.add(Dropout(rate=0.5))\n# model.add(layers.Dense(32, activation='relu'))\n# model.add(Dropout(rate=0.5))\nmodel.add(layers.Dense(1, activation='sigmoid')) # 5 outputs","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.compile(optimizer='adam',\n              loss = 'binary_crossentropy',\n#               loss='categorical_crossentropy',\n#               loss=kappa_loss,\n              metrics=[\"acc\"])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"callbacks_list = [checkpoint, csv_logger, reduceLROnPlat, early]\n# callbacks_list = [checkpoint, csv_logger, reduceLROnPlat, early, qwk]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# fit the model\n# commented out code for small trial set\nhistory = model.fit_generator(generator=train_generator,\n#                               steps_per_epoch=2,\n                              steps_per_epoch=STEP_SIZE_TRAIN,\n                              validation_data=valid_generator,\n#                               validation_steps=2,\n                              validation_steps=STEP_SIZE_VALID,\n                              class_weight='balanced',\n                              epochs=30,\n                              verbose=1,\n                              callbacks=callbacks_list\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(valid_generator.filenames)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"prediction = model.predict_generator(valid_generator, steps=549, verbose=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"prediction","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pred = []\nfor i in prediction:\n    for j in i:\n        if j > 0.5:\n            pred.append(1)\n        else:\n            pred.append(0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pred","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pred = np.roll(pred, -1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# predictions = model.predict_generator(valid_generator, steps=len(valid_generator), verbose=1)        \n# predictions = np.argmax(predictions, axis=-1) #multiple categories\n\n# label_map = (train_generator.class_indices)\n# label_map = dict((v,k) for k,v in label_map.items()) #flip k,v\n# predictions = [label_map[k] for k in predictions]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# predictions","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.metrics_names","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# evaluate the model\nmodel.evaluate_generator(generator=valid_generator,\n                         steps=STEP_SIZE_TEST,\n                         verbose=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"markdown","source":"# get predictions\nSTEP_SIZE_TEST=test_generator.n//test_generator.batch_size\ntest_generator.reset()\npred=model.predict_generator(test_generator,\n                             steps=STEP_SIZE_TEST+1,\n                             verbose=1)"},{"metadata":{"trusted":true},"cell_type":"markdown","source":"predicted_class_indices=np.argmax(pred,axis=1)"},{"metadata":{"trusted":true},"cell_type":"markdown","source":"labels = (train_generator.class_indices)\nlabels = dict((v,k) for k,v in labels.items())\npredictions = [labels[k] for k in predicted_class_indices]"},{"metadata":{"trusted":true},"cell_type":"markdown","source":"id_code = test_df['id_code'].tolist()"},{"metadata":{"trusted":true},"cell_type":"markdown","source":"filenames=test_generator.filenames\nresults=pd.DataFrame({\"id_code\":id_code,\n                      \"diagnosis\":predictions})\nresults.to_csv(\"submission.csv\",index=False)"},{"metadata":{"trusted":true},"cell_type":"markdown","source":"results['diagnosis'].value_counts(normalize=True)"},{"metadata":{"trusted":true},"cell_type":"markdown","source":"results['diagnosis'].value_counts()"},{"metadata":{"trusted":true},"cell_type":"code","source":"import matplotlib.pyplot as plt\n\naccuracy = history.history['acc']\nval_accuracy = history.history['val_acc']\nloss = history.history['loss']\nval_loss = history.history['val_loss']\nepochs = range(len(accuracy))\n\nplt.plot(epochs, accuracy, 'bo', label='Training accuracy')\nplt.plot(epochs, val_accuracy, 'b', label='Validation accuracy')\nplt.title('Training and validation accuracy')\nplt.legend()\nplt.figure()\n\nplt.plot(epochs, loss, 'bo', label='Training loss')\nplt.plot(epochs, val_loss, 'b', label='Validation loss')\nplt.title('Training and validation loss')\nplt.legend()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"markdown","source":"pred=model.predict_generator(valid_generator,\n                             steps=len(valid_generator),\n                             verbose=1)\npred = np.argmax(pred, axis=1)\nprint('Confusion Matrix')\nprint(confusion_matrix(valid_generator.classes, pred))\nprint('Classification Report')\n# target_names = ['0', '1', '2', '3', '4']\ntarget_names = ['0', '1']\nprint(classification_report(valid_generator.classes, pred, target_names=target_names))"},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Confusion Matrix')\nprint(confusion_matrix(valid_generator.classes, pred))\nprint('Classification Report')\n# target_names = ['0', '1', '2', '3', '4']\ntarget_names = ['0', '1']\nprint(classification_report(valid_generator.classes, pred, target_names=target_names))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"valid_generator.classes","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":1}