{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Overview\n\nPneumonia is an infection in one or both lungs. The infection causes inflammation in the air sacs in your lungs, which are called **alveoli**. The alveoli fill with fluid or pus, making it difficult to breathe.\n\n![Pneumonia Inflammation](https://www.physio-pedia.com/images/9/94/Pneumonia_Inflammation.jpg)\n","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"\nDoctors or radiologiests conduct a physical exam and use **CXR**(chest x-ray) to examin and detect pneumonia. In CXR it shows opacity in the reagion.\n\n![Pneumonia CXRs](https://ars.els-cdn.com/content/image/1-s2.0-S0092867418301545-figs6_lrg.jpg)\n\n\n* There are multiple causes of opacity n CXR other than pneumonia like;\n    * fluid overload (pulmonary edema)\n    * bleeding\n    * volume loss (atelectasis or collapse)\n    * lung cancer\n    * post-radiation or surgical changes\n    * Outside of the lungs, fluid in the pleural space (pleural effusion) \n\nA number of factors such as positioning of the patient and depth of inspiration can alter the appearance of the CXR.\n\n\n\nPneumonia opacity can occour in different reagions of chest and the opacity can be of different kinds. This makes it the problem of detection(regression) as well as recognition(classification). For such purpose we can think of using the pre-existing models like 'Faster R-CNN' or 'Yolo'.\n\n![Types and Regions](http://adigaskell.org/wp-content/uploads/2017/11/pneumonia-xray.jpg)\n\n\n","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"## Table of Contents\n\n**- MileStone 1**\n- Pre-Processing,-Data-Visualisation,-EDA-and-Model-Building\n- Exploring-the-given-Data-files,-classes-and-images-of-different-classes\n- Imports\n- Load-images\n- Load-Labels\n- Load-Classes\n- Show-bounding-box-on-the-image-to-identify-pneumonia\n- Dealing-with-missing-values\n- Get-Target-Labels-and-Classes-into-one-dataset\n- Visualisation-of-different-classes\n- Show-image-of-class-'No-Lung-Opacity-/-Not-Normal\n- Show-image-of-class-'Normal'\n- Show-image-of-class-'Lung-Opacity'\n- Show-images-with-multiple-bounding-boxes-as-applicable\n- Analysis-from-the-visualisation-of-different-classes\n \n**- MileStone 2** \n- Build-Model\n       \n\n   ","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"# Milestone 1: Pre-Processing, Data Visualisation, EDA and Model Building","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"## Exploring the given Data files, classes and images of different classes.","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"### Imports\n[Back to top](#Table-of-Contents)","execution_count":null},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import glob, pylab, pandas as pd\nimport numpy as np \nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom matplotlib.patches import Rectangle\nimport seaborn as sns\nimport gc\nimport glob\nimport os\nimport cv2\nimport pydicom\n\nimport warnings\nwarnings.simplefilter(action = 'ignore')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"> ### Load Files\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"detailed_df = pd.read_csv('/kaggle/input/rsna-pneumonia-detection-challenge/stage_2_detailed_class_info.csv')\ntrain_df = pd.read_csv('/kaggle/input/rsna-pneumonia-detection-challenge/stage_2_train_labels.csv')\n\nROOT_DIR = '/kaggle/working'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\ndetailed_df.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\ntrain_df.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"detailed_df.head()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.head()\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Merging the data tables detailed_df and train_df¶\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"df = pd.concat([train_df,detailed_df[\"class\"]],axis=1,sort=False)\ndf = df.drop_duplicates()\ndf.info()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Summary on the values, types and null values:¶\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"df.shape\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.isnull().sum()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Distribution of classes\n\nThe following output shows that the nearly 2/3 of the patients do not have pneumonia (with target value = 0) and 1/3 of the patients have pneumonia (with target value =1","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"pd.pivot_table(df,index=[\"Target\"], values=['patientId'], aggfunc='count')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Distribution of patients in each class\nThere are 9555 patients in the category 'Lung Opacity' and 11821 in 'No Lung Opacity / Not Normal' category and 8851 are in Normal category","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"pd.pivot_table(df,index=[\"class\"], values=['patientId'], aggfunc='count')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The classes \"No Lung Opacity / Not Normal\", \"Normal\", and \"Lung Opacity\" are in the proportion of 39%, 29% and 32% respectively","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"df[\"class\"].value_counts().plot(kind='pie',autopct='%1.0f%%', shadow=True, subplots=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"It is also clear from the below output that the patients who do not have pnuemonia do not have the bounding box coordinates","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"pd.pivot_table(df,index=[\"Target\"], aggfunc='count')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Count of patients having single row and more than single rows¶\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"df['patientId'].value_counts().value_counts()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Patients who do not have pneumonia has only one record in the table¶\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"df[df['Target'] == 0]['patientId'].value_counts().value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sns.countplot(x = 'class', hue = 'Target', data = df)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Preprocessing - Filling the null values\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"df.fillna(0.0)\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Correlation between the variables\nThere is a strong Correlation between height and width variables","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"df.corr()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sns.jointplot(x = 'width', y = 'height', data = df, kind=\"reg\")\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## EDA with the header values from the dataframe\n* Creating a data frame with all of their appropriate header values from the dicom file takes long time as there are 30277 records. Hence, the EDA analysis is done on a subset of randomly chosen 1000 records by keeping the same proportion of the classes. (i.e) The classes Not Normal, Normal, Lunge Opacity are in a proportion 39%, 29%, and 32% respectively.\n\n* Number of rows of Not Normal class = 39% of 1000 = 390 rows\n* Number of rows of Normal class = 29% of 1000 = 290 rows\n* Number of rows of Lunge Opacity class = 32% of 1000 = 320 rows","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"df_Not_Normal = df[df['class']=='No Lung Opacity / Not Normal'].sample(n=390)\ndf_Normal = df[df['class']=='Normal'].sample(n=290)\ndf_Lunge_Opacity = df[df['class']=='Lung Opacity'].sample(n=320)\nframes = [df_Not_Normal, df_Normal, df_Lunge_Opacity]\n\ndicom_df = pd.concat(frames)\n\ndicom_df.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def process_dicom_data(data_df):\n    for n, pid in enumerate(data_df['patientId'].unique()):        \n        dcm_file = '/kaggle/input/rsna-pneumonia-detection-challenge/stage_2_train_images/%s.dcm' % pid\n        dcm_data = pydicom.read_file(dcm_file)        \n        idx = (data_df['patientId']==dcm_data.PatientID)\n        data_df.loc[idx,'Modality'] = dcm_data.Modality\n        data_df.loc[idx,'PatientAge'] = pd.to_numeric(dcm_data.PatientAge)\n        data_df.loc[idx,'PatientSex'] = dcm_data.PatientSex\n        data_df.loc[idx,'BodyPartExamined'] = dcm_data.BodyPartExamined\n        data_df.loc[idx,'ViewPosition'] = dcm_data.ViewPosition\n        \n    return data_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dicom_df = process_dicom_data(dicom_df)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dicom_df = dicom_df.astype({\"PatientAge\": int})\ndicom_df.fillna(0.0, inplace=True)\ndicom_df.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"> There are 995 unique patient rows exist\n> ","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"dicom_df.nunique()\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Now Visualizing the data along with their dicom header values\n","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Patient's age proportion in the detection\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize = (30, 10))\nsns.countplot(x = 'PatientAge', hue = 'Target', data = dicom_df)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Patient's gender proportion in the detection\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"sns.countplot(x = 'PatientSex', hue = 'Target', data = dicom_df)\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"With respect to view proportion\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"sns.countplot(x = 'ViewPosition', hue = 'Target', data = dicom_df);\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dicom_df = dicom_df.drop('Target', axis=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dicom_df['PatientSex'].astype('category')\ndicom_df['ViewPosition'].astype('category')\ndicom_df['PatientSex'] = np.where(dicom_df[\"PatientSex\"].str.contains(\"M\"), 1, 0)\ndicom_df['ViewPosition'] = np.where(dicom_df[\"ViewPosition\"].str.contains(\"AP\"), 1, 0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dicom_df.head()\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Apart from the correlation between the width and height,there is no strong correlation between the other variables in the dataframe","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"dicom_df.corr()\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Visualizing the dicom images**\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def show_dicom_image(data_df):\n        img_data = list(data_df.T.to_dict().values())\n        f, ax = plt.subplots(2,2, figsize=(16,18))\n        for i,data_row in enumerate(img_data):\n            pid = data_row['patientId']\n            dcm_file = '/kaggle/input/rsna-pneumonia-detection-challenge/stage_2_train_images/%s.dcm' % pid\n            dcm_data = pydicom.read_file(dcm_file)                    \n            ax[i//2, i%2].imshow(dcm_data.pixel_array, cmap=plt.cm.bone)\n            ax[i//2, i%2].set_title('ID: {}\\n Age: {} Sex: {}'.format(\n                data_row['patientId'],dcm_data.PatientAge, dcm_data.PatientSex))\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"show_dicom_image(df[df['Target']==1].sample(n=4))\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"> Showing some random dicom images of a patient who do not have Pnuemonia, however with class No Lung Opacity / Not Normal","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"show_dicom_image(df[ (df['Target']==0) & (df['class']=='No Lung Opacity / Not Normal')].sample(n=4))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"> Showing some random dicom images of a patients who do not have Pnuemonia, however with class Normal","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"show_dicom_image(df[ (df['Target']==0) & (df['class']=='Normal')].sample(n=4))\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def show_dicome_with_boundingbox(data_df):\n    img_data = list(data_df.T.to_dict().values())\n    f, ax = plt.subplots(2,2, figsize=(16,18))\n    for i,data_row in enumerate(img_data):\n        pid = data_row['patientId']\n        dcm_file = '/kaggle/input/rsna-pneumonia-detection-challenge/stage_2_train_images/%s.dcm' % pid\n        dcm_data = pydicom.read_file(dcm_file)                    \n        ax[i//2, i%2].imshow(dcm_data.pixel_array, cmap=plt.cm.bone)\n        ax[i//2, i%2].set_title('ID: {}\\n Age: {} Sex: {}'.format(\n                data_row['patientId'],dcm_data.PatientAge, dcm_data.PatientSex))\n        rows = data_df[data_df['patientId']==data_row['patientId']]\n        box_data = list(rows.T.to_dict().values())        \n        for j, row in enumerate(box_data):            \n            x,y,width,height = row['x'], row['y'],row['width'],row['height']\n            rectangle = Rectangle(xy=(x,y),width=width, height=height, color=\"red\",alpha = 0.1)\n            ax[i//2, i%2].add_patch(rectangle)    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"show_dicome_with_boundingbox(df[df['Target']==1].sample(n=4))\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# MileStone 2\n# **Model Building**","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import keras\nfrom keras.models import Sequential,Input,Model\nfrom keras.layers import Dense, Dropout, Flatten\nfrom keras.layers import Conv2D, MaxPooling2D\nfrom keras.layers.normalization import BatchNormalization\nfrom keras.layers.advanced_activations import LeakyReLU\nfrom keras.utils import to_categorical\nimport os","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"images_list = os.listdir(\"/kaggle/input/rsna-pneumonia-detection-challenge/stage_2_train_images\")\ntest_image = os.listdir(\"/kaggle/input/rsna-pneumonia-detection-challenge/stage_2_test_images\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(images_list[0])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"ty=[]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"c=df[df['patientId']==images_list[1][:-4]]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"ty.append(c['class'].unique()[0])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"path=\"/kaggle/input/rsna-pneumonia-detection-challenge/stage_2_train_images/\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_x=[]\ntrain_y=[]\ndef makeDataset():\n    for i in range(len(images_list)%1500):\n        d=pydicom.read_file(path+images_list[i])\n        c=df[df['patientId']==images_list[i][:-4]]\n        train_y.append(c['class'].unique()[0])\n        train_x.append(d.pixel_array)\nmakeDataset()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Defining labels","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def label(s):\n    if s=='Normal':\n        return 0\n    if s=='No Lung Opacity / Not Normal':\n        return 1\n    if s=='Lung Opacity':\n        return 2","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Defining training parameters","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"train_y = list(map(label,train_y))\ntrain_y= np.stack(train_y)\ntrain_x = np.stack(train_x)\nbatch_size = 2\nepochs = 5\nnum_classes = 3","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_y = to_categorical(train_y)\ntrain_x=train_x.reshape(-1,1024,1024,1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_x.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_x = train_x.astype('float32')\ntrain_x = train_x / 255","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model= Sequential()\nmodel.add(Conv2D(32,kernel_size=(7,7),activation='linear',input_shape=(1024,1024,1),padding='same'))\nmodel.add(LeakyReLU(alpha=0.1))\nmodel.add(MaxPooling2D(pool_size=(7,7),padding='same'))\nmodel.add(Conv2D(64,kernel_size=(7,7),activation='linear',padding='same'))\nmodel.add(LeakyReLU(alpha=0.1))\nmodel.add(MaxPooling2D(pool_size=(7,7),padding='same'))\nmodel.add(Conv2D(128,kernel_size=(7,7),activation='linear',padding='same'))\nmodel.add(LeakyReLU(alpha=0.1))\nmodel.add(MaxPooling2D(pool_size=(7,7),padding='same'))\nmodel.add(Flatten())\nmodel.add(Dense(128,activation='linear'))\nmodel.add(LeakyReLU(alpha=0.1))\nmodel.add(Dense(num_classes,activation='softmax'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.Adam(),metrics=['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model_train = model.fit(train_x,train_y,batch_size=batch_size,epochs=epochs,verbose=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_eval = model.evaluate(train_x, train_y, verbose=0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Test loss:', test_eval[0])\nprint('Test accuracy:', test_eval[1])","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}