{"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":"markdown","source":"# RSNA 2022 Cerical Spine Fracture Detection\n**CSCI217 Project**","metadata":{}},{"cell_type":"markdown","source":"## Import Libraries","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\nimport tensorflow as tf\nimport tensorflow.keras.layers as tfl\nfrom tensorflow.keras import backend as K\nfrom sklearn.model_selection import StratifiedKFold\nfrom tensorflow.keras.preprocessing.image import load_img, img_to_array\nfrom tensorflow.keras.applications import EfficientNetB0\n\nimport os\nimport cv2\nimport glob\nimport pydicom as dicom\nimport nibabel as nib\nimport sys","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-01-05T04:56:49.306653Z","iopub.execute_input":"2023-01-05T04:56:49.30713Z","iopub.status.idle":"2023-01-05T04:56:55.964912Z","shell.execute_reply.started":"2023-01-05T04:56:49.307035Z","shell.execute_reply":"2023-01-05T04:56:55.963883Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Load Data","metadata":{}},{"cell_type":"markdown","source":"#### Load dataframes","metadata":{}},{"cell_type":"code","source":"df_train = pd.read_csv(\"/kaggle/input/rsna-2022-cervical-spine-fracture-detection/train.csv\")\ndf_test = pd.DataFrame({\"row_id\": ['1.2.826.0.1.3680043.22327_C1', '1.2.826.0.1.3680043.25399_C1', '1.2.826.0.1.3680043.5876_C1'], \n                        \"StudyInstanceUID\": ['1.2.826.0.1.3680043.22327', '1.2.826.0.1.3680043.25399', '1.2.826.0.1.3680043.5876'], \n                        \"prediction_type\": [\"C1\", \"C1\", \"C1\"]})  \n\ntrain_images_dir = '/kaggle/input/rsna-2022-cervical-spine-fracture-detection/train_images'\ntest_images_dir = '/kaggle/input/rsna-2022-cervical-spine-fracture-detection/test_images'\n\nnew_submission = []\nmeans = dict(zip(df_train.columns[1:], np.average(df_train.iloc[:,1:], axis=0, weights=df_train[\"patient_overall\"] + 1)))\nprediction_type = df_test['prediction_type'].tolist()\nsubmission = pd.read_csv('/kaggle/input/rsna-2022-cervical-spine-fracture-detection/sample_submission.csv')\nfor i in range(len(submission)):        \n    new_submission.append(means[prediction_type[i]])\nsubmission['fractured'] = new_submission\n\nprediction_type_mapping = df_test['prediction_type'].map({'C1': 0, 'C2': 1, 'C3': 2, 'C4': 3, 'C5': 4, 'C6': 5, 'C7': 6}).values\n\ndf_train.head()","metadata":{"execution":{"iopub.status.busy":"2023-01-05T04:56:55.967133Z","iopub.execute_input":"2023-01-05T04:56:55.967834Z","iopub.status.idle":"2023-01-05T04:56:56.017454Z","shell.execute_reply.started":"2023-01-05T04:56:55.967792Z","shell.execute_reply":"2023-01-05T04:56:56.016416Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Load Dicom Helper Function","metadata":{}},{"cell_type":"code","source":"def load_dicom(path, size = 64):\n    img=dicom.dcmread(path)\n    img.PhotometricInterpretation = 'YBR_FULL'\n    data=img.pixel_array\n    data=data-np.min(data)\n    if np.max(data) != 0:\n        data=data/np.max(data)\n    data=(data*255).astype(np.uint8)        \n    return cv2.cvtColor(data.reshape(512, 512), cv2.COLOR_GRAY2RGB)\n\n    \npatients = sorted(os.listdir(train_images_dir))","metadata":{"execution":{"iopub.status.busy":"2023-01-05T04:56:56.018969Z","iopub.execute_input":"2023-01-05T04:56:56.019407Z","iopub.status.idle":"2023-01-05T04:56:56.236652Z","shell.execute_reply.started":"2023-01-05T04:56:56.019361Z","shell.execute_reply":"2023-01-05T04:56:56.235805Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### visualize Images","metadata":{}},{"cell_type":"code","source":"image_file = glob.glob(\"/kaggle/input/rsna-2022-cervical-spine-fracture-detection/train_images/1.2.826.0.1.3680043.10001/*.dcm\")\nplt.figure(figsize=(20, 10))\n\nfor i in range(16):\n    ax = plt.subplot(4, 4, i + 1)\n    image_path = image_file[i]\n    image = load_dicom(image_path)\n    plt.axis('off')   \n    plt.imshow(image)","metadata":{"execution":{"iopub.status.busy":"2023-01-05T04:56:56.240086Z","iopub.execute_input":"2023-01-05T04:56:56.240952Z","iopub.status.idle":"2023-01-05T04:56:57.829075Z","shell.execute_reply.started":"2023-01-05T04:56:56.240915Z","shell.execute_reply":"2023-01-05T04:56:57.828258Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Create Data Generator\n(As data is so large that it can't fit in memory)","metadata":{}},{"cell_type":"code","source":"def RSNATrainGenerator(train_df, batch_size, infinite = True, base_path = train_images_dir):\n    while True:\n        trainset = []\n        trainidt = []\n        trainlabel = []\n        for i in (range(len(train_df))):\n            idt = train_df.loc[i, 'StudyInstanceUID']\n            path = os.path.join(base_path, idt)\n            for im in os.listdir(path):\n                dc = dicom.read_file(os.path.join(path,im))\n                if dc.file_meta.TransferSyntaxUID.name =='JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1])':\n                    continue\n                img = load_dicom(os.path.join(path , im))\n                img = cv2.resize(img, (128 , 128))\n                image = img_to_array(img)\n                image = image / 255.0\n                trainset += [image]\n                cur_label = [train_df.loc[i,f'C{j}'] for j in range(1,8)]\n                trainlabel += [cur_label]\n                trainidt += [idt]\n                if len(trainidt) == batch_size:                    \n                    yield np.array(trainset), np.array(trainlabel)\n                    trainset, trainlabel, trainidt = [], [], []\n            i+=1","metadata":{"execution":{"iopub.status.busy":"2023-01-05T04:56:57.830102Z","iopub.execute_input":"2023-01-05T04:56:57.830403Z","iopub.status.idle":"2023-01-05T04:56:57.8422Z","shell.execute_reply.started":"2023-01-05T04:56:57.830374Z","shell.execute_reply":"2023-01-05T04:56:57.841257Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def RSNATestGenerator(test_df, batch_size, infinite = True, base_path = test_images_dir):\n    while 1:        \n        testset=[]\n        testidt=[]\n        for i in (range(len(test_df))):        \n            if type(test_df) is list: idt = test_df[i]\n            else: idt = test_df['StudyInstanceUID'].iloc[i]\n            path = os.path.join(base_path, idt)\n            if os.path.exists(path):\n                for im in os.listdir(path):\n                    dc = dicom.read_file(os.path.join(path,im))\n                    if dc.file_meta.TransferSyntaxUID.name =='JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1])':\n                        continue\n                    img=load_dicom(os.path.join(path,im))\n                    img=cv2.resize(img,(128, 128))\n                    image=img_to_array(img)\n                    image=image/255.0\n                    testset+=[image]\n                    testidt+=[idt]\n                    if len(testset) == batch_size:                        \n                        yield np.array(testset)\n                        testset = []\n        if len(testset) > 0: yield np.array(testset)\n        if not infinite: break","metadata":{"execution":{"iopub.status.busy":"2023-01-05T04:56:57.843783Z","iopub.execute_input":"2023-01-05T04:56:57.844401Z","iopub.status.idle":"2023-01-05T04:56:57.85422Z","shell.execute_reply.started":"2023-01-05T04:56:57.844365Z","shell.execute_reply":"2023-01-05T04:56:57.853517Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data = RSNATrainGenerator(df_train, 64)\nsample = next(train_data)\nprint(\"input_shape:\", sample[0].shape)\nprint(\"target_shape:\", sample[1].shape)","metadata":{"execution":{"iopub.status.busy":"2023-01-05T04:56:57.855566Z","iopub.execute_input":"2023-01-05T04:56:57.85618Z","iopub.status.idle":"2023-01-05T04:57:01.831706Z","shell.execute_reply.started":"2023-01-05T04:56:57.856144Z","shell.execute_reply":"2023-01-05T04:57:01.830504Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Create Model","metadata":{"execution":{"iopub.status.busy":"2022-12-24T08:45:28.342629Z","iopub.execute_input":"2022-12-24T08:45:28.342996Z","iopub.status.idle":"2022-12-24T08:45:28.347812Z","shell.execute_reply.started":"2022-12-24T08:45:28.342963Z","shell.execute_reply":"2022-12-24T08:45:28.346634Z"}}},{"cell_type":"code","source":"def get_model1():       \n    eff_model = tf.keras.applications.EfficientNetB0(\n                    include_top=False,\n                    weights=\"imagenet\",\n                    pooling=\"max\")\n    \n    for layer in eff_model.layers[:-10]:\n        layer.trainable = False\n        \n        \n    inp = tfl.Input((128, 128 ,3))\n    x = eff_model(inp)\n    x = tfl.Dense(128, 'relu')(x)\n    x = tfl.Dropout(0.5)(x)\n    out = tfl.Dense(7, 'sigmoid')(x)\n    model = tf.keras.models.Model(inp, out)\n    model.compile(loss=\"binary_crossentropy\", optimizer = tf.keras.optimizers.Adam(learning_rate = 0.0001),\n                 metrics=[tf.keras.metrics.BinaryAccuracy()])\n    model.summary()\n    return model\n\nget_model1()","metadata":{"execution":{"iopub.status.busy":"2023-01-05T04:57:11.977455Z","iopub.execute_input":"2023-01-05T04:57:11.977883Z","iopub.status.idle":"2023-01-05T04:57:17.539297Z","shell.execute_reply.started":"2023-01-05T04:57:11.977846Z","shell.execute_reply":"2023-01-05T04:57:17.538133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_model2():\n    inp = tfl.Input((128, 128 ,3))\n    x = tfl.Conv2D(32, (3, 3), activation='relu')(inp)\n    x = tfl.MaxPooling2D((2, 2))(x)\n    x = tfl.Conv2D(64, (3, 3), activation='relu')(inp)\n    x = tfl.MaxPooling2D((2, 2))(x)\n    x = tfl.Conv2D(128, (3, 3), activation='relu')(inp)\n    x = tfl.MaxPooling2D((2, 2))(x)\n    x = tfl.Flatten()(x)\n    x = tfl.Dense(128, 'relu')(x)\n    x = tfl.Dropout(0.5)(x)\n    out = tfl.Dense(7, 'sigmoid')(x)\n    \n    model = tf.keras.models.Model(inp, out)\n    \n    model.layers[2].trainable = False\n    \n    model.compile(loss=\"binary_crossentropy\",\n                  optimizer = tf.keras.optimizers.Adam(learning_rate = 1e-4),\n                  metrics=[tf.keras.metrics.BinaryAccuracy()])\n    model.summary()\n    \n    return model\n\nget_model2()","metadata":{"execution":{"iopub.status.busy":"2023-01-05T04:57:17.541336Z","iopub.execute_input":"2023-01-05T04:57:17.541795Z","iopub.status.idle":"2023-01-05T04:57:17.610406Z","shell.execute_reply.started":"2023-01-05T04:57:17.541759Z","shell.execute_reply":"2023-01-05T04:57:17.609449Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_model_3():       \n    MobileNet_model = tf.keras.applications.MobileNet(\n    include_top=False,\n    weights='imagenet',\n    pooling=\"max\",\n)\n    \n    for layer in MobileNet_model.layers[:-10]:\n        layer.trainable = False\n        \n        \n    inp = tfl.Input((128, 128 ,3))\n    x = MobileNet_model(inp)\n    out = tfl.Dense(7, 'sigmoid')(x)\n    model = tf.keras.models.Model(inp, out)\n    model.compile(loss=\"binary_crossentropy\", optimizer = tf.keras.optimizers.Adam(learning_rate = 0.0001),\n                 metrics=[tf.keras.metrics.BinaryAccuracy()])\n    model.summary()\n    return model","metadata":{"execution":{"iopub.status.busy":"2023-01-05T04:57:17.611771Z","iopub.execute_input":"2023-01-05T04:57:17.612352Z","iopub.status.idle":"2023-01-05T04:57:17.619954Z","shell.execute_reply.started":"2023-01-05T04:57:17.612315Z","shell.execute_reply":"2023-01-05T04:57:17.618921Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_model_4():\n    DenseNet_model = tf.keras.applications.DenseNet121(\n    include_top=False,\n    weights='imagenet',\n    pooling=\"max\",\n)\n    \n    for layer in DenseNet_model.layers[:-10]:\n        layer.trainable = False\n        \n        \n    inp = tfl.Input((128, 128 ,3))\n    x = DenseNet_model(inp)\n    out = tfl.Dense(7, 'sigmoid')(x)\n    model = tf.keras.models.Model(inp, out)\n    model.compile(loss=\"binary_crossentropy\", optimizer = tf.keras.optimizers.Adam(learning_rate = 0.0001),\n                 metrics=[tf.keras.metrics.BinaryAccuracy()])\n    model.summary()\n    return model","metadata":{"execution":{"iopub.status.busy":"2023-01-05T04:57:17.622267Z","iopub.execute_input":"2023-01-05T04:57:17.622903Z","iopub.status.idle":"2023-01-05T04:57:17.631214Z","shell.execute_reply.started":"2023-01-05T04:57:17.622853Z","shell.execute_reply":"2023-01-05T04:57:17.630275Z"},"trusted":true},"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":"for train_idx, val_idx in StratifiedKFold(5).split(df_train, df_train['patient_overall']):    \n    K.clear_session()\n    x_train = df_train.iloc[train_idx].reset_index()\n    x_val = df_train.iloc[val_idx].reset_index()\n    \n    train_gen = RSNATrainGenerator(x_train, min(len(x_train), 64), infinite = False, base_path = train_images_dir)\n    val_gen = RSNATrainGenerator(x_val, min(len(x_val), 64), infinite = False, base_path = train_images_dir)\n    \n    model1 = get_model1()\n    model2 = get_model2()\n    \n    \n    hist1 = model1.fit_generator(                            \n        train_gen,\n        epochs = 5,\n        callbacks = [tf.keras.callbacks.EarlyStopping(monitor = 'val_loss', patience = 2, restore_best_weights = True)],\n        validation_steps = max((len(x_val) // 64), 1),\n        steps_per_epoch = max((len(x_train) // 64), 1),\n        validation_data = val_gen,\n      )\n    \n    hist2 = model2.fit_generator(                            \n        train_gen,\n        epochs = 5,\n        callbacks = [tf.keras.callbacks.EarlyStopping(monitor = 'val_loss', patience = 2, restore_best_weights = True)],\n        validation_steps = max((len(x_val) // 64), 1),\n        steps_per_epoch = max((len(x_train) // 64), 1),\n        validation_data = val_gen,\n      )\n    try: # the best we can do at the moment..\n        preds1 = model1.predict_generator(RSNATestGenerator(df_test, min(len(df_test), 64), infinite = False, base_path = test_images_dir), steps = max((len(df_test) // 64), 1))\n        preds2 = model2.predict_generator(RSNATestGenerator(df_test, min(len(df_test), 64), infinite = False, base_path = test_images_dir), steps = max((len(df_test) // 64), 1))\n        \n        new_preds = []\n        for pred_idx in range(len(preds1)):\n            new_preds.append(preds1[pred_idx][prediction_type_mapping[pred_idx]])\n        submission['fractured'] += np.array(new_preds) / 10\n        \n        new_preds = []\n        for pred_idx in range(len(preds2)):\n            new_preds.append(preds2[pred_idx][prediction_type_mapping[pred_idx]])\n        submission['fractured'] += np.array(new_preds) / 10\n        \n    except: traceback.print_exc()    ","metadata":{"execution":{"iopub.status.busy":"2023-01-05T04:57:17.632569Z","iopub.execute_input":"2023-01-05T04:57:17.633145Z","iopub.status.idle":"2023-01-05T05:03:06.03477Z","shell.execute_reply.started":"2023-01-05T04:57:17.633108Z","shell.execute_reply":"2023-01-05T05:03:06.033277Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission","metadata":{"execution":{"iopub.status.busy":"2023-01-05T04:57:02.25679Z","iopub.status.idle":"2023-01-05T04:57:02.257457Z","shell.execute_reply.started":"2023-01-05T04:57:02.257198Z","shell.execute_reply":"2023-01-05T04:57:02.257221Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.to_csv('submission.csv', index = 0)","metadata":{"execution":{"iopub.status.busy":"2023-01-05T04:57:02.258671Z","iopub.status.idle":"2023-01-05T04:57:02.25931Z","shell.execute_reply.started":"2023-01-05T04:57:02.259062Z","shell.execute_reply":"2023-01-05T04:57:02.259085Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"new_preds","metadata":{"execution":{"iopub.status.busy":"2023-01-05T04:57:02.260906Z","iopub.status.idle":"2023-01-05T04:57:02.26155Z","shell.execute_reply.started":"2023-01-05T04:57:02.26126Z","shell.execute_reply":"2023-01-05T04:57:02.261294Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission","metadata":{"execution":{"iopub.status.busy":"2023-01-05T04:57:02.263143Z","iopub.status.idle":"2023-01-05T04:57:02.263723Z","shell.execute_reply.started":"2023-01-05T04:57:02.263451Z","shell.execute_reply":"2023-01-05T04:57:02.263498Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.array(new_preds) / 5","metadata":{"execution":{"iopub.status.busy":"2023-01-05T04:57:02.265288Z","iopub.status.idle":"2023-01-05T04:57:02.267832Z","shell.execute_reply.started":"2023-01-05T04:57:02.267579Z","shell.execute_reply":"2023-01-05T04:57:02.267604Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}