{"cells":[{"metadata":{"trusted":true,"_uuid":"6348f4458c278443ce1a4e1c8d09378094a80d73"},"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport pydicom\nfrom sklearn.model_selection import train_test_split\nfrom keras.layers import *\nfrom keras.layers import SpatialDropout2D\nfrom keras.models import Model\nimport cv2\nimport random","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8fcf578b9ceedef2d7f9c9a8fd3931d9b82c1595","collapsed":true},"cell_type":"code","source":"input_size = 256\nbatch_size = 8","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2572f3261bff9f888bce3651a45af11bf2d747e6","collapsed":true},"cell_type":"code","source":"df_labels = pd.read_csv(\"../input/stage_1_train_labels.csv\")\ndf_class  = pd.read_csv(\"../input/stage_1_detailed_class_info.csv\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f139f213da4750b49688cd73d990c859128efa88","collapsed":true},"cell_type":"code","source":"df = df_labels\ndf[\"class\"] = df_class[\"class\"]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"984ddf41b6d7e21da3abfe37be89444c19eb8786","collapsed":true},"cell_type":"code","source":"ages = []\nsexes = []\nfor p_id in df_labels[\"patientId\"]:\n    ds = pydicom.read_file(\"../input/stage_1_train_images/{}.dcm\".format(str(p_id)))\n    ages.append(ds.PatientAge)\n    sexes.append(ds.PatientSex)\ndf[\"age\"] = ages\ndf[\"sex\"] = sexes\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ccb381101ad3e01ef5fb2f62c927b208b2c5bacf","collapsed":true},"cell_type":"code","source":"ids = df[\"patientId\"].values\nids_train, ids_test = train_test_split(ids)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5dfb02ab7995e37763843fc743225ec71cf60919"},"cell_type":"code","source":"df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b820302f20df471b2484d2ecbad10566292c3332","collapsed":true},"cell_type":"code","source":"input_img = Input((input_size, input_size, 1))\n\nx = Conv2D(32, (3, 3), activation=\"relu\")(input_img)\nx = MaxPooling2D((2, 2))(x)\n\nx = Conv2D(32, (3, 3), activation=\"relu\")(x)\n# x = GaussianNoise(0.2)(x)\nx = BatchNormalization()(x)\nx = MaxPooling2D((2, 2))(x)\n\nx = Dropout(0.1)(x)\nx = Conv2D(64, (3, 3), activation=\"relu\")(x)\nx = GaussianNoise(0.2)(x)\nx = BatchNormalization()(x)\nx = MaxPooling2D((2, 2))(x)\n\nx = Dropout(0.1)(x)\nx = Conv2D(64, (3, 3), activation=\"relu\")(x)\nx = BatchNormalization()(x)\n# x = GaussianNoise(0.2)(x)\nx = MaxPooling2D((2, 2))(x)\n\nx = Flatten()(x)\n\ninput_extra = Input((3,))\nx = Concatenate()([input_extra, x])\nx = Dropout(0.2)(x)\nx = Dense(1024, activation=\"relu\")(x)\nx = Dense(64, activation=\"relu\")(x)\nx = Dense(1, activation=\"sigmoid\")(x)\n\nextra_model = Model([input_img, input_extra], x)\nextra_model.compile(optimizer=\"ADAM\", loss=\"binary_crossentropy\", metrics=[\"accuracy\"])\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"98301f832cd1e90657a67272908e820791386b2b","collapsed":true},"cell_type":"code","source":"def random_crop(img, crop_max=0.1, shape=input_size):\n\n    crop_max = 128*crop_max\n    crop_x1 = int(random.uniform(0, crop_max))\n    crop_x2 = int(random.uniform(0, crop_max-crop_x1))\n    crop_y1 = int(random.uniform(0, crop_max))\n    crop_y2 = int(random.uniform(0, crop_max-crop_y1))\n    # cv2.imshow(\"\", img)\n    # cv2.waitKey()\n    img = img[crop_x1:128-crop_x2, crop_y1:128-crop_y2]\n    img = cv2.resize(img, (shape, shape))\n    # cv2.imshow(\"\", img)\n    # cv2.waitKey()\n    return img\n\ndef train_generator_extra(ids, train = True):\n    while True:\n        for start in range(0, len(ids), batch_size):\n            x_batch = []\n            y_batch = []\n            age_sex = []\n            end = min(start + batch_size, len(ids))\n            ids_train_batch = ids[start:end]\n            for id in ids_train_batch:\n                ds = pydicom.read_file(\"../input/stage_1_train_images/{}.dcm\".format(id))\n                img = ds.pixel_array\n                img = cv2.resize(img, (input_size, input_size))\n                img = random_crop(img)\n                img = np.expand_dims(img, axis=2)\n                \n                row = df.loc[df[\"patientId\"]==id].values[0]\n                y_val = int(row[5])\n                \n                age_sex_val = [1, 0] if row[8] == \"F\" else [0, 1]\n                age_sex_val.append(int(row[7])/100)\n                age_sex.append(age_sex_val)\n                x_batch.append(img)\n                y_batch.append(y_val)\n            x_batch = np.array(x_batch, np.float32) / 255\n            y_batch = np.array(y_batch, np.float32)\n            age_sex_batch = np.array(age_sex, np.float32)\n            if train:\n                yield [x_batch, age_sex_batch], y_batch\n            else:\n                yield [x_batch, age_sex_batch]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"4b70fc4bc21cbb8f2ead83de2671cf668a61d089"},"cell_type":"code","source":"extra_model.fit_generator(train_generator_extra(ids_train), steps_per_epoch=int(len(ids_train)/batch_size), epochs=2,\n                          validation_data=train_generator_extra(ids_test), validation_steps=int(len(ids_test)/batch_size))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"94485cc5dd7404b01ca652498e91e0c1871d7c4c"},"cell_type":"code","source":"def u_generator_extra(ids, train = True):\n    while True:\n        for start in range(0, len(ids), batch_size):\n            x_batch = []\n            y_batch = []\n            end = min(start + batch_size, len(ids))\n            ids_train_batch = ids[start:end]\n            for id in ids_train_batch:\n                ds = pydicom.read_file(\"../input/stage_1_train_images/{}.dcm\".format(id))\n                img = ds.pixel_array\n                img = cv2.resize(img, (input_size, input_size))\n                img = random_crop(img)\n                img = np.expand_dims(img, axis=2)\n                \n                row = df.loc[df[\"patientId\"]==id]\n                mask = np.zeros((input_size, input_size))\n                if not row.isnull().values.any():\n                    for box in row.values:\n                        mask[int(box[2]/4):int(box[2]/4+round(box[4]/4)), int(box[1]/4):int(box[1]/4+round(box[3]/4))] = np.ones((int(round(box[4]/4)), int(round(box[3]/4))))\n                \n                mask = np.expand_dims(mask, axis=2)\n                x_batch.append(img)\n                y_batch.append(mask)\n            x_batch = np.array(x_batch, np.float32) / 255\n            y_batch = np.array(y_batch, np.float32)\n            if train:\n                yield x_batch, y_batch\n            else:\n                yield x_batch","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"39091a144101c88f174cb53156b58e048e216155"},"cell_type":"code","source":"from keras.losses import binary_crossentropy\nimport keras.backend as K\n\n\ndef dice_coeff(y_true, y_pred):\n    smooth = 1.\n    y_true_f = K.flatten(y_true)\n    y_pred_f = K.flatten(y_pred)\n    intersection = K.sum(y_true_f * y_pred_f)\n    score = (2. * intersection + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)\n    return score\n\n\ndef dice_loss(y_true, y_pred):\n    loss = 1 - dice_coeff(y_true, y_pred)\n    return loss\n\n\ndef bce_dice_loss(y_true, y_pred):\n    loss = binary_crossentropy(y_true, y_pred) + dice_loss(y_true, y_pred)\n    return loss\n\n\ndef get_unet_256(input_shape=(256, 256, 1),\n                 num_classes=1):\n    inputs = Input(shape=input_shape)\n    # 256\n\n    down0 = Conv2D(32, (3, 3), padding='same')(inputs)\n    down0 = BatchNormalization()(down0)\n    down0 = Activation('relu')(down0)\n    down0 = Conv2D(32, (3, 3), padding='same')(down0)\n    down0 = BatchNormalization()(down0)\n    down0 = Activation('relu')(down0)\n    down0_pool = MaxPooling2D((2, 2), strides=(2, 2))(down0)\n    # 128\n\n    down1 = Conv2D(64, (3, 3), padding='same')(down0_pool)\n    down1 = BatchNormalization()(down1)\n    down1 = Activation('relu')(down1)\n    down1 = Conv2D(64, (3, 3), padding='same')(down1)\n    down1 = BatchNormalization()(down1)\n    down1 = Activation('relu')(down1)\n    down1_pool = MaxPooling2D((2, 2), strides=(2, 2))(down1)\n    # 64\n\n    down2 = Conv2D(128, (3, 3), padding='same')(down1_pool)\n    down2 = BatchNormalization()(down2)\n    down2 = Activation('relu')(down2)\n    down2 = Conv2D(128, (3, 3), padding='same')(down2)\n    down2 = BatchNormalization()(down2)\n    down2 = Activation('relu')(down2)\n    down2_pool = MaxPooling2D((2, 2), strides=(2, 2))(down2)\n    # 32\n\n    down3 = Conv2D(256, (3, 3), padding='same')(down2_pool)\n    down3 = BatchNormalization()(down3)\n    down3 = Activation('relu')(down3)\n    down3 = Conv2D(256, (3, 3), padding='same')(down3)\n    down3 = BatchNormalization()(down3)\n    down3 = Activation('relu')(down3)\n    down3_pool = MaxPooling2D((2, 2), strides=(2, 2))(down3)\n    # 16\n\n    down4 = Conv2D(512, (3, 3), padding='same')(down3_pool)\n    down4 = BatchNormalization()(down4)\n    down4 = Activation('relu')(down4)\n    down4 = Conv2D(512, (3, 3), padding='same')(down4)\n    down4 = BatchNormalization()(down4)\n    down4 = Activation('relu')(down4)\n    down4_pool = MaxPooling2D((2, 2), strides=(2, 2))(down4)\n    # 8\n\n    center = Conv2D(1024, (3, 3), padding='same')(down4_pool)\n    center = BatchNormalization()(center)\n    center = Activation('relu')(center)\n    center = Conv2D(1024, (3, 3), padding='same')(center)\n    center = BatchNormalization()(center)\n    center = Activation('relu')(center)\n    # center\n\n    up4 = UpSampling2D((2, 2))(center)\n    up4 = concatenate([down4, up4], axis=3)\n    up4 = Conv2D(512, (3, 3), padding='same')(up4)\n    up4 = BatchNormalization()(up4)\n    up4 = Activation('relu')(up4)\n    up4 = Conv2D(512, (3, 3), padding='same')(up4)\n    up4 = BatchNormalization()(up4)\n    up4 = Activation('relu')(up4)\n    up4 = Conv2D(512, (3, 3), padding='same')(up4)\n    up4 = BatchNormalization()(up4)\n    up4 = Activation('relu')(up4)\n    # 16\n\n    up3 = UpSampling2D((2, 2))(up4)\n    up3 = concatenate([down3, up3], axis=3)\n    up3 = Conv2D(256, (3, 3), padding='same')(up3)\n    up3 = BatchNormalization()(up3)\n    up3 = Activation('relu')(up3)\n    up3 = Conv2D(256, (3, 3), padding='same')(up3)\n    up3 = BatchNormalization()(up3)\n    up3 = Activation('relu')(up3)\n    up3 = Conv2D(256, (3, 3), padding='same')(up3)\n    up3 = BatchNormalization()(up3)\n    up3 = Activation('relu')(up3)\n    # 32\n\n    up2 = UpSampling2D((2, 2))(up3)\n    up2 = concatenate([down2, up2], axis=3)\n    up2 = Conv2D(128, (3, 3), padding='same')(up2)\n    up2 = BatchNormalization()(up2)\n    up2 = Activation('relu')(up2)\n    up2 = Conv2D(128, (3, 3), padding='same')(up2)\n    up2 = BatchNormalization()(up2)\n    up2 = Activation('relu')(up2)\n    up2 = Conv2D(128, (3, 3), padding='same')(up2)\n    up2 = BatchNormalization()(up2)\n    up2 = Activation('relu')(up2)\n    # 64\n\n    up1 = UpSampling2D((2, 2))(up2)\n    up1 = concatenate([down1, up1], axis=3)\n    up1 = Conv2D(64, (3, 3), padding='same')(up1)\n    up1 = BatchNormalization()(up1)\n    up1 = Activation('relu')(up1)\n    up1 = Conv2D(64, (3, 3), padding='same')(up1)\n    up1 = BatchNormalization()(up1)\n    up1 = Activation('relu')(up1)\n    up1 = Conv2D(64, (3, 3), padding='same')(up1)\n    up1 = BatchNormalization()(up1)\n    up1 = Activation('relu')(up1)\n    # 128\n\n    up0 = UpSampling2D((2, 2))(up1)\n    up0 = concatenate([down0, up0], axis=3)\n    up0 = Conv2D(32, (3, 3), padding='same')(up0)\n    up0 = BatchNormalization()(up0)\n    up0 = Activation('relu')(up0)\n    up0 = Conv2D(32, (3, 3), padding='same')(up0)\n    up0 = BatchNormalization()(up0)\n    up0 = Activation('relu')(up0)\n    up0 = Conv2D(32, (3, 3), padding='same')(up0)\n    up0 = BatchNormalization()(up0)\n    up0 = Activation('relu')(up0)\n    # 256\n\n    classify = Conv2D(num_classes, (1, 1), activation='sigmoid')(up0)\n\n    model = Model(inputs=inputs, outputs=classify)\n\n    model.compile(optimizer=\"ADAM\", loss=bce_dice_loss, metrics=[dice_coeff])\n\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2fb6f33a243d9ff18b8cd8c56df1529e650cfd33"},"cell_type":"code","source":"pred = extra_model.predict_generator(train_generator_extra(ids_train, train=False), steps=np.ceil(float(len(ids_train)) / float(batch_size)),)\nhard_ids = [ids_train[index] for index in range(len(ids_train)) if pred[index]<0.5]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"36c9b867cf61371f3d0d3eff77286ed76c9b7e91"},"cell_type":"code","source":"model = get_unet_256()\nmodel.fit_generator(u_generator_extra(hard_ids), steps_per_epoch = int(len(hard_ids)/batch_size))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"3dc8b647aca93f1422d820cde981a726924a61e2"},"cell_type":"code","source":"model.fit_generator(u_generator_extra(hard_ids), steps_per_epoch = int(len(hard_ids)/batch_size), epochs=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"89e877a874a8e8a5c41dc645bf3ee4bec72587fc"},"cell_type":"code","source":"import cv2\n\n# load and shuffle filenames\nfolder = '../input/stage_1_test_images'\ntest_filenames = os.listdir(folder)\nprint('n test samples:', len(test_filenames))\ntest_ids = [name[:-4] for name in test_filenames]\n\nsubmission_dict = {}\n\npred = extra_model.predict_generator(train_generator_extra(ids_train, train=False), steps=np.ceil(float(len(ids_train)) / float(batch_size)),)\nfor index, id_ in enumerate(test_ids):\n    \n    if pred[index] < 0.5:\n        submission_dict[id_] = \"\"\n    else:\n        mask = model.predict([folder+test_filenames[index]])[0]\n        im_gray = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)\n        ret, im_th = cv2.threshold(im_gray, 90, 255, cv2.THRESH_BINARY_INV)\n        _, ctrs, hier = cv2.findContours(im_th.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)\n        rects = [cv2.boundingRect(ctr) for ctr in ctrs]\n        boxstring = \"\"\n        for rect in rects:\n            boxstring += str[rect[0]]+ \" \" + str[rect[1]]+ \" \" + str[rect[2]]+ \" \" + str[rect[3]]\n        submission_dict[id_]  = boxstring\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('submission.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"b3ae953523d8a0355ba595870219bd99b188ac10"},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}