{"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\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 read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 5GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import pandas as pd\nimport numpy as np","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nimport pydicom\nimport cv2\nimport skimage\nfrom skimage import color\nfrom skimage import exposure\n\nimport tensorflow as tf\nimport numpy as np\nimport tensorflow \n\n\ndef bbToYoloFormat(bb):\n    \"\"\"\n    converts (left, top, right, bottom) to\n    (center_x, center_y, center_w, center_h)\n    \"\"\"\n    x1, y1, x2, y2 = np.split(bb, 4, axis=1) \n    w = x2 - x1\n    h = y2 - y1\n    c_x = x1 + w / 2\n    c_y = y1 + h / 2\n    \n    return np.concatenate([c_x, c_y, w, h], axis=-1)\n\ndef findBestPrior(bb, priors):\n    \"\"\"\n    Given bounding boxes in yolo format and anchor priors\n    compute the best anchor prior for each bounding box\n    \"\"\"\n    w1, h1 = bb[:, 2], bb[:, 3]\n    w2, h2 = priors[:, 0], priors[:, 1]\n    \n    # overlap, assumes top left corner of both at (0, 0)\n    horizontal_overlap = np.minimum(w1[:, None], w2)\n    vertical_overlap = np.minimum(h1[:, None], h2)\n    \n    intersection = horizontal_overlap * vertical_overlap\n    union = (w1 * h1)[:, None] + (w2 * h2) - intersection\n    iou = intersection / union\n    return np.argmax(iou, axis=1)\n\ndef processGroundTruth(bb, labels, priors, network_output_shape):\n    \"\"\"\n    Given bounding boxes in normal x1,y1,x2,y2 format, the relevant labels in one-hot form,\n    the anchor priors and the yolo model's output shape\n    build the y_true vector to be used in yolov2 loss calculation\n    \"\"\"\n    bb = bbToYoloFormat(bb) / 32\n    best_anchor_indices = findBestPrior(bb, priors)\n    \n    responsible_grid_coords = np.floor(bb).astype(np.uint32)[:, :2]\n    \n    values = np.concatenate((\n        bb, np.ones((len(bb), 1)), labels\n    ), axis=1)\n    \n    x, y = np.split(responsible_grid_coords, 2, axis=1)\n    y = y.ravel()\n    x = x.ravel()\n    \n    y_true = np.zeros(network_output_shape)    \n    y_true[y, x, best_anchor_indices] = values\n    \n    return y_true\n\n\n\n\nclass det_gen(tensorflow.keras.utils.Sequence):\n    'Generates data from a Dataframe'\n    def __init__(self,csv_path,patientId , img_path ,batch_size=8, dim=(256,256), n_channels=3,\n                 n_classes=1, shuffle=True,transform=None , only_positive=True, preprocess = None):\n        \n        self.df = pd.read_csv(csv_path)\n        if only_positive:\n            self.df= self.df[self.df[\"Target\"]==1]\n            \n        self.img_path = img_path\n        self.patient_ids = patientId\n        \n        self.batch_size = batch_size\n        self.nb_iteration = int(len(self.patient_ids)/self.batch_size)\n        self.dim = dim\n        self.n_channels= n_channels\n        \n        self.preprocess =preprocess\n        \n        \n        self.TINY_YOLOV2_ANCHOR_PRIORS = np.array([1.08, 1.19, 3.42, 4.41, 6.63, 11.38, 9.42, 5.11, 16.62, 10.52]).reshape(5, 2)\n        self.network_output_shape = (8,8,5,6)\n    \n    \n                    \n    def __len__(self):\n        'Denotes the number of batches per epoch'\n        return self.nb_iteration\n\n    def __getitem__(self, index):\n        'Generate one batch of data'\n        \n        indicies = range(index, min(index+self.batch_size ,len(self.patient_ids) ))\n            \n        patientIds = self.patient_ids[indicies]\n        X = np.zeros((self.batch_size, self.dim[0], self.dim[1],self.n_channels))\n        y_boxes = []\n        y = np.zeros((self.batch_size,self.network_output_shape[0],self.network_output_shape[1],self.network_output_shape[2],self.network_output_shape[3]))\n        output_labels = []\n        \n        \n        for index , patientId in enumerate(patientIds):\n            filtered_df = self.df[self.df[\"patientId\"] == patientId]\n            img_path = os.path.join(self.img_path,patientId+\".dcm\" )\n            img = self.load_img(img_path)\n            \n            X[index]= img\n            y_boxes = []\n            labels = []\n            \n            for i, row in filtered_df.iterrows():\n                xmin = int(row['x'])\n                ymin = int(row['y'])\n                xmax = int(xmin + row['width'])\n                ymax = int(ymin + row['height'])\n                \n                xmin = int((xmin/1024)*self.dim[0])\n                xmax = int((xmax/1024)*self.dim[0])\n                \n                ymin = int((ymin/1024)*self.dim[1])\n                ymax = int((ymax/1024)*self.dim[1])\n                y_boxes.append([xmin,ymin,xmax,ymax])\n                \n                labels.append([1])\n                \n            \n            #run preprocess_bboxes\n            y[index] = processGroundTruth(np.array(y_boxes),np.array(labels), self.TINY_YOLOV2_ANCHOR_PRIORS , self.network_output_shape)\n            \n\n        return X, y\n    \n    \n    \n    def load_img(self,img_path):\n        dcm_data = pydicom.read_file(img_path)\n        a = dcm_data.pixel_array\n\n        a=cv2.resize(a,(self.dim))\n        if self.n_channels == 3:\n            a = skimage.color.gray2rgb(a)\n        \n        \n        \n        if self.preprocess != None:\n            a= self.preprocess(a)\n        \n        a = exposure.equalize_adapthist(a)\n        \n        return a\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import random\n\ncsv_path= \"/kaggle/input/rsna-pneumonia-detection-challenge/stage_2_train_labels.csv\"\nimages_path = \"/kaggle/input/rsna-pneumonia-detection-challenge/stage_2_train_images/\"\n\ndf = pd.read_csv(csv_path)\ndf= df[df[\"Target\"]==1]\n\nrandom.seed(42)\npatient_ids = df[\"patientId\"].unique()\nrandom.shuffle(patient_ids)\n\nvalidation_split = 0.2\npatient_ids_train = patient_ids[int(len(patient_ids)*(validation_split)):]\npatient_ids_validation = patient_ids[:int(len(patient_ids)*(validation_split))]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow.keras.applications.densenet import preprocess_input","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_generator = det_gen(csv_path,patient_ids_train, images_path ,preprocess=None )\nvalidation_generator = det_gen(csv_path,patient_ids_validation, images_path , preprocess=None)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"X,Y = next(enumerate(validation_generator))[1]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"Y.shape , X.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import matplotlib.pyplot as plt\nplt.imshow(X[2])\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"color = (255, 0, 0) \n  \n# Line thickness of 2 px \nthickness = 2\n\n\nfor xx,yy in zip(X,Y):\n    for bbox in yy:\n        image = cv2.rectangle(xx, (bbox[0],bbox[1]), (bbox[2],bbox[3]), color, thickness)\n\n    plt.imshow(image)\n    plt.show()\n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!git clone https://github.com/ahmadelsallab/MultiCheXNet.git","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from MultiCheXNet.utils.Encoder import Encoder\nfrom MultiCheXNet.utils.Detector import Detector\nfrom MultiCheXNet.utils.ModelBlock import ModelBlock","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"encoder = Encoder()\ndetector_head = Detector(encoder, 256,1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = ModelBlock.add_heads(encoder ,[detector_head])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def loss( y_true, y_pred):\n        TINY_YOLOV2_ANCHOR_PRIORS = np.array([1.08, 1.19, 3.42, 4.41, 6.63, 11.38, 9.42, 5.11, 16.62, 10.52]).reshape(5, 2)\n        TINY_YOLOV2_ANCHOR_PRIORS = tf.convert_to_tensor(TINY_YOLOV2_ANCHOR_PRIORS, dtype= tf.float32)\n        \n        n_cells = y_pred.get_shape().as_list()[1]\n        y_true = tf.reshape(y_true, tf.shape(y_pred), name='y_true')\n        y_pred = tf.identity(y_pred, name='y_pred')\n\n        #### PROCESS PREDICTIONS ####\n        # get x-y coords (for now they are with respect to cell)\n        predicted_xy = tf.nn.sigmoid(y_pred[..., :2])\n\n        # convert xy coords to be with respect to image\n        cell_inds = tf.range(n_cells, dtype=tf.float32)\n        predicted_xy = tf.stack((\n            predicted_xy[..., 0] + tf.reshape(cell_inds, [1, -1, 1]),\n            predicted_xy[..., 1] + tf.reshape(cell_inds, [-1, 1, 1])\n        ), axis=-1)\n\n        # compute bb width and height\n        predicted_wh = TINY_YOLOV2_ANCHOR_PRIORS * tf.exp(y_pred[..., 2:4])\n\n        # compute predicted bb center and width\n        predicted_min = predicted_xy - predicted_wh / 2\n        predicted_max = predicted_xy + predicted_wh / 2\n\n        predicted_objectedness = tf.nn.sigmoid(y_pred[..., 4])\n        predicted_logits = tf.nn.softmax(y_pred[..., 5:])\n\n        #### PROCESS TRUE ####\n        true_xy = y_true[..., :2]\n        true_wh = y_true[..., 2:4]\n        true_logits = y_true[..., 5:]\n\n        true_min = true_xy - true_wh / 2\n        true_max = true_xy + true_wh / 2\n\n        #### compute iou between ground truth and predicted (used for objectedness) ####\n        intersect_mins = tf.maximum(predicted_min, true_min)\n        intersect_maxes = tf.minimum(predicted_max, true_max)\n        intersect_wh = tf.maximum(intersect_maxes - intersect_mins, 0.)\n        intersect_areas = intersect_wh[..., 0] * intersect_wh[..., 1]\n\n        true_areas = true_wh[..., 0] * true_wh[..., 1]\n        pred_areas = predicted_wh[..., 0] * predicted_wh[..., 1]\n\n        union_areas = pred_areas + true_areas - intersect_areas\n        iou_scores = intersect_areas / union_areas\n\n        #### Compute loss terms ####\n        responsibility_selector = y_true[..., 4]\n\n        xy_diff = tf.square(true_xy - predicted_xy) * responsibility_selector[..., None]\n        xy_loss = tf.reduce_sum(xy_diff, axis=[1, 2, 3, 4])\n\n        wh_diff = tf.square(tf.sqrt(true_wh) - tf.sqrt(predicted_wh)) * responsibility_selector[..., None]\n        wh_loss = tf.reduce_sum(wh_diff, axis=[1, 2, 3, 4])\n\n        obj_diff = tf.square(iou_scores - predicted_objectedness) * responsibility_selector\n        obj_loss = tf.reduce_sum(obj_diff, axis=[1, 2, 3])\n\n        best_iou = tf.reduce_max(iou_scores, axis=-1)\n        no_obj_diff = tf.square(0 - predicted_objectedness) * tf.cast(best_iou < 0.6, dtype=tf.float32)[..., None] * (\n                    1 - responsibility_selector)\n        no_obj_loss = tf.reduce_sum(no_obj_diff, axis=[1, 2, 3])\n\n        clf_diff = tf.square(true_logits - predicted_logits) * responsibility_selector[..., None]\n        clf_loss = tf.reduce_sum(clf_diff, axis=[1, 2, 3, 4])\n\n        object_coord_scale = 5\n        object_conf_scale = 1\n        noobject_conf_scale = 1\n        object_class_scale = 1\n\n        loss = object_coord_scale * (xy_loss + wh_loss) + \\\n               object_conf_scale * obj_loss + noobject_conf_scale * no_obj_loss + \\\n               object_class_scale * clf_loss\n        \n        if np.isnan(loss):\n            import ipdb;ipdb.set_trace()\n        \n        \n        return loss","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import tensorflow as tf\ndef calls(model_name):\n  checkpoint = tf.keras.callbacks.ModelCheckpoint(model_name,\n                             monitor='val_loss',\n                             verbose=1,\n                             save_best_only=True,\n                             save_weights_only=False,\n                             mode='min',\n                             period=1)\n  \n  early = tf.keras.callbacks.EarlyStopping(monitor='val_loss',\n                        min_delta=0,\n                        patience=10,\n                        verbose=1,\n                        mode='min')\n  \n  class myCallBack(tf.keras.callbacks.Callback):\n    def on_epoch_end(self, epoch, logs={}):\n      if (logs.get('val_accuracy') > 0.998):\n        print ('\\nReached 0.998 Validation accuracy!')\n        self.model.stop_training = True\n\n  my_call = myCallBack()\n\n  reduce_lr = tf.keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.05, patience=5,\n                              verbose=1, mode='min', min_delta=0,\n                              cooldown=0, min_lr=0)\n  \n  lr_schedule = tf.keras.callbacks.LearningRateScheduler(lambda epoch: 1e-5 * 10**(epoch / 10))\n  \n  return [checkpoint, early, reduce_lr]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"monitor = calls('model.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow.keras.optimizers import Adam\nmodel.compile(loss= detector_head.loss, optimizer= Adam(1e-4))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"num_epochs = 10\nmodel.fit_generator(train_generator, validation_data= validation_generator ,epochs=num_epochs ,\n                   callbacks=monitor)","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":{"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}