{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os\nimport json\n\nimport cv2\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\nimport pydicom\n\nfrom keras import layers\nfrom keras.applications import DenseNet121, ResNet50V2, InceptionV3\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.callbacks import Callback, ModelCheckpoint, ReduceLROnPlateau, EarlyStopping\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.initializers import Constant\nfrom keras.utils import Sequence\nfrom keras.models import Sequential\nfrom keras.optimizers import Adam\nfrom keras.models import Model, load_model\nfrom keras.layers import GlobalAveragePooling2D, Dense, Activation, concatenate, Dropout\nfrom keras.initializers import glorot_normal, he_normal\nfrom keras.regularizers import l2\n\nimport keras.metrics as M\nimport tensorflow_addons as tfa\nimport pickle\n\nfrom keras import backend as K\n\nimport tensorflow as tf\nfrom tensorflow.python.ops import array_ops\n\nfrom tqdm import tqdm\nfrom sklearn.model_selection import train_test_split, StratifiedKFold\n\nimport warnings\nwarnings.filterwarnings(action='once')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"BASE_PATH = '../input/rsna-intracranial-hemorrhage-detection/rsna-intracranial-hemorrhage-detection/'\nTRAIN_DIR = 'stage_2_train/'\nTEST_DIR = 'stage_2_test/'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = pd.read_csv(BASE_PATH + 'stage_2_train.csv')\n#sub_df = pd.read_csv(BASE_PATH + 'stage_1_sample_submission.csv')\n\ntrain_df['id'] = train_df['ID'].apply(lambda st: \"ID_\" + st.split('_')[1])\ntrain_df['subtype'] = train_df['ID'].apply(lambda st: st.split('_')[2])\n#sub_df['filename'] = sub_df['ID'].apply(lambda st: \"ID_\" + st.split('_')[1] + \".png\")\n#sub_df['type'] = sub_df['ID'].apply(lambda st: st.split('_')[2])\n\nprint(train_df.shape)\ntrain_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = train_df[[\"id\",\"subtype\",\"Label\"]]\ntrain_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = pd.pivot_table(train_df,index=\"id\",columns=\"subtype\",values=\"Label\")\ntrain_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pivot_df = train_df.copy()\n#bad = []\n#for index,row in tqdm(pivot_df.iterrows()):\n#    f = BASE_PATH+TRAIN_DIR+index+\".dcm\"\n#    dcm = pydicom.dcmread(f)\n#    try:\n#        d = dcm.pixel_array\n#    except:\n#        bad.append(index)\npivot_df.drop(\"ID_6431af929\",inplace=True)\n#print(bad)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def map_to_gradient(grey_img):\n    rainbow_img = np.zeros((grey_img.shape[0], grey_img.shape[1], 3))\n    rainbow_img[:, :, 0] = np.clip(4 * grey_img - 2, 0, 1.0) * (grey_img > 0) * (grey_img <= 1.0)\n    rainbow_img[:, :, 1] =  np.clip(4 * grey_img * (grey_img <=0.75), 0,1) + np.clip((-4*grey_img + 4) * (grey_img > 0.75), 0, 1)\n    rainbow_img[:, :, 2] = np.clip(-4 * grey_img + 2, 0, 1.0) * (grey_img > 0) * (grey_img <= 1.0)\n    return rainbow_img\n\ndef rainbow_window(dcm):\n    grey_img = window_image(dcm, 40, 80)\n    return map_to_gradient(grey_img)\n\nimport cupy as cp\n\ndef sigmoid_window(dcm, window_center, window_width, U=1.0, eps=(1.0 / 255.0)):\n    img = dcm.pixel_array\n    img = cp.array(np.array(img))\n    _, _, intercept, slope = get_windowing(dcm)\n    img = img * slope + intercept\n    ue = cp.log((U / eps) - 1.0)\n    W = (2 / window_width) * ue\n    b = ((-2 * window_center) / window_width) * ue\n    z = W * img + b\n    img = U / (1 + cp.power(np.e, -1.0 * z))\n    img = (img - cp.min(img)) / (cp.max(img) - cp.min(img))\n    return cp.asnumpy(img)\n\ndef sigmoid_bsb_window(dcm):\n    brain_img = sigmoid_window(dcm, 40, 80)\n    subdural_img = sigmoid_window(dcm, 80, 200)\n    bone_img = sigmoid_window(dcm, 600, 2000)\n    \n    bsb_img = np.zeros((brain_img.shape[0], brain_img.shape[1], 3))\n    bsb_img[:, :, 0] = brain_img\n    bsb_img[:, :, 1] = subdural_img\n    bsb_img[:, :, 2] = bone_img\n    return bsb_img\n\ndef window_image(dcm, window_center, window_width):\n    _, _, intercept, slope = get_windowing(dcm)\n    img = dcm.pixel_array * slope + intercept\n    img_min = window_center - window_width // 2\n    img_max = window_center + window_width // 2\n    img[img < img_min] = img_min\n    img[img > img_max] = img_max\n    img = (img - np.min(img)) / (np.max(img) - np.min(img))\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    bone_img = window_image(dcm, 600, 2000)\n    \n    bsb_img = np.zeros((brain_img.shape[0], brain_img.shape[1], 3))\n    bsb_img[:, :, 0] = brain_img\n    bsb_img[:, :, 1] = subdural_img\n    bsb_img[:, :, 2] = bone_img\n    return bsb_img\n    \ndef get_first_of_dicom_field_as_int(x):\n    #get x[0] as in int is x is a 'pydicom.multival.MultiValue', otherwise get int(x)\n    if type(x) == pydicom.multival.MultiValue:\n        return int(x[0])\n    else:\n        return int(x)\n\ndef get_windowing(data):\n    dicom_fields = [data[('0028','1050')].value, #window center\n                    data[('0028','1051')].value, #window width\n                    data[('0028','1052')].value, #intercept\n                    data[('0028','1053')].value] #slope\n    return [get_first_of_dicom_field_as_int(x) for x in dicom_fields]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def preprocess(file,type=\"WINDOW\"):\n    dcm = pydicom.dcmread(BASE_PATH+TRAIN_DIR+file+\".dcm\")\n    if type == \"WINDOW\":\n        window_center , window_width, intercept, slope = get_windowing(dcm)\n        w = window_image(dcm, window_center, window_width)\n        win_img = np.repeat(w[:, :, np.newaxis], 3, axis=2)\n        #return win_img\n    elif type == \"SIGMOID\":\n        window_center , window_width, intercept, slope = get_windowing(dcm)\n        test_img = dcm.pixel_array\n        w = sigmoid_window(dcm, window_center, window_width)\n        win_img = np.repeat(w[:, :, np.newaxis], 3, axis=2)\n        #return win_img\n    elif type == \"BSB\":\n        win_img = bsb_window(dcm)\n        #return win_img\n    elif type == \"SIGMOID_BSB\":\n        win_img = sigmoid_bsb_window(dcm)\n    elif type == \"GRADIENT\":\n        win_img = rainbow_window(dcm)\n        #return win_img\n    else:\n        win_img = dcm.pixel_array\n    resized = cv2.resize(win_img,(224,224))\n    return resized\n\nclass DataLoader(Sequence):\n    def __init__(self, dataframe,\n                 batch_size,\n                 shuffle,\n                 input_shape,\n                 num_classes=6,\n                 steps=None,\n                 prep=\"BSB\"):\n        \n        self.data_ids = dataframe.index.values\n        self.dataframe = dataframe\n        self.batch_size = batch_size\n        self.shuffle = shuffle\n        self.input_shape = input_shape\n        self.num_classes = num_classes\n        self.current_epoch=0\n        self.prep = prep\n        self.steps=steps\n        if self.steps is not None:\n            self.steps = np.round(self.steps/3) * 3\n            self.undersample()\n        \n    def undersample(self):\n        part = np.int(self.steps/3 * self.batch_size)\n        zero_ids = np.random.choice(self.dataframe.loc[self.dataframe[\"any\"] == 0].index.values, size=5000, replace=False)\n        hot_ids = np.random.choice(self.dataframe.loc[self.dataframe[\"any\"] == 1].index.values, size=5000, replace=True)\n        self.data_ids = list(set(zero_ids).union(hot_ids))\n        np.random.shuffle(self.data_ids)\n        \n    # defines the number of steps per epoch\n    def __len__(self):\n        if self.steps is None:\n            return np.int(np.ceil(len(self.data_ids) / np.float(self.batch_size)))\n        else:\n            return 3*np.int(self.steps/3) \n    \n    # at the end of an epoch: \n    def on_epoch_end(self):\n        # if steps is None and shuffle is true:\n        if self.steps is None:\n            self.data_ids = self.dataframe.index.values\n            if self.shuffle:\n                np.random.shuffle(self.data_ids)\n        else:\n            self.undersample()\n        self.current_epoch += 1\n    \n    # should return a batch of images\n    def __getitem__(self, item):\n        # select the ids of the current batch\n        current_ids = self.data_ids[item*self.batch_size:(item+1)*self.batch_size]\n        X, y = self.__generate_batch(current_ids)\n        return X, y\n    \n    # collect the preprocessed images and targets of one batch\n    def __generate_batch(self, current_ids):\n        X = np.empty((self.batch_size, *self.input_shape, 3))\n        y = np.empty((self.batch_size, self.num_classes))\n        for idx, ident in enumerate(current_ids):\n            # Store sample\n            #image = self.preprocessor.preprocess(ident) \n            image = preprocess(ident,self.prep)\n            X[idx] = image\n            # Store class\n            y[idx] = self.__get_target(ident)\n        return X, y\n    \n    # extract the targets of one image id:\n    def __get_target(self, ident):\n        targets = self.dataframe.loc[ident].values\n        return targets","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def DenseNet():\n    densenet = DenseNet121(\n    #weights='../input/densenet-keras/DenseNet-BC-121-32-no-top.h5',\n    weights='imagenet',\n    include_top=False)\n    return densenet\ndef ResNet():\n    resnet = ResNet50V2(weights=\"imagenet\",include_top=False)\n    return resnet\ndef Inception():\n    incept = InceptionV3(weights=\"imagenet\",include_top=False)\n    return incept\n\ndef get_backbone(name):\n    if name == \"RESNET\":\n        return ResNet\n    elif name == \"DENSE\":\n        return DenseNet\n    elif name == \"INCEPT\":\n        return Inception\n\ndef build_model(backbone):\n    m = backbone()\n    x = m.output\n    x = GlobalAveragePooling2D()(x)\n    x = Dropout(0.3)(x)\n    x = Dense(100, activation=\"relu\")(x)\n    x = Dropout(0.3)(x)\n    pred = Dense(6,activation=\"sigmoid\")(x)\n    model = Model(inputs=m.input,outputs=pred)\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"split_seed = 1\nkfold = StratifiedKFold(n_splits=5, random_state=split_seed,shuffle=True).split(np.arange(pivot_df.shape[0]), pivot_df[\"any\"].values)\n\ntrain_idx, dev_idx = next(kfold)\n\ntrain_data = pivot_df.iloc[train_idx]\ndev_data = pivot_df.iloc[dev_idx]\n\n#train_data, dev_data = train_test_split(traindf, test_size=0.1, stratify=traindf.values, random_state=split_seed)\nprint(train_data.shape)\nprint(dev_data.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def casting_focal_loss():\n    def inner_casting(y_true,y_pred):\n        y_true = tf.cast(y_true, tf.float32)\n        y_pred = tf.cast(y_pred, tf.float32)\n        return tfa.losses.SigmoidFocalCrossEntropy(y_true,y_pred)\n\nMETRICS = ['accuracy']\n#LOSS = casting_focal_loss()\nLOSS = 'categorical_crossentropy'\n\nBATCH_SIZE = 32\nTRAIN_STEPS = 200#(train_data.shape[0] // BATCH_SIZE)\nVAL_STEPS = 200#dev_data.shape[0] // BATCH_SIZE\nEPOCHS = 15\n\nALPHA = 0.5\nGAMMA = 2\n\nLR = 0.0001\n\nPREP = \"SIGMOID_BSB\"\nfor ARCH in ['RESNET','DENSE','INCEPT']:\n    train_dataloader = DataLoader(train_data,\n                                  BATCH_SIZE,\n                                  shuffle=True,\n                                  input_shape=(224,224),\n                                  steps=TRAIN_STEPS,\n                                  prep=PREP)\n\n    dev_dataloader = DataLoader(dev_data, \n                                BATCH_SIZE,\n                                shuffle=True,\n                                input_shape=(224,224),\n                                steps=VAL_STEPS,\n                                prep=PREP)\n    \n    cpath = \"./\" + ARCH + \"_\" + PREP + \"_\" + str(TRAIN_STEPS) + \"_\" + str(EPOCHS) \n    \n    checkpoint = ModelCheckpoint(filepath=cpath + \".model\",mode=\"min\",verbose=1,save_best_only=True,save_weights_only=False,period=1)\n    \n    model = build_model(get_backbone(ARCH))\n    \n    model.compile(optimizer=Adam(learning_rate=LR),loss=LOSS,metrics=METRICS)\n    \n    history = model.fit_generator(generator=train_dataloader,validation_data=dev_dataloader,epochs=EPOCHS,workers=8,callbacks=[checkpoint])\n   \n    with open(cpath + \".history\", 'wb') as file_pi:\n        pickle.dump(history.history, file_pi)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#history_df = pd.DataFrame(history.history)\n#ax1 = history_df[['loss', 'val_loss']].plot()\n#ax1.set_title(\"Sigmoid Focal Cross-Entropy\")\n#ax1.set_xlabel(\"Epoch #\")\n#ax1.set_ylabel(\"Loss\")\n#ax2 = history_df[['binary_crossentropy', 'val_binary_crossentropy']].plot()\n#ax2.set_title(\"Binary Cross-Entropy\")\n#ax2.set_xlabel(\"Epoch #\")\n#ax2.set_ylabel(\"Loss\")\n#history_df[['precision','recall','auc']].plot()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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":4}