{"cells":[{"metadata":{"_uuid":"d320f90f432c331afea02ef66fcddb59448ea200"},"cell_type":"markdown","source":"**** Attribution\nThanks to:\nflyyufrlix for : https://gist.github.com/flyyufelix/7e2eafb149f72f4d38dd661882c554a6\n* Jonne, Ashish and many other folks who worked on:\nhttps://www.kaggle.com/jonnedtc/cnn-segmentation-connected-components***\n*\n\n# Approach\n\n**I have used skeleton of following approach/code base  and tried replacing the model function with ResNet152 model and load it with pre trained weights  **\n\n* Firstly a convolutional neural network is used to segment the image, using the bounding boxes directly as a mask. \n* Secondly connected components is used to separate multiple nodules.\n* Finally a bounding box is simply drawn around every connected component.\n\n\n# Network\n**While RSNA input is (256,256,1) single channel (black and white)\nPre-trained ResNet152 model expects (256,256,3) three channel inputs. I have replicated same information across three channels while loading the images **\n\n* The network consists of a number of residual blocks with convolutions and downsampling blocks with max pooling.\n* At the end of the network a single upsampling layer converts the output to the same shape as the input.\n\nAs the input to the network is 256 by 256 (instead of the original 1024 by 1024) and the network downsamples a number of times without any meaningful upsampling (the final upsampling is just to match in 256 by 256 mask) the final prediction is very crude. If the network downsamples 4 times the final bounding boxes can only change with at least 16 pixels."},{"metadata":{"trusted":true,"_uuid":"0a86f0029240a20186b36b4267375f6ad6d0b65b"},"cell_type":"code","source":"import os\nos.listdir('../input/')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"41d8370cfa24507fa086f2bb9d70ee643efc5b9a"},"cell_type":"code","source":"os.listdir('../input/resnet152-pretrained-weights-tensorflow')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a7ca59625b7356a8e64a87bf930ee3656a72beef"},"cell_type":"code","source":"os.listdir('../input/rsna-pneumonia-detection-challenge')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# -*- coding: utf-8 -*-\n\"\"\"\nCreated on Sun Sep  2 23:20:23 2018\n\n@author: prasun.mishra\n\"\"\"\n\nimport os\nimport csv\nimport random\nimport pydicom\nimport numpy as np\nimport pandas as pd\nfrom skimage import measure\nfrom skimage.transform import resize\n\nimport tensorflow as tf\nfrom tensorflow import keras\n\nfrom matplotlib import pyplot as plt\n\n\n\nimport keras.layers\nfrom keras.models import Sequential\nfrom keras.optimizers import SGD\nfrom keras.layers import Input, Dense, Convolution2D, MaxPooling2D, AveragePooling2D, ZeroPadding2D, Dropout, Flatten, merge, Reshape, Activation\nfrom keras.layers.normalization import BatchNormalization\nfrom keras.models import Model\nfrom keras import backend as K\nfrom sklearn.metrics import log_loss\n#from ResNet.custom_layers.scale_layer import Scale\nimport sys\n###################################################################\nPATH = \"../input/rsna-pneumonia-detection-challenge/\"\nprint(\"Section 1 completed\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"81bbb95175348c08f9d6a2cabade70dafb9ac222"},"cell_type":"code","source":"###################################### Scale Layer whicch is a seprate file in original model, merged here############\nfrom keras.layers.core import Layer\nfrom keras.engine import InputSpec\nfrom keras import backend as K\n#from keras import initializations\nfrom keras import initializers as initializations\nimport tensorflow as tf\ntry:\n    from keras import initializations\nexcept ImportError:\n    from keras import initializers as initializations\n    \n    \n\nclass Scale(Layer):\n    '''Learns a set of weights and biases used for scaling the input data.\n    the output consists simply in an element-wise multiplication of the input\n    and a sum of a set of constants:\n\n        out = in * gamma + beta,\n\n    where 'gamma' and 'beta' are the weights and biases larned.\n\n    # Arguments\n        axis: integer, axis along which to normalize in mode 0. For instance,\n            if your input tensor has shape (samples, channels, rows, cols),\n            set axis to 1 to normalize per feature map (channels axis).\n        momentum: momentum in the computation of the\n            exponential average of the mean and standard deviation\n            of the data, for feature-wise normalization.\n        weights: Initialization weights.\n            List of 2 Numpy arrays, with shapes:\n            `[(input_shape,), (input_shape,)]`\n        beta_init: name of initialization function for shift parameter\n            (see [initializations](../initializations.md)), or alternatively,\n            Theano/TensorFlow function to use for weights initialization.\n            This parameter is only relevant if you don't pass a `weights` argument.\n        gamma_init: name of initialization function for scale parameter (see\n            [initializations](../initializations.md)), or alternatively,\n            Theano/TensorFlow function to use for weights initialization.\n            This parameter is only relevant if you don't pass a `weights` argument.\n    '''\n    \n    ###\n    #with tf.Session() as sess:\n        #sess.run(tf.global_variables_initializer())\n    ###\n    def __init__(self, weights=None, axis=-1, momentum = 0.9, beta_init='zero', gamma_init='one', **kwargs):\n        self.momentum = momentum\n        self.axis = axis\n        self.beta_init = initializations.get(beta_init)\n        self.gamma_init = initializations.get(gamma_init)\n        self.initial_weights = weights\n        super(Scale, self).__init__(**kwargs)\n\n    def build(self, input_shape):\n\n        \n        self.input_spec = [InputSpec(shape=input_shape)]\n        shape = (int(input_shape[self.axis]),)\n\n        # Compatibility with TensorFlow >= 1.0.0\n        self.gamma = K.variable(self.gamma_init(shape), name='{}_gamma'.format(self.name))\n        self.beta = K.variable(self.beta_init(shape), name='{}_beta'.format(self.name))\n        #self.gamma = self.gamma_init(shape, name='{}_gamma'.format(self.name))\n        #self.beta = self.beta_init(shape, name='{}_beta'.format(self.name))\n        self.trainable_weights = [self.gamma, self.beta]\n\n        if self.initial_weights is not None:\n            self.set_weights(self.initial_weights)\n            del self.initial_weights\n\n    def call(self, x, mask=None):\n        input_shape = self.input_spec[0].shape\n        broadcast_shape = [1] * len(input_shape)\n        broadcast_shape[self.axis] = input_shape[self.axis]\n\n        out = K.reshape(self.gamma, broadcast_shape) * x + K.reshape(self.beta, broadcast_shape)\n        return out\n\n    def get_config(self):\n        config = {\"momentum\": self.momentum, \"axis\": self.axis}\n        base_config = super(Scale, self).get_config()\n        return dict(list(base_config.items()) + list(config.items()))\nprint(\"Section 2 Scale Layer  completed\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c7ec47be860a8e11c3484436cad9ee5ef849bba8"},"cell_type":"code","source":"#############ResNet Model definition########################\n\nsys.setrecursionlimit(3000)\n\ndef identity_block(input_tensor, kernel_size, filters, stage, block):\n    '''The identity_block is the block that has no conv layer at shortcut\n    # Arguments\n        input_tensor: input tensor\n        kernel_size: defualt 3, the kernel size of middle conv layer at main path\n        filters: list of integers, the nb_filters of 3 conv layer at main path\n        stage: integer, current stage label, used for generating layer names\n        block: 'a','b'..., current block label, used for generating layer names\n    '''\n    eps = 1.1e-5\n    nb_filter1, nb_filter2, nb_filter3 = filters\n    conv_name_base = 'res' + str(stage) + block + '_branch'\n    bn_name_base = 'bn' + str(stage) + block + '_branch'\n    scale_name_base = 'scale' + str(stage) + block + '_branch'\n\n    x = Convolution2D(nb_filter1, 1, 1, name=conv_name_base + '2a', bias=False)(input_tensor)\n    x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2a')(x)\n    x = Scale(axis=bn_axis, name=scale_name_base + '2a')(x)\n    x = Activation('relu', name=conv_name_base + '2a_relu')(x)\n\n    x = ZeroPadding2D((1, 1), name=conv_name_base + '2b_zeropadding')(x)\n    x = Convolution2D(nb_filter2, kernel_size, kernel_size,\n                      name=conv_name_base + '2b', bias=False)(x)\n    x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2b')(x)\n    x = Scale(axis=bn_axis, name=scale_name_base + '2b')(x)\n    x = Activation('relu', name=conv_name_base + '2b_relu')(x)\n\n    x = Convolution2D(nb_filter3, 1, 1, name=conv_name_base + '2c', bias=False)(x)\n    x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2c')(x)\n    x = Scale(axis=bn_axis, name=scale_name_base + '2c')(x)\n\n    #x = merge([x, input_tensor], mode='sum', name='res' + str(stage) + block)\n    x= keras.layers.Add()([x, input_tensor])\n    x = Activation('relu', name='res' + str(stage) + block + '_relu')(x)\n    return x\n\ndef conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)):\n    '''conv_block is the block that has a conv layer at shortcut\n    # Arguments\n        input_tensor: input tensor\n        kernel_size: defualt 3, the kernel size of middle conv layer at main path\n        filters: list of integers, the nb_filters of 3 conv layer at main path\n        stage: integer, current stage label, used for generating layer names\n        block: 'a','b'..., current block label, used for generating layer names\n    Note that from stage 3, the first conv layer at main path is with subsample=(2,2)\n    And the shortcut should have subsample=(2,2) as well\n    '''\n    eps = 1.1e-5\n    nb_filter1, nb_filter2, nb_filter3 = filters\n    conv_name_base = 'res' + str(stage) + block + '_branch'\n    bn_name_base = 'bn' + str(stage) + block + '_branch'\n    scale_name_base = 'scale' + str(stage) + block + '_branch'\n\n    x = Convolution2D(nb_filter1, 1, 1, subsample=strides,\n                      name=conv_name_base + '2a', bias=False)(input_tensor)\n    x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2a')(x)\n    x = Scale(axis=bn_axis, name=scale_name_base + '2a')(x)\n    x = Activation('relu', name=conv_name_base + '2a_relu')(x)\n\n    x = ZeroPadding2D((1, 1), name=conv_name_base + '2b_zeropadding')(x)\n    x = Convolution2D(nb_filter2, kernel_size, kernel_size,\n                      name=conv_name_base + '2b', bias=False)(x)\n    x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2b')(x)\n    x = Scale(axis=bn_axis, name=scale_name_base + '2b')(x)\n    x = Activation('relu', name=conv_name_base + '2b_relu')(x)\n\n    x = Convolution2D(nb_filter3, 1, 1, name=conv_name_base + '2c', bias=False)(x)\n    x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2c')(x)\n    x = Scale(axis=bn_axis, name=scale_name_base + '2c')(x)\n\n    shortcut = Convolution2D(nb_filter3, 1, 1, subsample=strides,\n                             name=conv_name_base + '1', bias=False)(input_tensor)\n    shortcut = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '1')(shortcut)\n    shortcut = Scale(axis=bn_axis, name=scale_name_base + '1')(shortcut)\n\n    #x = merge([x, shortcut], mode='sum', name='res' + str(stage) + block)\n    x= keras.layers.Add()([x, shortcut])\n    x = Activation('relu', name='res' + str(stage) + block + '_relu')(x)\n    return x\n\ndef resnet152_model(img_rows, img_cols, color_type=1, num_classes=None):\n    \"\"\"\n    Resnet 152 Model for Keras\n\n    Model Schema and layer naming follow that of the original Caffe implementation\n    https://github.com/KaimingHe/deep-residual-networks\n\n    ImageNet Pretrained Weights \n    Theano: https://drive.google.com/file/d/0Byy2AcGyEVxfZHhUT3lWVWxRN28/view?usp=sharing\n    TensorFlow: https://drive.google.com/file/d/0Byy2AcGyEVxfeXExMzNNOHpEODg/view?usp=sharing\n\n    Parameters:\n      img_rows, img_cols - resolution of inputs\n      channel - 1 for grayscale, 3 for color \n      num_classes - number of class labels for our classification task\n    \"\"\"\n    eps = 1.1e-5\n\n    # Handle Dimension Ordering for different backends\n    global bn_axis\n    if K.image_dim_ordering() == 'tf':\n      bn_axis = 3\n      img_input = Input(shape=(img_rows, img_cols, color_type), name='data')\n    else:\n      bn_axis = 1\n      img_input = Input(shape=(color_type, img_rows, img_cols), name='data')\n\n    x = ZeroPadding2D((3, 3), name='conv1_zeropadding')(img_input)\n    x = Convolution2D(64, 7, 7, subsample=(2, 2), name='conv1', bias=False)(x)\n    x = BatchNormalization(epsilon=eps, axis=bn_axis, name='bn_conv1')(x)\n    x = Scale(axis=bn_axis, name='scale_conv1')(x)\n    x = Activation('relu', name='conv1_relu')(x)\n    x = MaxPooling2D((3, 3), strides=(2, 2), name='pool1')(x)\n\n    x = conv_block(x, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1))\n    x = identity_block(x, 3, [64, 64, 256], stage=2, block='b')\n    x = identity_block(x, 3, [64, 64, 256], stage=2, block='c')\n\n    x = conv_block(x, 3, [128, 128, 512], stage=3, block='a')\n    for i in range(1,8):\n      x = identity_block(x, 3, [128, 128, 512], stage=3, block='b'+str(i))\n\n    x = conv_block(x, 3, [256, 256, 1024], stage=4, block='a')\n    for i in range(1,36):\n      x = identity_block(x, 3, [256, 256, 1024], stage=4, block='b'+str(i))\n\n    x = conv_block(x, 3, [512, 512, 2048], stage=5, block='a')\n    x = identity_block(x, 3, [512, 512, 2048], stage=5, block='b')\n    x = identity_block(x, 3, [512, 512, 2048], stage=5, block='c')\n\n    x_fc = AveragePooling2D((7, 7), name='avg_pool')(x)\n    x_fc = Flatten()(x_fc)\n    x_fc = Dense(1000, activation='softmax', name='fc1000')(x_fc)\n\n    model = Model(img_input, x_fc)\n\n    if K.image_dim_ordering() == 'th':\n      # Use pre-trained weights for Theano backend\n      weights_path ='../input/resnet152-pretrained-weights-tensorflow/resnet152_weights_th.h5'\n    else:\n      # Use pre-trained weights for Tensorflow backend\n      print(\"Loading weights for Tensorflow\")\n      weights_path ='../input/resnet152-pretrained-weights-tensorflow/resnet152_weights_tf.h5'\n\n    model.load_weights(weights_path, by_name=True)\n\n    # Truncate and replace softmax layer for transfer learning\n    # Cannot use model.layers.pop() since model is not of Sequential() type\n    # The method below works since pre-trained weights are stored in layers but not in the model\n    x_newfc = AveragePooling2D((7, 7), name='avg_pool')(x)\n    \n    \n    # output\n    depth=8\n    x_newfc = keras.layers.BatchNormalization(momentum=0.9)(x_newfc)\n    x_newfc = keras.layers.LeakyReLU(0)(x_newfc)\n    x_newfc = keras.layers.Conv2D(1, 1, activation='sigmoid')(x_newfc)\n    x_newfc = keras.layers.UpSampling2D(2**depth)(x_newfc)\n    \"\"\"\n    x_newfc = Flatten()(x_newfc)\n    x_newfc = Dense(num_classes, activation='softmax', name='fc8')(x_newfc)\n    \"\"\"\n    model = Model(img_input, x_newfc)\n\n    return model\n\nprint(\"Section 3 ResNet Model function completed\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"470b4c4cd03f8d86a270a90d9d229d71152ef139"},"cell_type":"code","source":" #Original Skeleton##############################\n# empty dictionary\npneumonia_locations = {}\n# load table\nwith open(os.path.join(PATH+'stage_1_train_labels.csv'), mode='r') as infile:\n    # open reader\n    reader = csv.reader(infile)\n    # skip header\n    next(reader, None)\n    # loop through rows\n    for rows in reader:\n        # retrieve information\n        filename = rows[0]\n        location = rows[1:5]\n        pneumonia = rows[5]\n        # if row contains pneumonia add label to dictionary\n        # which contains a list of pneumonia locations per filename\n        if pneumonia == '1':\n            # convert string to float to int\n            location = [int(float(i)) for i in location]\n            # save pneumonia location in dictionary\n            if filename in pneumonia_locations:\n                pneumonia_locations[filename].append(location)\n            else:\n                pneumonia_locations[filename] = [location]\n                \n                \n# load and shuffle filenames\nfolder = PATH+'stage_1_train_images'\nfilenames = os.listdir(folder)\nrandom.shuffle(filenames)\n# split into train and validation filenames\nn_valid_samples = 2560\ntrain_filenames = filenames[n_valid_samples:]\nvalid_filenames = filenames[:n_valid_samples]\nprint('n train samples', len(train_filenames))\nprint('n valid samples', len(valid_filenames))\nn_train_samples = len(filenames) - n_valid_samples\n\n\n\nprint('Total train images:',len(filenames))\nprint('Images with pneumonia:', len(pneumonia_locations))\n\nns = [len(value) for value in pneumonia_locations.values()]\nplt.figure()\nplt.hist(ns)\nplt.xlabel('Pneumonia per image')\nplt.xticks(range(1, np.max(ns)+1))\nplt.show()\n\nheatmap = np.zeros((1024, 1024))\nws = []\nhs = []\nfor values in pneumonia_locations.values():\n    for value in values:\n        x, y, w, h = value\n        heatmap[y:y+h, x:x+w] += 1\n        ws.append(w)\n        hs.append(h)\nplt.figure()\nplt.title('Pneumonia location heatmap')\nplt.imshow(heatmap)\nplt.figure()\nplt.title('Pneumonia height lengths')\nplt.hist(hs, bins=np.linspace(0,1000,50))\nplt.show()\nplt.figure()\nplt.title('Pneumonia width lengths')\nplt.hist(ws, bins=np.linspace(0,1000,50))\nplt.show()\nprint('Minimum pneumonia height:', np.min(hs))\nprint('Minimum pneumonia width: ', np.min(ws))\n\n\n#################### Class Generator#######################\n\nclass generator(keras.utils.Sequence):\n       \n    def __init__(self, folder, filenames, pneumonia_locations=None, batch_size=8, image_size=256, shuffle=True, augment=False, predict=False):\n        self.folder = folder\n        self.filenames = filenames\n        self.pneumonia_locations = pneumonia_locations\n        self.batch_size = batch_size\n        self.image_size = image_size\n        self.shuffle = shuffle\n        self.augment = augment\n        self.predict = predict\n        self.on_epoch_end()\n        \n    def __load__(self, filename):\n        # load dicom file as numpy array\n        img = pydicom.dcmread(os.path.join(self.folder, filename)).pixel_array\n        # create empty mask\n        msk = np.zeros(img.shape)\n        # get filename without extension\n        filename = filename.split('.')[0]\n        # if image contains pneumonia\n        if filename in pneumonia_locations:\n            # loop through pneumonia\n            for location in pneumonia_locations[filename]:\n                # add 1's at the location of the pneumonia\n                x, y, w, h = location\n                msk[y:y+h, x:x+w] = 1\n        # if augment then horizontal flip half the time\n        if self.augment and random.random() > 0.5:\n            img = np.fliplr(img)\n            msk = np.fliplr(msk)\n        # resize both image and mask\n        img = resize(img, (self.image_size, self.image_size), mode='reflect')\n        msk = resize(msk, (self.image_size, self.image_size), mode='reflect') > 0.5\n        # add trailing channel dimension\n        img = np.expand_dims(img, -1)\n        msk = np.expand_dims(msk, -1)\n        ##############################\n        #print(\"img before:\",img)\n        img=np.stack([img] * 3, axis=-1)\n        msk=np.stack([msk]*3, axis=-1)\n        #img=np.dstack([img] * 3)\n        #msk=np.dstack([msk]*3)\n        # Reshape images as per the tensor format required by tensorflow\n        img = img.reshape(256,256,-1)\n        msk= msk.reshape (256,256,-1)\n        \n        #print(\"img shape after:\",img.shape())\n        ##############################\n        return img, msk\n    \n    def __loadpredict__(self, filename):\n        # load dicom file as numpy array\n        img = pydicom.dcmread(os.path.join(self.folder, filename)).pixel_array\n        # resize image\n        img = resize(img, (self.image_size, self.image_size), mode='reflect')\n        # add trailing channel dimension\n        img = np.expand_dims(img, -1)\n        return img\n        \n    def __getitem__(self, index):\n        # select batch\n        filenames = self.filenames[index*self.batch_size:(index+1)*self.batch_size]\n        # predict mode: return images and filenames\n        if self.predict:\n            # load files\n            imgs = [self.__loadpredict__(filename) for filename in filenames]\n            # create numpy batch\n            imgs = np.array(imgs)\n            return imgs, filenames\n        # train mode: return images and masks\n        else:\n            # load files\n            items = [self.__load__(filename) for filename in filenames]\n            # unzip images and masks\n            imgs, msks = zip(*items)\n            # create numpy batch\n            imgs = np.array(imgs)\n            msks = np.array(msks)\n            return imgs, msks\n        \n    def on_epoch_end(self):\n        if self.shuffle:\n            random.shuffle(self.filenames)\n        \n    def __len__(self):\n        if self.predict:\n            # return everything\n            return int(np.ceil(len(self.filenames) / self.batch_size))\n        else:\n            # return full batches only\n            return int(len(self.filenames) / self.batch_size)\n        \n############################################## Network ##########################      \n\n################################### Train Network\n    \n# define iou or jaccard loss function\ndef iou_loss(y_true, y_pred):\n    y_true = tf.reshape(y_true, [-1])\n    y_pred = tf.reshape(y_pred, [-1])\n    intersection = tf.reduce_sum(y_true * y_pred)\n    score = (intersection + 1.) / (tf.reduce_sum(y_true) + tf.reduce_sum(y_pred) - intersection + 1.)\n    return 1 - score\n\n# combine bce loss and iou loss\ndef iou_bce_loss(y_true, y_pred):\n    return 0.5 * keras.losses.binary_crossentropy(y_true, y_pred) + 0.5 * iou_loss(y_true, y_pred)\n\n# mean iou as a metric\ndef mean_iou(y_true, y_pred):\n    y_pred = tf.round(y_pred)\n    intersect = tf.reduce_sum(y_true * y_pred, axis=[1, 2, 3])\n    union = tf.reduce_sum(y_true, axis=[1, 2, 3]) + tf.reduce_sum(y_pred, axis=[1, 2, 3])\n    smooth = tf.ones(tf.shape(intersect))\n    return tf.reduce_mean((intersect + smooth) / (union - intersect + smooth))\n#################################################### Creat Model and Compile#######################\n# create network and compiler\n#model = create_network(input_size=512, channels=32, n_blocks=2, depth=8)\nmodel = resnet152_model(img_rows=256, img_cols=256, color_type=3, num_classes=10)\n\"\"\"\nmodel.compile(optimizer='adam',\n              loss=iou_bce_loss,\n              metrics=['accuracy', mean_iou])\n\"\"\"\n\n\nsgd = SGD(lr=1e-3, decay=1e-6, momentum=0.9, nesterov=True)\nmodel.compile(optimizer=sgd, loss= iou_bce_loss, metrics=['accuracy', mean_iou])\n\n\nprint(\"Section 4 Original Skeleton completed\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b0e3dda239ecd3c8fe7131d79cbfee977e686d8c"},"cell_type":"code","source":"##################### Print model summary \nmodel.summary()\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"9e627aa2085c488d8e34fbc035acd539911e3c9d"},"cell_type":"code","source":"\"\"\"\nimport pydot\nimport keras.utils\nimport os\n#os.environ[\"PATH\"] += os.pathsep + 'C:/Program Files (x86)/Graphviz2.38/bin/'\nkeras.utils.plot_model(model, to_file='model.png', show_shapes=True, show_layer_names=True, rankdir='TB')\n\"\"\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"fb071a48a60600bbaf0db4e973bfcdba86994470"},"cell_type":"code","source":"# cosine learning rate annealing\ndef cosine_annealing(x):\n    lr = 0.01\n    epochs = 10\n    return lr*(np.cos(np.pi*x/epochs)+1.)/2\nlearning_rate = tf.keras.callbacks.LearningRateScheduler(cosine_annealing)\n################\n\n    \n########################\n# create train and validation generators\nfolder = PATH+'stage_1_train_images'\ntrain_gen = generator(folder, train_filenames, pneumonia_locations, batch_size=8, image_size=256, shuffle=True, augment=True, predict=False)\nvalid_gen = generator(folder, valid_filenames, pneumonia_locations, batch_size=8, image_size=256, shuffle=False, predict=False)\n######## To avoid problem off non initialized parameters###################\nwith tf.Session() as sess:\n    sess.run(tf.global_variables_initializer())\n    history = model.fit_generator(train_gen, validation_data=valid_gen, callbacks=[learning_rate], epochs=10, shuffle=True)\n\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"31832b64c6f516596c8616bd390e0810688a6b98"},"cell_type":"code","source":"##################################### Plot\nplt.figure(figsize=(12,4))\nplt.subplot(131)\nplt.plot(history.epoch, history.history[\"loss\"], label=\"Train loss\")\nplt.plot(history.epoch, history.history[\"val_loss\"], label=\"Valid loss\")\nplt.legend()\nplt.subplot(132)\nplt.plot(history.epoch, history.history[\"acc\"], label=\"Train accuracy\")\nplt.plot(history.epoch, history.history[\"val_acc\"], label=\"Valid accuracy\")\nplt.legend()\nplt.subplot(133)\nplt.plot(history.epoch, history.history[\"mean_iou\"], label=\"Train iou\")\nplt.plot(history.epoch, history.history[\"val_mean_iou\"], label=\"Valid iou\")\nplt.legend()\nplt.show()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8811a938538bdffe04f939803b235791e48d6373"},"cell_type":"code","source":"############################################## Predict Test Images\n\n# load and shuffle filenames\nfolder = PATH+'stage_1_test_images'\ntest_filenames = os.listdir(folder)\nprint('n test samples:', len(test_filenames))\n\n# create test generator with predict flag set to True\ntest_gen = generator(folder, test_filenames, None, batch_size=8, image_size=256, shuffle=False, predict=True)\n\n# create submission dictionary\nsubmission_dict = {}\n# loop through testset\nfor imgs, filenames in test_gen:\n    # predict batch of images\n    preds = model.predict(imgs)\n    # loop through batch\n    for pred, filename in zip(preds, filenames):\n        # resize predicted mask\n        pred = resize(pred, (1024, 1024), mode='reflect')\n        # threshold predicted mask\n        comp = pred[:, :, 0] > 0.5\n        # apply connected components\n        comp = measure.label(comp)\n        # apply bounding boxes\n        predictionString = ''\n        for region in measure.regionprops(comp):\n            # retrieve x, y, height and width\n            y, x, y2, x2 = region.bbox\n            height = y2 - y\n            width = x2 - x\n            # proxy for confidence score\n            conf = np.mean(pred[y:y+height, x:x+width])\n            # add to predictionString\n            predictionString += str(conf) + ' ' + str(x) + ' ' + str(y) + ' ' + str(width) + ' ' + str(height) + ' '\n        # add filename and predictionString to dictionary\n        filename = filename.split('.')[0]\n        submission_dict[filename] = predictionString\n    # stop if we've got them all\n    if len(submission_dict) >= len(test_filenames):\n        break\n\n# save dictionary as csv file\nsub = pd.DataFrame.from_dict(submission_dict,orient='index')\nsub.index.names = ['patientId']\nsub.columns = ['PredictionString']\nsub.to_csv('submissionResNet152.csv')\n","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}