{"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":"raw","source":"","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"code","source":"!pip install git+https://github.com/qubvel/classification_models.git\n\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):\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):\n    K.clear_session()\n    \n#     SE_resnext101, preprocess_input = Classifiers.get('seresnext101')\n#     engine = SE_resnext101(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## resNet18\n    mobileNet, preprocess_input = Classifiers.get('resnet18')\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):\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_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):\n    dcm = pydicom.dcmread(path)\n    try:\n        img = bsb_window(dcm)\n    except:\n        img = np.zeros(SHAPE)\n    return img","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def _read_png(path, SHAPE):\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):\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):\n        return int(ceil(len(self.ids) / self.batch_size))\n\n    def __getitem__(self, 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):\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):\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_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):\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_count":null,"outputs":[]},{"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_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_count":null,"outputs":[]},{"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_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('resNet_alldata_retrain_f1_run3.h5')],\n                    verbose = 1, workers=4\n                    )","metadata":{},"execution_count":null,"outputs":[]},{"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_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_count":null,"outputs":[]},{"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_count":null,"outputs":[]},{"cell_type":"code","source":"print_confusion_matrix(y_true, y_pred, class_names)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print_performance_metrics(y_true, y_pred, class_names)","metadata":{},"execution_count":null,"outputs":[]},{"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_count":null,"outputs":[]},{"cell_type":"code","source":"print_confusion_matrix(y_true, y_pred, class_names)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print_performance_metrics(y_true, y_pred, class_names)","metadata":{},"execution_count":null,"outputs":[]},{"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_count":null,"outputs":[]},{"cell_type":"code","source":"print_confusion_matrix(y_true, y_pred, class_names)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print_performance_metrics(y_true, y_pred, class_names)","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":[]},{"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":[]}]}