{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install git+https://github.com/qubvel/classification_models.git\n\n\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport os\nimport random\nimport cv2\nimport tensorflow as tf\n\nfrom math import ceil, floor\nfrom copy import deepcopy\nfrom tqdm.notebook import tqdm\nfrom imgaug import augmenters as iaa\n\nimport tensorflow.keras as keras\nimport tensorflow.keras.backend as K\nfrom tensorflow.keras.callbacks import Callback, ModelCheckpoint\nfrom tensorflow.keras.layers import Dense, Flatten, Dropout\nfrom tensorflow.keras.models import Model, load_model\nfrom tensorflow.keras.utils import Sequence\nfrom tensorflow.keras.losses import binary_crossentropy\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.metrics import AUC, Recall, Precision, BinaryCrossentropy\nfrom classification_models.tfkeras import Classifiers\nfrom tensorflow.keras.layers import *\nfrom sklearn.utils.class_weight import compute_class_weight\n\ndef calculating_class_weights(y_true):     #  input : true labels  \n                                        # output : weights of each class\n    number_dim = np.shape(y_true)[1]\n    weights = np.empty([number_dim, 2])\n    for i in range(number_dim):\n        weights[i] = compute_class_weight('balanced', classes=np.unique(y_true[:, i]), y=y_true[:, i])\n    return weights\n\n\ndef ModelCheckpointFull(model_name):\n    return ModelCheckpoint(model_name, \n                            monitor = 'val_accuracy', \n                            verbose = 1, \n                            save_best_only = True, \n                            save_weights_only = True, \n                            mode = 'max', \n                            period = 1)\n\n# Create Model\ndef create_model(num_classes):    # input : num of classes\n                               # output : pretrained mobilenet to classify num_classes classes.\n    K.clear_session()\n  # mobileNet\n    mobileNet, preprocess_input = Classifiers.get('mobilenet')\n    engine = mobileNet(include_top=False,\n                           input_shape=(256, 256, 3),\n                           backend = tf.keras.backend,\n                           layers = tf.keras.layers,\n                           models = tf.keras.models,\n                           utils = tf.keras.utils,\n                          weights = 'imagenet')\n\n    x = GlobalAveragePooling2D(name='avg_pool')(engine.output)\n    x = Dropout(0.15)(x)\n    out = Dense(num_classes, activation='sigmoid', name='new_output')(x)\n    model = Model(inputs=engine.input, outputs=out)\n\n    return model\n\ndef metrics_define(num_classes):\n    metrics_all = ['accuracy',\n    AUC(curve='PR',multi_label=True,name='auc_pr'),\n    AUC(multi_label=True, name='auc_roc')\n    ]\n\n    return metrics_all\n\ndef get_weighted_loss(weights):    # input : weights of classes\n                                   # output : loss (weighted loss)\n    def weighted_loss(y_true, y_pred):\n        return K.mean((weights[:,0]**(1-y_true))*(weights[:,1]**(y_true))*K.binary_crossentropy(y_true, y_pred), axis=-1)\n    return weighted_loss","metadata":{"execution":{"iopub.status.busy":"2021-11-09T23:34:25.031478Z","iopub.execute_input":"2021-11-09T23:34:25.031744Z","iopub.status.idle":"2021-11-09T23:34:43.465692Z","shell.execute_reply.started":"2021-11-09T23:34:25.031714Z","shell.execute_reply":"2021-11-09T23:34:43.464939Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pydicom\n\ndef correct_dcm(dcm):\n    x = dcm.pixel_array + 1000\n    px_mode = 4096\n    x[x>=px_mode] = x[x>=px_mode] - px_mode\n    dcm.PixelData = x.tobytes()\n    dcm.RescaleIntercept = -1000\n\ndef window_image(dcm, window_center, window_width):    \n    if (dcm.BitsStored == 12) and (dcm.PixelRepresentation == 0) and (int(dcm.RescaleIntercept) > -100):\n        correct_dcm(dcm)\n    img = dcm.pixel_array * dcm.RescaleSlope + dcm.RescaleIntercept\n    img = cv2.resize(img, SHAPE[:2], interpolation = cv2.INTER_LINEAR)\n    img_min = window_center - window_width // 2\n    img_max = window_center + window_width // 2\n    img = np.clip(img, img_min, img_max)\n    return img\n\ndef bsb_window(dcm):\n    brain_img = window_image(dcm, 40, 80)\n    subdural_img = window_image(dcm, 80, 200)\n    brain_img = (brain_img - 0) / 80\n    subdural_img = (subdural_img - (-20)) / 200\n    soft_img = window_image(dcm, 40, 380)\n    soft_img = (soft_img - (-150)) / 380\n    bsb_img = np.array([brain_img, subdural_img, soft_img]).transpose(1,2,0)\n    return bsb_img\n\ndef _read_dicom(path, SHAPE):    # input : the path of dicome image and its shape.\n                                  # output : image in numpy format.\n    dcm = pydicom.dcmread(path)\n    try:\n        img = bsb_window(dcm)\n    except:\n        img = np.zeros(SHAPE)\n    return img","metadata":{"execution":{"iopub.status.busy":"2021-11-09T23:34:43.467241Z","iopub.execute_input":"2021-11-09T23:34:43.467497Z","iopub.status.idle":"2021-11-09T23:34:43.556092Z","shell.execute_reply.started":"2021-11-09T23:34:43.467464Z","shell.execute_reply":"2021-11-09T23:34:43.555422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def _read_png(path, SHAPE):    # input : path of specific image and the shape that we want convert image to.\n                              # output : readed image/255\n    img = cv2.imread(path)\n    img = cv2.resize(img, dsize=(256, 256))\n    return img/255.0\n\n# Image Augmentation\nsometimes = lambda aug: iaa.Sometimes(0.25, aug)\naugmentation = iaa.Sequential([ iaa.Fliplr(0.25),\n                                iaa.Flipud(0.10),\n                                sometimes(iaa.Crop(px=(0, 25), keep_size = True, sample_independently = False))   \n                            ], random_order = True)       \n        \n# Generators\nclass TrainDataGenerator(keras.utils.Sequence):\n    def __init__(self, dataset, class_names, batch_size = 16, img_size = (256, 256, 3), \n                 augment = False, shuffle = True, *args, **kwargs):    # initialize datagenerator\n        self.dataset = dataset\n        self.ids = self.dataset['imgfile'].values\n        self.labels = self.dataset[class_names].values\n        self.batch_size = batch_size\n        self.img_size = img_size\n        self.augment = augment\n        self.shuffle = shuffle\n        self.on_epoch_end()\n\n    def __len__(self):    # size of datagenerator (number of batchs)\n        return int(ceil(len(self.ids) / self.batch_size))\n\n    def __getitem__(self, index):     # input : index of a batch\n                                    # output : specific batch with input index\n        indices = self.indices[index*self.batch_size:(index+1)*self.batch_size]\n        X, Y = self.__data_generation(indices)\n        return X, Y\n\n    def augmentor(self, image):     # input : image\n                                 # output : augmented image\n        augment_img = augmentation        \n        image_aug = augment_img.augment_image(image)\n        return image_aug\n\n    def on_epoch_end(self):\n        self.indices = np.arange(len(self.ids))\n        if self.shuffle:\n            np.random.shuffle(self.indices)\n\n    def __data_generation(self, indices):    # creating augmented images and their labels.\n                                          # input : /////////////////////////////////////\n                                          # output : augmented images and their labels.\n        X = np.empty((self.batch_size, *self.img_size))\n        Y = np.empty((self.batch_size, len(class_names)), dtype=np.float32)\n        \n        for i, index in enumerate(indices):\n            ID = self.ids[index]\n            if '.png' not in ID:\n                image = _read_dicom('../input/rsna-intracranial-hemorrhage-detection/rsna-intracranial-hemorrhage-detection/stage_2_train/'+ID+'.dcm', self.img_size)\n            else:\n                if 'NonHemo' in ID:\n                    image = _read_png('../input/cq500-normal-images-and-labels/'+ID, self.img_size)\n                else:\n                    if 'content' in ID:\n                        ID = ID[9:]\n                    image = _read_png('../input/rsna-cq500-abnormal-data/'+ID, self.img_size)\n            if self.augment:\n                X[i,] = self.augmentor(image)\n            else:\n                X[i,] = image\n            Y[i,] = self.labels[index]        \n        return X, Y","metadata":{"execution":{"iopub.status.busy":"2021-11-09T23:34:43.5574Z","iopub.execute_input":"2021-11-09T23:34:43.557656Z","iopub.status.idle":"2021-11-09T23:34:43.575746Z","shell.execute_reply.started":"2021-11-09T23:34:43.55762Z","shell.execute_reply":"2021-11-09T23:34:43.574768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from prettytable import PrettyTable\nfrom sklearn import metrics\nfrom sklearn.metrics import roc_auc_score, accuracy_score, precision_score, recall_score, f1_score\nfrom sklearn.metrics import precision_recall_curve\nfrom sklearn.metrics import average_precision_score\nfrom sklearn.metrics import roc_curve, auc, roc_auc_score\nfrom sklearn.metrics import multilabel_confusion_matrix\nfrom sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay\nimport seaborn as sns\n\n\ndef print_confusion_matrix(y_test, y_pred, class_names):    # input : true labels, predicted labels, array of class names \n                                                                # print confusion matrixes.\n    matrix = confusion_matrix(y_test, y_pred)\n    plt.figure(figsize=(6, 4))\n    cm = matrix.astype('float') / matrix.sum(axis=1)[:, np.newaxis]\n    sns.heatmap(cm,cmap='crest',linecolor='white',linewidths=1,annot=True, xticklabels = class_names, yticklabels = class_names)\n    plt.title('Confusion Matrix')\n    plt.ylabel('True Label')\n    plt.xlabel('Predicted Label')\n    plt.show()\n\ndef print_performance_metrics(y_test, y_pred, class_names):\n    print('Accuracy:', np.round(metrics.accuracy_score(y_test, y_pred),4))\n    print('Precision:', np.round(metrics.precision_score(y_test, y_pred, average='weighted'),4))\n    print('Recall:', np.round(metrics.recall_score(y_test, y_pred, average='weighted'),4))\n    print('F1 Score:', np.round(metrics.f1_score(y_test, y_pred, average='weighted'),4))\n    print('Cohen Kappa Score:', np.round(metrics.cohen_kappa_score(y_test, y_pred), 4))\n    print('Matthews Corrcoef:', np.round(metrics.matthews_corrcoef(y_test, y_pred), 4))\n    if len(np.unique(y_test)) == 2:\n        print('ROC AUC:',roc_auc_score(y_test,y_pred))\n    print('\\t\\tClassification Report:\\n', metrics.classification_report(y_test, y_pred, target_names=class_names))","metadata":{"execution":{"iopub.status.busy":"2021-11-09T23:34:43.578254Z","iopub.execute_input":"2021-11-09T23:34:43.578516Z","iopub.status.idle":"2021-11-09T23:34:43.680566Z","shell.execute_reply.started":"2021-11-09T23:34:43.578483Z","shell.execute_reply":"2021-11-09T23:34:43.679883Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"create validation and train dataframe on fold 1","metadata":{}},{"cell_type":"code","source":"from sklearn.utils import shuffle\n\ntrain_df = pd.read_csv('../input/cq500-normal-images-and-labels/NormalAbnormal/NormalAbnormal/Train_f1.csv')\nabnormal = train_df.loc[train_df['Abnormal']==1]\ntrain_df = train_df.append(abnormal, ignore_index=True)\ntrain_df = shuffle(train_df)\n\nval_df = pd.read_csv('../input/cq500-normal-images-and-labels/NormalAbnormal/NormalAbnormal/Validation_f1.csv')","metadata":{"execution":{"iopub.status.busy":"2021-11-09T23:34:43.681896Z","iopub.execute_input":"2021-11-09T23:34:43.682335Z","iopub.status.idle":"2021-11-09T23:34:45.484107Z","shell.execute_reply.started":"2021-11-09T23:34:43.682297Z","shell.execute_reply":"2021-11-09T23:34:45.483303Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"HEIGHT = 256\nWIDTH = 256\nCHANNELS = 3\nTRAIN_BATCH_SIZE = 32\nVALID_BATCH_SIZE = 64\nSHAPE = (HEIGHT, WIDTH, CHANNELS)\n\nclass_names = ['Normal', 'Abnormal']\n\nweights = calculating_class_weights((train_df[class_names].values).astype(np.float32))\nprint(weights)\n\ndata_generator_train = TrainDataGenerator(train_df,\n                                          class_names,\n                                          TRAIN_BATCH_SIZE,\n                                          SHAPE,\n                                          augment = True,\n                                          shuffle = True)\ndata_generator_val = TrainDataGenerator(val_df,\n                                        class_names, \n                                        VALID_BATCH_SIZE, \n                                        SHAPE,\n                                        augment = False,\n                                        shuffle = True\n                                        )\n\nTRAIN_STEPS = int(len(data_generator_train)/10)\nprint(TRAIN_STEPS)\nVal_STEPS = int(len(data_generator_val)/10)\nprint(Val_STEPS)\nLR = 1e-6","metadata":{"execution":{"iopub.status.busy":"2021-11-09T23:34:45.487937Z","iopub.execute_input":"2021-11-09T23:34:45.488161Z","iopub.status.idle":"2021-11-09T23:34:46.086716Z","shell.execute_reply.started":"2021-11-09T23:34:45.488135Z","shell.execute_reply":"2021-11-09T23:34:46.085942Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"define model and fit it\n","metadata":{}},{"cell_type":"code","source":"Metrics = metrics_define(len(class_names))\nmodel = create_model(len(class_names))\n# model.load_weights('../input/stroke-binary-classification-model/model_alldata_retrain_f1_run2.h5')\nmodel.compile(optimizer = Adam(learning_rate = LR),\n              loss = get_weighted_loss(weights),\n              metrics = Metrics)","metadata":{"execution":{"iopub.status.busy":"2021-11-07T16:40:50.380789Z","iopub.execute_input":"2021-11-07T16:40:50.381052Z","iopub.status.idle":"2021-11-07T16:40:51.9635Z","shell.execute_reply.started":"2021-11-07T16:40:50.381014Z","shell.execute_reply":"2021-11-07T16:40:51.962749Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(data_generator_train,\n                    validation_data = data_generator_val,\n                    validation_steps = Val_STEPS,\n                    steps_per_epoch = TRAIN_STEPS,\n                    epochs = 10,\n                    callbacks = [ModelCheckpointFull('mobileNet_alldata_retrain_f1_run3.h5')],\n                    verbose = 1, workers=4\n                    )","metadata":{"execution":{"iopub.status.busy":"2021-11-07T16:40:51.96487Z","iopub.execute_input":"2021-11-07T16:40:51.965132Z","iopub.status.idle":"2021-11-07T19:01:38.907276Z","shell.execute_reply.started":"2021-11-07T16:40:51.965086Z","shell.execute_reply":"2021-11-07T19:01:38.906443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"results","metadata":{}},{"cell_type":"code","source":"plt.plot(history.history['loss'])\nplt.plot(history.history['val_loss'])\nplt.title('model loss')\nplt.ylabel('loss')\nplt.xlabel('epoch')\nplt.legend(['train', 'val'], loc='upper left')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-11-07T19:01:38.910404Z","iopub.execute_input":"2021-11-07T19:01:38.911044Z","iopub.status.idle":"2021-11-07T19:01:39.124119Z","shell.execute_reply.started":"2021-11-07T19:01:38.910998Z","shell.execute_reply":"2021-11-07T19:01:39.123448Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(history.history['accuracy'])\nplt.plot(history.history['val_accuracy'])\nplt.title('model auc_accuracy')\nplt.ylabel('accuracy')\nplt.xlabel('epoch')\nplt.legend(['train', 'val'], loc='upper left')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-11-07T19:01:39.125268Z","iopub.execute_input":"2021-11-07T19:01:39.12665Z","iopub.status.idle":"2021-11-07T19:01:39.318098Z","shell.execute_reply.started":"2021-11-07T19:01:39.12661Z","shell.execute_reply":"2021-11-07T19:01:39.317349Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"validate model","metadata":{}},{"cell_type":"code","source":"val_df = pd.read_csv('../input/cq500-normal-images-and-labels/NormalAbnormal/NormalAbnormal/Validation_f1.csv')\nabnormal = val_df.loc[val_df['Abnormal']==1]\nnormal = val_df.loc[val_df['Normal']==1]\nnormal=shuffle(normal)\nnormal = normal.iloc[0:len(abnormal)]\nval_df = abnormal.append(normal, ignore_index=True)\nval_df = shuffle(val_df)\nprint(len(val_df))\n\nHEIGHT = 256\nWIDTH = 256\nCHANNELS = 3\nVALID_BATCH_SIZE = 64\nSHAPE = (HEIGHT, WIDTH, CHANNELS)\n\nclass_names = ['Normal', 'Abnormal']\ndata_generator_test = TrainDataGenerator(val_df,\n                                        class_names, \n                                        VALID_BATCH_SIZE, \n                                        SHAPE,\n                                        augment = False,\n                                        shuffle = False\n                                        )\n\ny_true = val_df[class_names].values\ny_hat = model.predict(data_generator_test, verbose=1)\n\ny_hat = y_hat[0:len(y_true)]\ny_pred = np.argmax(y_hat, axis=1)\ny_true = np.argmax(y_true, axis=1)","metadata":{"execution":{"iopub.status.busy":"2021-11-07T19:01:39.319257Z","iopub.execute_input":"2021-11-07T19:01:39.319532Z","iopub.status.idle":"2021-11-07T19:13:44.421678Z","shell.execute_reply.started":"2021-11-07T19:01:39.319479Z","shell.execute_reply":"2021-11-07T19:13:44.420815Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print_confusion_matrix(y_true, y_pred, class_names)","metadata":{"execution":{"iopub.status.busy":"2021-11-07T19:13:44.42327Z","iopub.execute_input":"2021-11-07T19:13:44.423618Z","iopub.status.idle":"2021-11-07T19:13:44.720179Z","shell.execute_reply.started":"2021-11-07T19:13:44.423569Z","shell.execute_reply":"2021-11-07T19:13:44.71937Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print_performance_metrics(y_true, y_pred, class_names)","metadata":{"execution":{"iopub.status.busy":"2021-11-07T19:13:44.721585Z","iopub.execute_input":"2021-11-07T19:13:44.721881Z","iopub.status.idle":"2021-11-07T19:13:45.002951Z","shell.execute_reply.started":"2021-11-07T19:13:44.721846Z","shell.execute_reply":"2021-11-07T19:13:45.002072Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"validate model on another fold (RSNA f0) ","metadata":{}},{"cell_type":"code","source":"val_df = pd.read_csv('../input/cq500-normal-images-and-labels/NormalAbnormal/NormalAbnormal/RSNA/Validation_f0.csv')\nabnormal = val_df.loc[val_df['Abnormal']==1]\nnormal = val_df.loc[val_df['Normal']==1]\nnormal=shuffle(normal)\nnormal = normal.iloc[0:len(abnormal)]\nval_df = abnormal.append(normal, ignore_index=True)\nval_df = shuffle(val_df)\nprint(len(val_df))\n\nHEIGHT = 256\nWIDTH = 256\nCHANNELS = 3\nVALID_BATCH_SIZE = 64\nSHAPE = (HEIGHT, WIDTH, CHANNELS)\n\nclass_names = ['Normal', 'Abnormal']\ndata_generator_test = TrainDataGenerator(val_df,\n                                        class_names, \n                                        VALID_BATCH_SIZE, \n                                        SHAPE,\n                                        augment = False,\n                                        shuffle = False\n                                        )\n\ny_true = val_df[class_names].values\ny_hat = model.predict(data_generator_test, verbose=1)\n\ny_hat = y_hat[0:len(y_true)]\ny_pred = np.argmax(y_hat, axis=1)\ny_true = np.argmax(y_true, axis=1)","metadata":{"execution":{"iopub.status.busy":"2021-11-07T19:13:45.007192Z","iopub.execute_input":"2021-11-07T19:13:45.007402Z","iopub.status.idle":"2021-11-07T19:22:47.220787Z","shell.execute_reply.started":"2021-11-07T19:13:45.007376Z","shell.execute_reply":"2021-11-07T19:22:47.219956Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print_confusion_matrix(y_true, y_pred, class_names)","metadata":{"execution":{"iopub.status.busy":"2021-11-07T19:22:47.223978Z","iopub.execute_input":"2021-11-07T19:22:47.224232Z","iopub.status.idle":"2021-11-07T19:22:47.500302Z","shell.execute_reply.started":"2021-11-07T19:22:47.224178Z","shell.execute_reply":"2021-11-07T19:22:47.499557Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print_performance_metrics(y_true, y_pred, class_names)","metadata":{"execution":{"iopub.status.busy":"2021-11-07T19:22:47.501481Z","iopub.execute_input":"2021-11-07T19:22:47.502194Z","iopub.status.idle":"2021-11-07T19:22:47.732478Z","shell.execute_reply.started":"2021-11-07T19:22:47.502151Z","shell.execute_reply":"2021-11-07T19:22:47.731677Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"validate model on another fold (CQ500 f0)","metadata":{}},{"cell_type":"code","source":"val_df = pd.read_csv('../input/cq500-normal-images-and-labels/NormalAbnormal/NormalAbnormal/CQ500/Validation_f0.csv')\nabnormal = val_df.loc[val_df['Abnormal']==1]\nnormal = val_df.loc[val_df['Normal']==1]\nnormal=shuffle(normal)\nnormal = normal.iloc[0:len(abnormal)]\nval_df = abnormal.append(normal, ignore_index=True)\nval_df = shuffle(val_df)\nprint(len(val_df))\n\nHEIGHT = 256\nWIDTH = 256\nCHANNELS = 3\nVALID_BATCH_SIZE = 64\nSHAPE = (HEIGHT, WIDTH, CHANNELS)\n\nclass_names = ['Normal', 'Abnormal']\ndata_generator_test = TrainDataGenerator(val_df,\n                                        class_names, \n                                        VALID_BATCH_SIZE, \n                                        SHAPE,\n                                        augment = False,\n                                        shuffle = False\n                                        )\n\ny_true = val_df[class_names].values\ny_hat = model.predict(data_generator_test, verbose=1)\n\ny_hat = y_hat[0:len(y_true)]\ny_pred = np.argmax(y_hat, axis=1)\ny_true = np.argmax(y_true, axis=1)","metadata":{"execution":{"iopub.status.busy":"2021-11-07T19:22:47.733737Z","iopub.execute_input":"2021-11-07T19:22:47.734086Z","iopub.status.idle":"2021-11-07T19:24:08.146593Z","shell.execute_reply.started":"2021-11-07T19:22:47.734044Z","shell.execute_reply":"2021-11-07T19:24:08.145819Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print_confusion_matrix(y_true, y_pred, class_names)","metadata":{"execution":{"iopub.status.busy":"2021-11-07T19:24:08.147932Z","iopub.execute_input":"2021-11-07T19:24:08.148292Z","iopub.status.idle":"2021-11-07T19:24:08.374746Z","shell.execute_reply.started":"2021-11-07T19:24:08.148251Z","shell.execute_reply":"2021-11-07T19:24:08.374117Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print_performance_metrics(y_true, y_pred, class_names)","metadata":{"execution":{"iopub.status.busy":"2021-11-07T19:24:08.375905Z","iopub.execute_input":"2021-11-07T19:24:08.376148Z","iopub.status.idle":"2021-11-07T19:24:08.434884Z","shell.execute_reply.started":"2021-11-07T19:24:08.376114Z","shell.execute_reply":"2021-11-07T19:24:08.434032Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"[](http://)","metadata":{}},{"cell_type":"markdown","source":"GradCam","metadata":{}},{"cell_type":"code","source":"model = create_model(2)\nmodel.load_weights('../input/stroke-mobilenet-binary-classification/mobileNet_alldata_retrain_f1_run3.h5')","metadata":{"execution":{"iopub.status.busy":"2021-11-09T23:35:26.193754Z","iopub.execute_input":"2021-11-09T23:35:26.194013Z","iopub.status.idle":"2021-11-09T23:35:27.230274Z","shell.execute_reply.started":"2021-11-09T23:35:26.193983Z","shell.execute_reply":"2021-11-09T23:35:27.229496Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport tensorflow as tf\nfrom tensorflow import keras\n\n# Display\nfrom IPython.display import Image, display\nimport matplotlib.pyplot as plt\nimport matplotlib.cm as cm","metadata":{"execution":{"iopub.status.busy":"2021-11-09T23:35:31.859458Z","iopub.execute_input":"2021-11-09T23:35:31.859989Z","iopub.status.idle":"2021-11-09T23:35:31.865554Z","shell.execute_reply.started":"2021-11-09T23:35:31.859951Z","shell.execute_reply":"2021-11-09T23:35:31.863712Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_builder = model\nimg_size = (256, 256)\n\ndecode_predictions = keras.applications.mobilenet.decode_predictions\n\nlast_conv_layer_name = \"conv_pw_13_relu\"\n\n","metadata":{"execution":{"iopub.status.busy":"2021-11-09T23:35:34.752598Z","iopub.execute_input":"2021-11-09T23:35:34.753293Z","iopub.status.idle":"2021-11-09T23:35:34.758749Z","shell.execute_reply.started":"2021-11-09T23:35:34.753251Z","shell.execute_reply":"2021-11-09T23:35:34.757872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_img_array(img_path, size):\n    \n    img = keras.preprocessing.image.load_img(img_path, target_size=size)\n    \n    array = keras.preprocessing.image.img_to_array(img)\n    \n    array = np.expand_dims(array, axis=0)\n    return array\n\n\ndef make_gradcam_heatmap(img_array, model, last_conv_layer_name, pred_index=None):\n    # First, we create a model that maps the input image to the activations\n    # of the last conv layer as well as the output predictions\n    grad_model = tf.keras.models.Model(\n        [model.inputs], [model.get_layer(last_conv_layer_name).output, model.output]\n    )\n\n    # Then, we compute the gradient of the top predicted class for our input image\n    # with respect to the activations of the last conv layer\n    with tf.GradientTape() as tape:\n        last_conv_layer_output, preds = grad_model(img_array)\n        if pred_index is None:\n            pred_index = tf.argmax(preds[0])\n        class_channel = preds[:, pred_index]\n\n    # This is the gradient of the output neuron (top predicted or chosen)\n    # with regard to the output feature map of the last conv layer\n    grads = tape.gradient(class_channel, last_conv_layer_output)\n\n    # This is a vector where each entry is the mean intensity of the gradient\n    # over a specific feature map channel\n    pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))\n\n    # We multiply each channel in the feature map array\n    # by \"how important this channel is\" with regard to the top predicted class\n    # then sum all the channels to obtain the heatmap class activation\n    last_conv_layer_output = last_conv_layer_output[0]\n    heatmap = last_conv_layer_output @ pooled_grads[..., tf.newaxis]\n    heatmap = tf.squeeze(heatmap)\n\n    # For visualization purpose, we will also normalize the heatmap between 0 & 1\n    heatmap = tf.maximum(heatmap, 0) / tf.math.reduce_max(heatmap)\n    return heatmap.numpy()","metadata":{"execution":{"iopub.status.busy":"2021-11-09T23:35:37.75334Z","iopub.execute_input":"2021-11-09T23:35:37.753808Z","iopub.status.idle":"2021-11-09T23:35:37.763902Z","shell.execute_reply.started":"2021-11-09T23:35:37.753772Z","shell.execute_reply":"2021-11-09T23:35:37.763064Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_generator_test = TrainDataGenerator(val_df,\n                                        class_names, \n                                        VALID_BATCH_SIZE, \n                                        SHAPE,\n                                        augment = False,\n                                        shuffle = False\n                                        )","metadata":{"execution":{"iopub.status.busy":"2021-11-09T23:35:40.982768Z","iopub.execute_input":"2021-11-09T23:35:40.983039Z","iopub.status.idle":"2021-11-09T23:35:40.989976Z","shell.execute_reply.started":"2021-11-09T23:35:40.983005Z","shell.execute_reply":"2021-11-09T23:35:40.9891Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def save_and_display_gradcam(img, heatmap, cam_path=\"cam.jpg\", alpha=0.4):\n\n\n    # Rescale heatmap to a range 0-255\n    heatmap = np.uint8(255 * heatmap)\n\n    # Use jet colormap to colorize heatmap\n    jet = cm.get_cmap(\"jet\")\n\n    # Use RGB values of the colormap\n    jet_colors = jet(np.arange(256))[:, :3]\n    jet_heatmap = jet_colors[heatmap]\n\n    # Create an image with RGB colorized heatmap\n    jet_heatmap = keras.preprocessing.image.array_to_img(jet_heatmap)\n    jet_heatmap = jet_heatmap.resize((img.shape[1], img.shape[0]))\n    jet_heatmap = keras.preprocessing.image.img_to_array(jet_heatmap)\n\n    # Superimpose the heatmap on original image\n    superimposed_img = jet_heatmap * alpha + img\n    superimposed_img = keras.preprocessing.image.array_to_img(superimposed_img)\n\n    # Save the superimposed image\n    superimposed_img.save(cam_path)\n\n    # Display Grad CAM\n    display(Image(cam_path))\n\n\n# save_and_display_gradcam(img_array[0]*255, heatmap)","metadata":{"execution":{"iopub.status.busy":"2021-11-09T23:35:43.548023Z","iopub.execute_input":"2021-11-09T23:35:43.548734Z","iopub.status.idle":"2021-11-09T23:35:43.556358Z","shell.execute_reply.started":"2021-11-09T23:35:43.548692Z","shell.execute_reply":"2021-11-09T23:35:43.555529Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm -r 0\n!rm -r 1","metadata":{"execution":{"iopub.status.busy":"2021-11-09T23:41:45.031558Z","iopub.execute_input":"2021-11-09T23:41:45.031963Z","iopub.status.idle":"2021-11-09T23:41:46.466513Z","shell.execute_reply.started":"2021-11-09T23:41:45.031926Z","shell.execute_reply":"2021-11-09T23:41:46.465549Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir 0\n!mkdir 1\n","metadata":{"execution":{"iopub.status.busy":"2021-11-09T23:41:46.622073Z","iopub.execute_input":"2021-11-09T23:41:46.622451Z","iopub.status.idle":"2021-11-09T23:41:48.152517Z","shell.execute_reply.started":"2021-11-09T23:41:46.622415Z","shell.execute_reply":"2021-11-09T23:41:48.151503Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nh=0\nfor i in range(0,10):\n    for j in range (0,64):\n        x = data_generator_test[i][0][j]\n        x = x.reshape(1,256,256,3)\n        np.shape(x)\n        \n        h+=1\n        preds = model.predict(x)\n        heatmap = make_gradcam_heatmap(x*255, model, last_conv_layer_name)\n        p=os.path.join(\"./\", str(np.argmax(preds)))\n        if len(os.listdir(p)) < 21: \n            save_and_display_gradcam(x[0]*255, heatmap, str(np.argmax(preds))+\"/\"+\"cam_\"+str(len(os.listdir(p)))+\".jpg\")\n            print(\"--- \"+str(np.argmax(preds))+\" :  \"+ str(len(os.listdir(p))))\n        if len(os.listdir('./0')) == 21 and len(os.listdir('./1')) ==21 :\n            break\n            ","metadata":{"execution":{"iopub.status.busy":"2021-11-09T23:41:48.822688Z","iopub.execute_input":"2021-11-09T23:41:48.822966Z","iopub.status.idle":"2021-11-09T23:42:26.199622Z","shell.execute_reply.started":"2021-11-09T23:41:48.822936Z","shell.execute_reply":"2021-11-09T23:42:26.198852Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\nw = 256\nh = 256\nfig = plt.figure(figsize=(9, 13))\ncolumns = 4\nrows = 5\n\n# prep (x,y) for extra plotting\nxs = np.linspace(0, 2*np.pi, 60)  # from 0 to 2pi\nys = np.abs(np.sin(xs))           # absolute of sine\n\n# ax enables access to manipulate each of subplots\nax = []\np=os.path.join(\"./\",\"0\",)\nfor i in range(columns*rows):\n\n#     img = np.random.randint(10, size=(h,w))\n    img = cv2.imread(p+'/'+'cam_'+str(i)+'.jpg')\n\n    \n    # create subplot and append to ax\n    ax.append( fig.add_subplot(rows, columns, i+1) )\n    ax[-1].set_title(\"prediction : 0\")  # set title\n    plt.imshow(img, )\n\n# do extra plots on selected axes/subplots\n# note: index starts with 0\nax[2].plot(xs, 3*ys)\nax[19].plot(ys**2, xs)\n\nplt.show()  # finally, render the plot","metadata":{"execution":{"iopub.status.busy":"2021-11-09T23:42:34.360959Z","iopub.execute_input":"2021-11-09T23:42:34.361262Z","iopub.status.idle":"2021-11-09T23:42:36.303212Z","shell.execute_reply.started":"2021-11-09T23:42:34.361216Z","shell.execute_reply":"2021-11-09T23:42:36.302544Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\nw = 256\nh = 256\nfig = plt.figure(figsize=(9, 13))\ncolumns = 4\nrows = 5\n\n# prep (x,y) for extra plotting\nxs = np.linspace(0, 2*np.pi, 60)  # from 0 to 2pi\nys = np.abs(np.sin(xs))           # absolute of sine\n\n# ax enables access to manipulate each of subplots\nax = []\np=os.path.join(\"./\",\"1\",)\nfor i in range(columns*rows):\n\n#     img = np.random.randint(10, size=(h,w))\n    img = cv2.imread(p+'/'+'cam_'+str(i)+'.jpg')\n\n    \n    # create subplot and append to ax\n    ax.append( fig.add_subplot(rows, columns, i+1) )\n    ax[-1].set_title(\"prediction : 1\")  # set title\n    plt.imshow(img, )\n\n# do extra plots on selected axes/subplots\n# note: index starts with 0\nax[2].plot(xs, 3*ys)\nax[19].plot(ys**2, xs)\n\nplt.show()  # finally, render the plot","metadata":{"execution":{"iopub.status.busy":"2021-11-09T23:42:47.900508Z","iopub.execute_input":"2021-11-09T23:42:47.900918Z","iopub.status.idle":"2021-11-09T23:42:50.075116Z","shell.execute_reply.started":"2021-11-09T23:42:47.900879Z","shell.execute_reply":"2021-11-09T23:42:50.07446Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}