{"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":"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)\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torchvision.transforms as tvf\nimport torchvision\nfrom torch.utils.data import DataLoader, Dataset\nimport pytorch_lightning as pl\nfrom pytorch_lightning import LightningModule\n\nimport os\nfrom joblib import Parallel, delayed\nfrom tqdm import tqdm\nimport pydicom\nimport cv2\nfrom pathlib import Path\nfrom PIL import Image\nimport multiprocessing as mp\nfrom timm.data.transforms_factory import create_transform\nfrom timm.data.transforms_factory import create_transform\nfrom timm.loss import BinaryCrossEntropy\nfrom torch.utils.data import DataLoader\nfrom torch.utils.data import Dataset\nfrom tqdm.notebook import tqdm\nfrom PIL import Image\nfrom glob import glob\nimport glob\nimport cv2\nfrom keras.applications.resnet import ResNet50\nfrom keras.applications.densenet import DenseNet201\nfrom keras.applications.vgg16 import VGG16\nfrom sklearn.metrics import classification_report\n\n# import dicomsdl\n\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\n# import os\n# for 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 20GB 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","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-02-12T01:18:37.709246Z","iopub.execute_input":"2023-02-12T01:18:37.709885Z","iopub.status.idle":"2023-02-12T01:18:37.720677Z","shell.execute_reply.started":"2023-02-12T01:18:37.70985Z","shell.execute_reply":"2023-02-12T01:18:37.71927Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Goal of the Competition\n- The goal of this competition is to identify breast cancer. You'll train your model with screening mammograms obtained from regular screening.\n- Your work improving the automation of detection in screening mammography may enable radiologists to be more accurate and efficient, improving the quality and safety of patient care. It could also help reduce costs and unnecessary medical procedures.","metadata":{}},{"cell_type":"markdown","source":"# Dataset Description\n - Note: The dataset for this challenge contains radiographic breast images of female subjects.\nThe goal of this competition is to identify cases of breast cancer in mammograms from screening exams. It is important to identify cases of cancer for obvious reasons, but false positives also have downsides for patients.\n\n\n# Dataset\n- [train/test]_images/[patient_id]/[image_id].dcm The mammograms, in dicom format. You can expect roughly 8,000 patients in the hidden test set. There are usually but not always 4 images per patient. Note that many of the images use the jpeg 2000 format which may you may need special libraries to load.\n\n- [train/test].csv Metadata for each patient and image. Only the first few rows of the test set are available for download.\n- site_id - ID code for the source hospital.\n- patient_id - ID code for the patient.\n- image_id - ID code for the image.\n- laterality - Whether the image is of the left or right breast.\n- view - The orientation of the image. The default for a screening exam is to capture two views per breast.\n- age - The patient's age in years.\n- implant - Whether or not the patient had breast implants. Site 1 only provides breast implant information at the patient level, not at the breast level.\n- density - A rating for how dense the breast tissue is, with A being the least dense and D being the most dense. Extremely dense tissue can make diagnosis more difficult. Only provided for train.\n- machine_id - An ID code for the imaging device.\n- cancer - Whether or not the breast was positive for malignant cancer. The target value. Only provided for train.\n- biopsy - Whether or not a follow-up biopsy was performed on the breast. Only provided for train.\n- invasive - If the breast is positive for cancer, whether or not the cancer proved to be invasive. Only provided for train.\n- BIRADS - 0 if the breast required follow-up, 1 if the breast was rated as negative for cancer, and 2 if the breast was rated as normal. Only provided for train.\n- prediction_id - The ID for the matching submission row. Multiple images will share the same prediction ID. Test only.\n- difficult_negative_case - True if the case was unusually difficult. Only provided for train.","metadata":{}},{"cell_type":"code","source":"# ! pip install -U pylibjpeg pylibjpeg-openjpeg pylibjpeg-libjpeg pydicom python-gdcm\n# ! pip install --upgrade pydicom\n\n!pip install python-gdcm -q\n!pip install pylibjpeg -q","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:18:37.722804Z","iopub.execute_input":"2023-02-12T01:18:37.723397Z","iopub.status.idle":"2023-02-12T01:19:01.509701Z","shell.execute_reply.started":"2023-02-12T01:18:37.72334Z","shell.execute_reply":"2023-02-12T01:19:01.508497Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pydicom\nimport pandas as pd\nimport numpy as np\nfrom skimage import measure\nimport scipy\nfrom plotly.tools import FigureFactory as FF\nfrom plotly.graph_objs import *\nfrom scipy.ndimage import zoom\nfrom plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot\nimport plotly.express as px\n","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:01.51248Z","iopub.execute_input":"2023-02-12T01:19:01.512871Z","iopub.status.idle":"2023-02-12T01:19:03.532599Z","shell.execute_reply.started":"2023-02-12T01:19:01.512828Z","shell.execute_reply":"2023-02-12T01:19:03.531637Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\n# Number of GPU's available\ndef print_num_gpus_available() -> None:\n    \"\"\"\n    Prints the number of GPUs available on the current machine.\n    :return: None\n    \"\"\"\n    print(\"Number of GPUs Available: \", len(tf.config.experimental.list_physical_devices('GPU')))\nprint_num_gpus_available()","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:03.533912Z","iopub.execute_input":"2023-02-12T01:19:03.534288Z","iopub.status.idle":"2023-02-12T01:19:03.612493Z","shell.execute_reply.started":"2023-02-12T01:19:03.534253Z","shell.execute_reply":"2023-02-12T01:19:03.61127Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pydicom as dicom\n\n# DCM FIle path\nfile_path = '../input/rsna-breast-cancer-detection/train_images/10006/1459541791.dcm'\n\n# Reading the DCM File\nd_file = dicom.dcmread(file_path)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:03.615745Z","iopub.execute_input":"2023-02-12T01:19:03.616647Z","iopub.status.idle":"2023-02-12T01:19:03.670788Z","shell.execute_reply.started":"2023-02-12T01:19:03.616606Z","shell.execute_reply":"2023-02-12T01:19:03.669834Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Plotting the image\nplt.imshow(d_file.pixel_array, cmap='gray')","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:03.672111Z","iopub.execute_input":"2023-02-12T01:19:03.672484Z","iopub.status.idle":"2023-02-12T01:19:05.886438Z","shell.execute_reply.started":"2023-02-12T01:19:03.672445Z","shell.execute_reply":"2023-02-12T01:19:05.885296Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nos.listdir('/kaggle/input/rsna-breast-cancer-detection/train_images')[:10]","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:05.892347Z","iopub.execute_input":"2023-02-12T01:19:05.894446Z","iopub.status.idle":"2023-02-12T01:19:06.129616Z","shell.execute_reply.started":"2023-02-12T01:19:05.894407Z","shell.execute_reply":"2023-02-12T01:19:06.12874Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data = pd.read_csv('/kaggle/input/rsna-breast-cancer-detection/train.csv')\ntest_data = pd.read_csv('/kaggle/input/rsna-breast-cancer-detection/test.csv')\nsubmission_data = pd.read_csv('/kaggle/input/rsna-breast-cancer-detection/sample_submission.csv')\n\ntrain_data.head(3)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:06.130951Z","iopub.execute_input":"2023-02-12T01:19:06.131743Z","iopub.status.idle":"2023-02-12T01:19:06.260127Z","shell.execute_reply.started":"2023-02-12T01:19:06.131705Z","shell.execute_reply":"2023-02-12T01:19:06.259205Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_data = pd.read_csv('/kaggle/input/rsna-breast-cancer-detection/test.csv')\ntest_data.head()","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:06.261859Z","iopub.execute_input":"2023-02-12T01:19:06.262255Z","iopub.status.idle":"2023-02-12T01:19:06.278049Z","shell.execute_reply.started":"2023-02-12T01:19:06.262193Z","shell.execute_reply":"2023-02-12T01:19:06.276984Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#first 10 elements of the train_images folder, you will notice that the labels correspond to different patient ids\nos.listdir('/kaggle/input/rsna-breast-cancer-detection/train_images')[:10]","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:06.279745Z","iopub.execute_input":"2023-02-12T01:19:06.28016Z","iopub.status.idle":"2023-02-12T01:19:06.292247Z","shell.execute_reply.started":"2023-02-12T01:19:06.280119Z","shell.execute_reply":"2023-02-12T01:19:06.290845Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"patient_id = '47903'\n\nos.listdir(f'/kaggle/input/rsna-breast-cancer-detection/train_images/{patient_id}')","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:06.297176Z","iopub.execute_input":"2023-02-12T01:19:06.297472Z","iopub.status.idle":"2023-02-12T01:19:06.307752Z","shell.execute_reply.started":"2023-02-12T01:19:06.297447Z","shell.execute_reply":"2023-02-12T01:19:06.306606Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"idx = 5  # 0\n\nbase_img_dir = '/kaggle/input/rsna-breast-cancer-detection/train_images'\n\nimg_id = str(train_data['image_id'].iloc[idx])\nfull_img_id = img_id + '.dcm'\npat_id = str(train_data['patient_id'].iloc[idx])\n\nlabel = train_data['cancer'].iloc[idx]\n\nos.path.join(base_img_dir, pat_id, full_img_id)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:06.309461Z","iopub.execute_input":"2023-02-12T01:19:06.310086Z","iopub.status.idle":"2023-02-12T01:19:06.321822Z","shell.execute_reply.started":"2023-02-12T01:19:06.310047Z","shell.execute_reply":"2023-02-12T01:19:06.32061Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"img_path = os.path.join(base_img_dir, pat_id, full_img_id)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:06.323494Z","iopub.execute_input":"2023-02-12T01:19:06.323858Z","iopub.status.idle":"2023-02-12T01:19:06.331607Z","shell.execute_reply.started":"2023-02-12T01:19:06.323822Z","shell.execute_reply":"2023-02-12T01:19:06.330538Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dcm_img = pydicom.dcmread(img_path, force=True)\ndcm_img","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:06.333299Z","iopub.execute_input":"2023-02-12T01:19:06.333744Z","iopub.status.idle":"2023-02-12T01:19:06.426665Z","shell.execute_reply.started":"2023-02-12T01:19:06.333711Z","shell.execute_reply":"2023-02-12T01:19:06.425735Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_array = dcm_img.pixel_array\n\nplt.imshow(img_array)\nif label == 0:\n    category = \"doesn't have cancer\"\nelif label == 1:\n    category = \"has cancer\"\n\nplt.title(f'Patient {pat_id} {category} in image: {img_id}');","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:06.428285Z","iopub.execute_input":"2023-02-12T01:19:06.428979Z","iopub.status.idle":"2023-02-12T01:19:07.316961Z","shell.execute_reply.started":"2023-02-12T01:19:06.42894Z","shell.execute_reply":"2023-02-12T01:19:07.316077Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ! pip install -U pylibjpeg pylibjpeg-openjpeg pylibjpeg-libjpeg pydicom python-gdcm\n# ! pip install --upgrade pydicom","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:07.318644Z","iopub.execute_input":"2023-02-12T01:19:07.319335Z","iopub.status.idle":"2023-02-12T01:19:07.32374Z","shell.execute_reply.started":"2023-02-12T01:19:07.319298Z","shell.execute_reply":"2023-02-12T01:19:07.322573Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# !pip install pylibjpeg\n# !pip install pylibjpeg pylibjpeg-libjpeg pydicom","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:07.325157Z","iopub.execute_input":"2023-02-12T01:19:07.326843Z","iopub.status.idle":"2023-02-12T01:19:07.332751Z","shell.execute_reply.started":"2023-02-12T01:19:07.326806Z","shell.execute_reply":"2023-02-12T01:19:07.331783Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# !conda install gdcm -c conda-forge -y","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:07.334008Z","iopub.execute_input":"2023-02-12T01:19:07.334511Z","iopub.status.idle":"2023-02-12T01:19:07.342125Z","shell.execute_reply.started":"2023-02-12T01:19:07.334472Z","shell.execute_reply":"2023-02-12T01:19:07.341186Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import pylibjpeg\n# import gdcm\n# def random_9img_sample(\n#     df: pd.DataFrame, \n#     random_state: int = 101, \n#     base_img_dir = '/kaggle/input/rsna-breast-cancer-detection/train_images'\n# ):\n#     \"\"\"Function that shows 9 random images with labels and their img sizes\"\"\"\n#     df_sample = df.sample(9, random_state=random_state).reset_index()\n    \n#     fig, ax = plt.subplots(3, 3, figsize=(14, 14))\n    \n#     for idx_num, row in df_sample.iterrows():\n#         img_id = str(row['image_id'])\n#         full_img_id = img_id + '.dcm'\n#         pat_id = str(row['patient_id'])\n\n#         label = row['cancer']\n\n#         img_path = os.path.join(base_img_dir, pat_id, full_img_id)\n#         q, r = divmod(idx_num, 3)\n        \n#         img_array = pydicom.dcmread(img_path, force=True).pixel_array\n        \n        \n#         ax[q][r].imshow(img_array)\n#         ax[q][r].set_title(f'Image label is: {label}')","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:07.343798Z","iopub.execute_input":"2023-02-12T01:19:07.344149Z","iopub.status.idle":"2023-02-12T01:19:07.35207Z","shell.execute_reply.started":"2023-02-12T01:19:07.344115Z","shell.execute_reply":"2023-02-12T01:19:07.351056Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# random_9img_sample(train_data)\n","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:07.355028Z","iopub.execute_input":"2023-02-12T01:19:07.356541Z","iopub.status.idle":"2023-02-12T01:19:07.361486Z","shell.execute_reply.started":"2023-02-12T01:19:07.356505Z","shell.execute_reply":"2023-02-12T01:19:07.360464Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# !git clone --recurse-submodules https://github.com/tfmoraes/python-gdcm\n\n","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:07.362777Z","iopub.execute_input":"2023-02-12T01:19:07.363256Z","iopub.status.idle":"2023-02-12T01:19:07.37012Z","shell.execute_reply.started":"2023-02-12T01:19:07.363222Z","shell.execute_reply":"2023-02-12T01:19:07.369341Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#  !find . -name \"*.dcm\" -exec echo {} \\; -exec dicom-decompress --transcode {} {} \\;","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:07.371541Z","iopub.execute_input":"2023-02-12T01:19:07.372365Z","iopub.status.idle":"2023-02-12T01:19:07.378661Z","shell.execute_reply.started":"2023-02-12T01:19:07.372331Z","shell.execute_reply":"2023-02-12T01:19:07.377887Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\nimport tensorflow_io as tfio\n\nimage_bytes = tf.io.read_file('/kaggle/input/rsna-breast-cancer-detection/train_images/10011/220375232.dcm')\n\nimage = tfio.image.decode_dicom_image(image_bytes, dtype=tf.uint16)\n\nskipped = tfio.image.decode_dicom_image(image_bytes, on_error='skip', dtype=tf.uint8)\n\nlossy_image = tfio.image.decode_dicom_image(image_bytes, scale='auto', on_error='lossy', dtype=tf.uint8)\n\n\nfig, axes = plt.subplots(1,2, figsize=(10,10))\naxes[0].imshow(np.squeeze(image.numpy()), cmap='gray')\naxes[0].set_title('image')\naxes[1].imshow(np.squeeze(lossy_image.numpy()), cmap='gray')\naxes[1].set_title('lossy image');","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:07.37992Z","iopub.execute_input":"2023-02-12T01:19:07.381897Z","iopub.status.idle":"2023-02-12T01:19:15.403157Z","shell.execute_reply.started":"2023-02-12T01:19:07.381844Z","shell.execute_reply":"2023-02-12T01:19:15.40224Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# !conda install gdcm -c conda-forge -y\n","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:15.40421Z","iopub.execute_input":"2023-02-12T01:19:15.404562Z","iopub.status.idle":"2023-02-12T01:19:15.4144Z","shell.execute_reply.started":"2023-02-12T01:19:15.404526Z","shell.execute_reply":"2023-02-12T01:19:15.413286Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for element in dcm_img:\n    print(element)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:15.416847Z","iopub.execute_input":"2023-02-12T01:19:15.419467Z","iopub.status.idle":"2023-02-12T01:19:15.427242Z","shell.execute_reply.started":"2023-02-12T01:19:15.41943Z","shell.execute_reply":"2023-02-12T01:19:15.426354Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dcm_img.file_meta","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:15.42978Z","iopub.execute_input":"2023-02-12T01:19:15.432795Z","iopub.status.idle":"2023-02-12T01:19:15.44043Z","shell.execute_reply.started":"2023-02-12T01:19:15.432762Z","shell.execute_reply":"2023-02-12T01:19:15.439526Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Downsize MRI image \n\nimport pydicom\n\n\n# get the pixel information into a numpy array\ndata = dcm_img.pixel_array\nprint('The image has {} x {} voxels'.format(data.shape[0],\n                                            data.shape[1]))\ndata_downsampling = data[::8, ::8]\nprint('The downsampled image has {} x {} voxels'.format(\n    data_downsampling.shape[0], data_downsampling.shape[1]))\n\n# copy the data back to the original data set\ndcm_img.PixelData = data_downsampling.tobytes()\n# update the information regarding the shape of the data array\ndcm_img.Rows, dcm_img.Columns = data_downsampling.shape\n\n# print the image information given in the dataset\nprint('The information of the data set after downsampling: \\n')\nprint(dcm_img)\n","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:15.443236Z","iopub.execute_input":"2023-02-12T01:19:15.444552Z","iopub.status.idle":"2023-02-12T01:19:15.46246Z","shell.execute_reply.started":"2023-02-12T01:19:15.444521Z","shell.execute_reply":"2023-02-12T01:19:15.461273Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfrom pydicom import dcmread\nfrom pydicom.data import get_testdata_file\ndcm_img = pydicom.dcmread(img_path, force=True)\n\n# plot the image using matplotlib\nplt.imshow(dcm_img.pixel_array, cmap=plt.cm.gray)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:15.465722Z","iopub.execute_input":"2023-02-12T01:19:15.466346Z","iopub.status.idle":"2023-02-12T01:19:16.600389Z","shell.execute_reply.started":"2023-02-12T01:19:15.466311Z","shell.execute_reply":"2023-02-12T01:19:16.599501Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from glob import glob\npatient_id = '21867'\npatient_folder = f'/kaggle/input/rsna-breast-cancer-detection/train_images/{patient_id}/'\ndata_paths = glob(patient_folder + '/*/*.dcm')\n\n# Print out the first 5 file names to verify we're in the right folder.\nprint (f'Total of {len(data_paths)} DICOM images.\\nFirst 5 filenames:' )\ndata_paths[:50]","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:16.607864Z","iopub.execute_input":"2023-02-12T01:19:16.60822Z","iopub.status.idle":"2023-02-12T01:19:16.620886Z","shell.execute_reply.started":"2023-02-12T01:19:16.608177Z","shell.execute_reply":"2023-02-12T01:19:16.619491Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_image(image, cm = plt.bone()):\n        plt.figure(dpi=100)\n        plt.axes().set_aspect('equal', 'datalim')\n        plt.set_cmap(cm)\n        plt.pcolormesh(image)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:16.622445Z","iopub.execute_input":"2023-02-12T01:19:16.623105Z","iopub.status.idle":"2023-02-12T01:19:16.634058Z","shell.execute_reply.started":"2023-02-12T01:19:16.623069Z","shell.execute_reply":"2023-02-12T01:19:16.632753Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nfile_path = '../input/rsna-breast-cancer-detection/train_images/10006/1459541791.dcm'\n\n# Reading the DCM File\nd_file = dicom.dcmread(file_path)\nplot_image(d_file.pixel_array)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:16.635855Z","iopub.execute_input":"2023-02-12T01:19:16.637457Z","iopub.status.idle":"2023-02-12T01:19:29.352094Z","shell.execute_reply.started":"2023-02-12T01:19:16.637418Z","shell.execute_reply":"2023-02-12T01:19:29.351158Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def transform_to_hu(dicomData):\n    \n        \"\"\"\n        transforms a dicom pixel data to the Hounsfield units (HU) \n        scale and returns the transformed HU scale image.\n        \n        Args:\n            dicomData: the dataset in accordance \n                       with the DICOM File Format\n                       \n        Return:\n            hu_image: the image in the hu scale.\n        \"\"\"\n        intercept = dicomData.RescaleIntercept\n        slope = dicomData.RescaleSlope\n        pixel_array = dicomData.pixel_array\n\n        hu_image = pixel_array * slope + intercept\n\n        return hu_image","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:29.353663Z","iopub.execute_input":"2023-02-12T01:19:29.354735Z","iopub.status.idle":"2023-02-12T01:19:29.361146Z","shell.execute_reply.started":"2023-02-12T01:19:29.354695Z","shell.execute_reply":"2023-02-12T01:19:29.359616Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Hounsfield_units = transform_to_hu(dcm_img)\nHounsfield_units","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:29.362682Z","iopub.execute_input":"2023-02-12T01:19:29.363063Z","iopub.status.idle":"2023-02-12T01:19:29.420112Z","shell.execute_reply.started":"2023-02-12T01:19:29.363027Z","shell.execute_reply":"2023-02-12T01:19:29.419207Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transform_to_hu(d_file)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:29.421704Z","iopub.execute_input":"2023-02-12T01:19:29.422087Z","iopub.status.idle":"2023-02-12T01:19:29.513823Z","shell.execute_reply.started":"2023-02-12T01:19:29.422049Z","shell.execute_reply":"2023-02-12T01:19:29.512592Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def getDicomAttributesDictionary(dicomData):\n    \n        \"\"\"\n        Extracts the dicom data attributes and stores\n        them as a key value pair in the dictionary format.\n\n        Args:\n            dicomData: the dataset in accordance \n                           with the DICOM File Format\n        Return:\n            dicom attributes in the dictionary format.\n        \"\"\"\n        return ({attr : getattr(dicomData, attr) for attr in \n                 dir(dicomData) if attr[0].isupper() and attr not in ['PixelData']})","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:29.515475Z","iopub.execute_input":"2023-02-12T01:19:29.515883Z","iopub.status.idle":"2023-02-12T01:19:29.522131Z","shell.execute_reply.started":"2023-02-12T01:19:29.515848Z","shell.execute_reply":"2023-02-12T01:19:29.521007Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"getDicomAttributesDictionary(d_file)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:29.524033Z","iopub.execute_input":"2023-02-12T01:19:29.524485Z","iopub.status.idle":"2023-02-12T01:19:29.538099Z","shell.execute_reply.started":"2023-02-12T01:19:29.52444Z","shell.execute_reply":"2023-02-12T01:19:29.537232Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"getDicomAttributesDictionary(dcm_img)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:29.539612Z","iopub.execute_input":"2023-02-12T01:19:29.539904Z","iopub.status.idle":"2023-02-12T01:19:29.552384Z","shell.execute_reply.started":"2023-02-12T01:19:29.539879Z","shell.execute_reply":"2023-02-12T01:19:29.55145Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install -U dicomsdl","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:29.553887Z","iopub.execute_input":"2023-02-12T01:19:29.554345Z","iopub.status.idle":"2023-02-12T01:19:40.368677Z","shell.execute_reply.started":"2023-02-12T01:19:29.554311Z","shell.execute_reply":"2023-02-12T01:19:40.367468Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import dicomsdl as dicom\ndcom_img2 = dicom.open(\"/kaggle/input/rsna-breast-cancer-detection/train_images/10006/1459541791.dcm\")  # file i\n","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:40.370926Z","iopub.execute_input":"2023-02-12T01:19:40.371374Z","iopub.status.idle":"2023-02-12T01:19:40.396089Z","shell.execute_reply.started":"2023-02-12T01:19:40.371316Z","shell.execute_reply":"2023-02-12T01:19:40.395177Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dcom_img2.pixelData()","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:40.399109Z","iopub.execute_input":"2023-02-12T01:19:40.399403Z","iopub.status.idle":"2023-02-12T01:19:41.556206Z","shell.execute_reply.started":"2023-02-12T01:19:40.399377Z","shell.execute_reply":"2023-02-12T01:19:41.555058Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dcom_img2.getDataElement('RescaleSlope')","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:41.56125Z","iopub.execute_input":"2023-02-12T01:19:41.563783Z","iopub.status.idle":"2023-02-12T01:19:41.573691Z","shell.execute_reply.started":"2023-02-12T01:19:41.56373Z","shell.execute_reply":"2023-02-12T01:19:41.572268Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dcom_img2.getPixelDataInfo()","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:41.575551Z","iopub.execute_input":"2023-02-12T01:19:41.576228Z","iopub.status.idle":"2023-02-12T01:19:41.588104Z","shell.execute_reply.started":"2023-02-12T01:19:41.57617Z","shell.execute_reply":"2023-02-12T01:19:41.586436Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dcom_img2.toPilImage()","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:41.589631Z","iopub.execute_input":"2023-02-12T01:19:41.593466Z","iopub.status.idle":"2023-02-12T01:19:43.392617Z","shell.execute_reply.started":"2023-02-12T01:19:41.593423Z","shell.execute_reply":"2023-02-12T01:19:43.391248Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(dcom_img2.dump())","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:43.394384Z","iopub.execute_input":"2023-02-12T01:19:43.395171Z","iopub.status.idle":"2023-02-12T01:19:43.401083Z","shell.execute_reply.started":"2023-02-12T01:19:43.395121Z","shell.execute_reply":"2023-02-12T01:19:43.400084Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data.info()","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:43.402325Z","iopub.execute_input":"2023-02-12T01:19:43.403322Z","iopub.status.idle":"2023-02-12T01:19:43.4427Z","shell.execute_reply.started":"2023-02-12T01:19:43.403288Z","shell.execute_reply":"2023-02-12T01:19:43.441841Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(train_data['cancer'].describe())\nplt.figure(figsize=(9, 8))\nsns.distplot(train_data['cancer'], color='g', bins=100, hist_kws={'alpha': 0.4});\n","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:43.444136Z","iopub.execute_input":"2023-02-12T01:19:43.445113Z","iopub.status.idle":"2023-02-12T01:19:44.102283Z","shell.execute_reply.started":"2023-02-12T01:19:43.445068Z","shell.execute_reply":"2023-02-12T01:19:44.101369Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(train_data['BIRADS'].describe())\nplt.figure(figsize=(9, 8))\nsns.distplot(train_data['BIRADS'], color='g', bins=100, hist_kws={'alpha': 0.4});\n","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:44.103626Z","iopub.execute_input":"2023-02-12T01:19:44.104677Z","iopub.status.idle":"2023-02-12T01:19:44.607887Z","shell.execute_reply.started":"2023-02-12T01:19:44.104638Z","shell.execute_reply":"2023-02-12T01:19:44.607028Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ploting them distribution of all of the features\n# To do so lets first list all the types of our data from our dataset and take only the numerical ones:\nlist(set(train_data.dtypes.tolist()))","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:44.609362Z","iopub.execute_input":"2023-02-12T01:19:44.610024Z","iopub.status.idle":"2023-02-12T01:19:44.617219Z","shell.execute_reply.started":"2023-02-12T01:19:44.609995Z","shell.execute_reply":"2023-02-12T01:19:44.616179Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_num = train_data.select_dtypes(include = ['float64', 'int64'])\ntrain_num.head()","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:44.618672Z","iopub.execute_input":"2023-02-12T01:19:44.619584Z","iopub.status.idle":"2023-02-12T01:19:44.638796Z","shell.execute_reply.started":"2023-02-12T01:19:44.619549Z","shell.execute_reply":"2023-02-12T01:19:44.637951Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_num.hist(figsize=(16, 20), bins=50, xlabelsize=8, ylabelsize=8); ","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:44.640332Z","iopub.execute_input":"2023-02-12T01:19:44.640682Z","iopub.status.idle":"2023-02-12T01:19:47.02485Z","shell.execute_reply.started":"2023-02-12T01:19:44.640648Z","shell.execute_reply":"2023-02-12T01:19:47.023874Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# corr = train_num.corr()\n# corr.style.background_gradient(cmap='coolwarm')","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:47.029058Z","iopub.execute_input":"2023-02-12T01:19:47.03167Z","iopub.status.idle":"2023-02-12T01:19:47.036625Z","shell.execute_reply.started":"2023-02-12T01:19:47.031632Z","shell.execute_reply":"2023-02-12T01:19:47.035767Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"corr = train_num.corr()\nplt.figure(figsize=(11,8))\nsns.heatmap(corr, cmap=\"Greens\",annot=True)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:47.040969Z","iopub.execute_input":"2023-02-12T01:19:47.041985Z","iopub.status.idle":"2023-02-12T01:19:47.979799Z","shell.execute_reply.started":"2023-02-12T01:19:47.04195Z","shell.execute_reply":"2023-02-12T01:19:47.978939Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_num_corr = train_num.corr()['cancer'][:-1] # -1 because the latest row is SalePrice\nfeatures_list = train_num_corr[abs(train_num_corr) > 0.5].sort_values(ascending=False)\nprint(\"There is {} strongly correlated values with cancer:\\n{}\".format(len(features_list), features_list))","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:47.983942Z","iopub.execute_input":"2023-02-12T01:19:47.986714Z","iopub.status.idle":"2023-02-12T01:19:48.02305Z","shell.execute_reply.started":"2023-02-12T01:19:47.986676Z","shell.execute_reply":"2023-02-12T01:19:48.022252Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(15,15))\ncorr = train_num.corr()\nsns.heatmap(corr, annot=True, fmt='.2f', linewidth=.1, cmap='Blues', annot_kws={'size': 8});","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:48.027525Z","iopub.execute_input":"2023-02-12T01:19:48.029961Z","iopub.status.idle":"2023-02-12T01:19:48.725789Z","shell.execute_reply.started":"2023-02-12T01:19:48.029925Z","shell.execute_reply":"2023-02-12T01:19:48.724163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Map two features to the correlation values\ncorrs = {}\nfor row in corr.index.values:\n    for col in corr.columns:\n        if row != col:\n            corrs[(row,col)] = corr.loc[row,col].round(2)\n\n#Sort by most correlated\nprint('Most positive correlations:')\nfor (k1, k2), v in sorted(corrs.items(), key=lambda x: x[1], reverse=True):\n    if v >= .5:\n        print(f'{k1} & {k2}: {v}')\n        \nprint()\n\n#Sort by least correlated\nprint('Most negative correlations:')\nfor (k1, k2), v in sorted(corrs.items(), key=lambda x: x[1], reverse=True):\n    if v <= -.5:\n        print(f'{k1} & {k2}: {v}')","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:48.727238Z","iopub.execute_input":"2023-02-12T01:19:48.728292Z","iopub.status.idle":"2023-02-12T01:19:48.740033Z","shell.execute_reply.started":"2023-02-12T01:19:48.728248Z","shell.execute_reply":"2023-02-12T01:19:48.738999Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# The frequency of cancer stages\nB, M = train_num['cancer'].value_counts()\nprint('Number of Malignant : ', M)\nprint('Number of Benign: ', B)\n\nplt.figure(figsize=(10,6))\nsns.set_context('notebook', font_scale=1.5)\nsns.countplot('cancer',data=train_num, palette=\"Set1\")\nplt.annotate('Malignant = 212', xy=(-0.2, 250), xytext=(-0.2, 250), size=18, color='red')\nplt.annotate('Benign = 357', xy=(0.8, 250), xytext=(0.8, 250), size=18, color='w');","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:48.741312Z","iopub.execute_input":"2023-02-12T01:19:48.741869Z","iopub.status.idle":"2023-02-12T01:19:48.935441Z","shell.execute_reply.started":"2023-02-12T01:19:48.741834Z","shell.execute_reply":"2023-02-12T01:19:48.934505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in range(0, len(train_num.columns), 5):\n    sns.pairplot(data=train_num,\n                x_vars=train_num.columns[i:i+5],\n                y_vars=['cancer'])","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:48.936897Z","iopub.execute_input":"2023-02-12T01:19:48.937546Z","iopub.status.idle":"2023-02-12T01:19:50.837995Z","shell.execute_reply.started":"2023-02-12T01:19:48.93751Z","shell.execute_reply":"2023-02-12T01:19:50.836952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"corr = train_num.drop('cancer', axis=1).corr() \nplt.figure(figsize=(12, 10))\n\nsns.heatmap(corr[(corr >= 0.5) | (corr <= -0.4)], \n            cmap='viridis', vmax=1.0, vmin=-1.0, linewidths=0.1,\n            annot=True, annot_kws={\"size\": 8}, square=True);","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:50.839555Z","iopub.execute_input":"2023-02-12T01:19:50.840008Z","iopub.status.idle":"2023-02-12T01:19:51.215252Z","shell.execute_reply.started":"2023-02-12T01:19:50.839969Z","shell.execute_reply":"2023-02-12T01:19:51.214158Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"list(set(train_data.dtypes.tolist()))","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:51.216623Z","iopub.execute_input":"2023-02-12T01:19:51.21782Z","iopub.status.idle":"2023-02-12T01:19:51.225723Z","shell.execute_reply.started":"2023-02-12T01:19:51.217783Z","shell.execute_reply":"2023-02-12T01:19:51.224439Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_not_num = train_data.select_dtypes(include = ['O', 'bool'])\ntrain_not_num.head()","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:51.227367Z","iopub.execute_input":"2023-02-12T01:19:51.227981Z","iopub.status.idle":"2023-02-12T01:19:51.245105Z","shell.execute_reply.started":"2023-02-12T01:19:51.227917Z","shell.execute_reply":"2023-02-12T01:19:51.244096Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(train_not_num.isnull().sum())\n","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:51.246492Z","iopub.execute_input":"2023-02-12T01:19:51.24695Z","iopub.status.idle":"2023-02-12T01:19:51.260971Z","shell.execute_reply.started":"2023-02-12T01:19:51.246905Z","shell.execute_reply":"2023-02-12T01:19:51.259825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- One approach to imputing categorical features is to replace missing values with the most common class. We can do with by taking the index of the most common feature given in Pandas’ value_counts function.\n","metadata":{}},{"cell_type":"code","source":"train_not_num = train_not_num.apply(lambda x: x.fillna(x.value_counts().index[0]))\n","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:51.262729Z","iopub.execute_input":"2023-02-12T01:19:51.263128Z","iopub.status.idle":"2023-02-12T01:19:51.28694Z","shell.execute_reply.started":"2023-02-12T01:19:51.263092Z","shell.execute_reply":"2023-02-12T01:19:51.286038Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(train_not_num.isnull().sum())\n","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:51.28844Z","iopub.execute_input":"2023-02-12T01:19:51.288837Z","iopub.status.idle":"2023-02-12T01:19:51.301028Z","shell.execute_reply.started":"2023-02-12T01:19:51.288797Z","shell.execute_reply":"2023-02-12T01:19:51.300084Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(train_not_num.isnull().sum())\n","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:51.30236Z","iopub.execute_input":"2023-02-12T01:19:51.302994Z","iopub.status.idle":"2023-02-12T01:19:51.318009Z","shell.execute_reply.started":"2023-02-12T01:19:51.302959Z","shell.execute_reply":"2023-02-12T01:19:51.317084Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axes = plt.subplots(round(len(train_not_num.columns) / 3), 3, figsize=(10, 10))\n\nfor i, ax in enumerate(fig.axes):\n    if i < len(train_not_num.columns):\n        ax.set_xticklabels(ax.xaxis.get_majorticklabels(), rotation=45)\n        sns.countplot(x=train_not_num.columns[i], alpha=0.7, data=train_not_num, ax=ax)\n\nfig.tight_layout()","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:51.319499Z","iopub.execute_input":"2023-02-12T01:19:51.319837Z","iopub.status.idle":"2023-02-12T01:19:51.871139Z","shell.execute_reply.started":"2023-02-12T01:19:51.319804Z","shell.execute_reply":"2023-02-12T01:19:51.870156Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_num.head()","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:51.872762Z","iopub.execute_input":"2023-02-12T01:19:51.873099Z","iopub.status.idle":"2023-02-12T01:19:51.886164Z","shell.execute_reply.started":"2023-02-12T01:19:51.873063Z","shell.execute_reply":"2023-02-12T01:19:51.885035Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import seaborn as sns\n\n## First plot\nsns.lmplot(x=\"cancer\", y=\"invasive\", hue=\"biopsy\", data=train_num)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:51.888021Z","iopub.execute_input":"2023-02-12T01:19:51.888538Z","iopub.status.idle":"2023-02-12T01:19:55.764007Z","shell.execute_reply.started":"2023-02-12T01:19:51.8884Z","shell.execute_reply":"2023-02-12T01:19:55.762949Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.style.use('seaborn-whitegrid')\ntrain_num.hist(bins=20, figsize=(14, 10), color='skyblue')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:55.765944Z","iopub.execute_input":"2023-02-12T01:19:55.766326Z","iopub.status.idle":"2023-02-12T01:19:56.840438Z","shell.execute_reply.started":"2023-02-12T01:19:55.76629Z","shell.execute_reply":"2023-02-12T01:19:56.839325Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import seaborn as sns\n\n## First plot\nsns.lmplot(x=\"cancer\", y=\"invasive\", hue=\"biopsy\", data=train_num)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:19:56.842101Z","iopub.execute_input":"2023-02-12T01:19:56.842472Z","iopub.status.idle":"2023-02-12T01:20:00.545691Z","shell.execute_reply.started":"2023-02-12T01:19:56.842434Z","shell.execute_reply":"2023-02-12T01:20:00.544503Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data.columns","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:20:00.547333Z","iopub.execute_input":"2023-02-12T01:20:00.547722Z","iopub.status.idle":"2023-02-12T01:20:00.554458Z","shell.execute_reply.started":"2023-02-12T01:20:00.547685Z","shell.execute_reply":"2023-02-12T01:20:00.553509Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cancer_target = train_data.iloc[:,4]","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:20:00.555886Z","iopub.execute_input":"2023-02-12T01:20:00.556661Z","iopub.status.idle":"2023-02-12T01:20:00.577544Z","shell.execute_reply.started":"2023-02-12T01:20:00.556624Z","shell.execute_reply":"2023-02-12T01:20:00.576619Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cancer_target","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:20:00.578772Z","iopub.execute_input":"2023-02-12T01:20:00.579269Z","iopub.status.idle":"2023-02-12T01:20:00.591027Z","shell.execute_reply.started":"2023-02-12T01:20:00.579232Z","shell.execute_reply":"2023-02-12T01:20:00.58999Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data.shape","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:20:00.592583Z","iopub.execute_input":"2023-02-12T01:20:00.592936Z","iopub.status.idle":"2023-02-12T01:20:00.60263Z","shell.execute_reply.started":"2023-02-12T01:20:00.592901Z","shell.execute_reply":"2023-02-12T01:20:00.601653Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_data.shape","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:20:00.604035Z","iopub.execute_input":"2023-02-12T01:20:00.604513Z","iopub.status.idle":"2023-02-12T01:20:00.615133Z","shell.execute_reply.started":"2023-02-12T01:20:00.604479Z","shell.execute_reply":"2023-02-12T01:20:00.614187Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# !pip install pytorch-lightning==1.7.7\n# !pip install opencv-python","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:20:00.616695Z","iopub.execute_input":"2023-02-12T01:20:00.617111Z","iopub.status.idle":"2023-02-12T01:20:00.622503Z","shell.execute_reply.started":"2023-02-12T01:20:00.617067Z","shell.execute_reply":"2023-02-12T01:20:00.621265Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import sys\n# sys.path.append('/kaggle/input/timm0611/pytorch-image-models-0.6.11')\n# import timm\n# timm.__version__","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:20:00.623671Z","iopub.execute_input":"2023-02-12T01:20:00.624528Z","iopub.status.idle":"2023-02-12T01:20:00.632547Z","shell.execute_reply.started":"2023-02-12T01:20:00.624501Z","shell.execute_reply":"2023-02-12T01:20:00.631498Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# !cp -r /kaggle/input/hydracore105 /kaggle/working\n# !mv /kaggle/working/hydracore105/antlr4-python3-runtime-4.8.tar.gz.tmp /kaggle/working/hydracore105/antlr4-python3-runtime-4.8.tar.gz\n# !ls /kaggle/working/hydracore105","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:20:00.634448Z","iopub.execute_input":"2023-02-12T01:20:00.634991Z","iopub.status.idle":"2023-02-12T01:20:00.64186Z","shell.execute_reply.started":"2023-02-12T01:20:00.634936Z","shell.execute_reply":"2023-02-12T01:20:00.640869Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# !pip install /kaggle/working/hydracore105/* --ignore-installed PyYAML\n# !rm -r /kaggle/working/hydracore105","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:20:00.643133Z","iopub.execute_input":"2023-02-12T01:20:00.643434Z","iopub.status.idle":"2023-02-12T01:20:00.651033Z","shell.execute_reply.started":"2023-02-12T01:20:00.643386Z","shell.execute_reply":"2023-02-12T01:20:00.650252Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# !pip install dicomsdl","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:20:00.652033Z","iopub.execute_input":"2023-02-12T01:20:00.653124Z","iopub.status.idle":"2023-02-12T01:20:00.66044Z","shell.execute_reply.started":"2023-02-12T01:20:00.653089Z","shell.execute_reply":"2023-02-12T01:20:00.659532Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"path='/kaggle/input/rsna-breast-cancer-detection/'","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:20:00.662084Z","iopub.execute_input":"2023-02-12T01:20:00.662532Z","iopub.status.idle":"2023-02-12T01:20:00.670717Z","shell.execute_reply.started":"2023-02-12T01:20:00.662497Z","shell.execute_reply":"2023-02-12T01:20:00.669902Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import glob\ntrain_images = sorted(glob.glob(\"../input/rsna-mammography-images-as-pngs/images_as_pngs_512/train_images_processed_512/*/*\"))\ntrain_images[0:5]","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:20:00.672056Z","iopub.execute_input":"2023-02-12T01:20:00.672919Z","iopub.status.idle":"2023-02-12T01:21:57.331888Z","shell.execute_reply.started":"2023-02-12T01:20:00.672883Z","shell.execute_reply":"2023-02-12T01:21:57.330898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data['path']=train_images\ntrain_data_cancer_1=train_data[train_data['cancer']==1]\ntrain_data_cancer_0=train_data[train_data['cancer']==0]","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:21:57.333257Z","iopub.execute_input":"2023-02-12T01:21:57.334228Z","iopub.status.idle":"2023-02-12T01:21:57.353691Z","shell.execute_reply.started":"2023-02-12T01:21:57.33417Z","shell.execute_reply":"2023-02-12T01:21:57.352758Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Resampling\n - A widely adopted technique for dealing with highly unbalanced datasets is called resampling. It consists of removing samples from the majority class (under-sampling) and / or adding more examples from the minority class (over-sampling).\n![resampling.png](attachment:90c94203-11dd-4729-b181-7c897494a9d9.png)\n\n- The simplest implementation of over-sampling is to duplicate random records from the minority class, which can cause overfitting. In under-sampling, the simplest technique involves removing random records from the majority class, which can cause loss of information.\n\n- For example, we can cluster the records of the majority class, and do the under-sampling by removing records from each cluster, thus seeking to preserve information. In over-sampling, instead of creating exact copies of the minority class records, we can introduce small variations into those copies, creating more diverse synthetic samples.\n\n- sklearn.utils.resample()- Resample arrays or sparse matrices in a consistent way.The default strategy implements one step of the bootstrapping procedure.\n\n","metadata":{},"attachments":{"90c94203-11dd-4729-b181-7c897494a9d9.png":{"image/png":"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"}}},{"cell_type":"code","source":"from sklearn.utils import resample\ncancer_upsample = resample(train_data_cancer_1, replace=True, n_samples=train_data_cancer_0.shape[0],\nrandom_state=42)\n\nprint(cancer_upsample.shape)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:21:57.364114Z","iopub.execute_input":"2023-02-12T01:21:57.364417Z","iopub.status.idle":"2023-02-12T01:21:57.37749Z","shell.execute_reply.started":"2023-02-12T01:21:57.364389Z","shell.execute_reply":"2023-02-12T01:21:57.376446Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_all = pd.concat([train_data_cancer_0, cancer_upsample])\n\nprint(data_all.head())\n\nprint(data_all[\"cancer\"].value_counts())\n\ndata_all.groupby('cancer').size().plot(kind='pie', y = \"v1\",label = \"Type\",autopct='%1.1f%%')","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:21:57.379085Z","iopub.execute_input":"2023-02-12T01:21:57.379461Z","iopub.status.idle":"2023-02-12T01:21:57.495258Z","shell.execute_reply.started":"2023-02-12T01:21:57.379425Z","shell.execute_reply":"2023-02-12T01:21:57.494073Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2\n# Load and process the images\ndef load_and_preprocess_image(path,contrast_en=False,median_filter=False):\n    # load image\n    img = cv2.imread(path, cv2.IMREAD_COLOR)\n    # normalise\n    # img = img/255\n    # Convert float to 8-bit type\n    if(img.dtype!='uint8'):\n        img = np.array(img,dtype=np.uint8)\n    if (contrast_en=='True'):\n        # Convert the image to grayscale\n        print('Enhancing contrast')\n        gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n        # For contrast enhancement, equalize the histogram\n        img_enhanced = cv2.equalizeHist(gray_img)\n        return img_enhanced\n    if (median_filter==\"True\"):\n        print('Applying median blur')\n        blur_img=cv2.medianBlur(img)\n        return blur_img\n    else:\n        return img","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:21:57.496936Z","iopub.execute_input":"2023-02-12T01:21:57.497294Z","iopub.status.idle":"2023-02-12T01:21:57.512209Z","shell.execute_reply.started":"2023-02-12T01:21:57.497257Z","shell.execute_reply":"2023-02-12T01:21:57.510995Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Radon transform \n - Radon transform  is used in computer tomography, but it can also detect lines on the image. It transforms the original \"image pixels\" space to \"sinogram\" space, where each point corresponds to a line on the original image. Although frequency modulation of our signals is not linear, Radon transform \"concentrates\" the signal energy in some compact area on the sinogram image, making it much easier to detect the signal.\n\n# Fourier Transform - OpenCV  \n\n- To find Fourier transforms of an input image, one could follow the steps given below :\n\n - Import the required libraries. In all below Python examples the required Python libraries are OpenCV, Numpy and Matplotlib. Make sure you have already installed them.\n- Load the input image as a grayscale image using cv2.imread() method. Also convert the type of gray image to float32.\n- Find Discrete Fourier Transform on the image using cv2.dft() passing required arguments.\n- Call np.fft.fftshift() to shift the zero-frequency component to the center of the spectrum.\n- Apply log transform and visualize the magnitude spectrum.\n- To visualize the transformed image we apply inverse transforms np.fft.ifftshift() and cv2.idft(). See the second example discussed below.","metadata":{}},{"cell_type":"code","source":"# read input image\nimg = cv2.imread('/kaggle/input/rsna-mammography-images-as-pngs/images_as_pngs/train_images_processed/10006/1864590858.png',0)\n\n# find the discrete fourier transform of the image\ndft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT)\n\n# shift zero-frequency component to the center of the spectrum\ndft_shift = np.fft.fftshift(dft)\nmagnitude_spectrum = 20*np.log(cv2.magnitude(\n      dft_shift[:,:,0],\n      dft_shift[:,:,1])\n   )\n# visualize input image and the magnitude spectrum\nplt.subplot(121),plt.imshow(img, cmap = 'gray')\nplt.title('Input Image'), plt.xticks([]), plt.yticks([])\nplt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')\nplt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])\nplt.show","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:21:57.51846Z","iopub.execute_input":"2023-02-12T01:21:57.51904Z","iopub.status.idle":"2023-02-12T01:21:57.793152Z","shell.execute_reply.started":"2023-02-12T01:21:57.518992Z","shell.execute_reply":"2023-02-12T01:21:57.791635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2\nimport numpy as np\nfrom matplotlib import pyplot as plt\nimg = cv2.imread('/kaggle/input/rsna-mammography-images-as-pngs/images_as_pngs/train_images_processed/10006/1864590858.png',0)\nf = np.fft.fft2(img)\nfshift = np.fft.fftshift(f)\nmagnitude_spectrum = 20*np.log(np.abs(fshift))\n\nplt.subplot(121),plt.imshow(img, cmap = 'gray')\nplt.title('Input Image'), plt.xticks([]), plt.yticks([])\nplt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')\nplt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:21:57.799981Z","iopub.execute_input":"2023-02-12T01:21:57.800548Z","iopub.status.idle":"2023-02-12T01:21:57.975109Z","shell.execute_reply.started":"2023-02-12T01:21:57.800493Z","shell.execute_reply":"2023-02-12T01:21:57.973885Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Radon Transform - forward transform\n- When calculating the Radon transform, we need to decide how many projection angles we wish to use. As a rule of thumb, the number of projections should be about the same as the number of pixels there are across the object (to see why this is so, consider how many unknown pixel values must be determined in the reconstruction process and compare this to the number of measurements provided by the projections. Radon transform, often known as original images sinogram:\n\n- Source : https://scikit-image.org/docs/stable/auto_examples/transform/plot_radon_transform.html","metadata":{}},{"cell_type":"code","source":"from skimage.transform import radon, rescale\nfrom skimage.color import rgb2hsv, rgb2gray, rgb2yuv\nfrom skimage import color, exposure, transform\nfrom skimage.exposure import equalize_hist\nimage_file = '/kaggle/input/rsna-mammography-images-as-pngs/images_as_pngs_1024/train_images_processed_1024/10011/541722628.png'\nimage = cv2.imread(image_file)\nimage = rgb2gray(image)\nimage = rescale(image, scale=0.4, mode='reflect', channel_axis=None)\n\nfig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4.5))\n\nax1.set_title(\"Original\")\nax1.imshow(image, cmap=plt.cm.Greys_r)\n\ntheta = np.linspace(0., 180., max(image.shape), endpoint=False)\nsinogram = radon(image, theta=theta)\ndx, dy = 0.5 * 180.0 / max(image.shape), 0.5 / sinogram.shape[0]\nax2.set_title(\"Radon transform\\n(Sinogram)\")\nax2.set_xlabel(\"Projection angle (deg)\")\nax2.set_ylabel(\"Projection position (pixels)\")\nax2.imshow(sinogram, cmap=plt.cm.Greys_r,\n           extent=(-dx, 180.0 + dx, -dy, sinogram.shape[0] + dy),\n           aspect='auto')\n\nfig.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:21:57.981158Z","iopub.execute_input":"2023-02-12T01:21:57.981672Z","iopub.status.idle":"2023-02-12T01:21:59.936247Z","shell.execute_reply.started":"2023-02-12T01:21:57.981622Z","shell.execute_reply":"2023-02-12T01:21:59.935168Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport cv2\n\nfrom skimage.transform import radon\n\n\nfilename = '/kaggle/input/rsna-mammography-images-as-pngs/images_as_pngs_1024/train_images_processed_1024/10042/1648588715.png'\n# Load file, converting to grayscale\nimg = cv2.imread(filename)\nI = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\nh, w = I.shape\n# If the resolution is high, resize the image to reduce processing time.\nif (w > 640):\n    I = cv2.resize(I, (640, int((h / w) * 640)))\nI = I - np.mean(I)  # Demean; make the brightness extend above and below zero\n# Do the radon transform\nsinogram = radon(I)\n# Find the RMS value of each row and find \"busiest\" rotation,\n# where the transform is lined up perfectly with the alternating dark\n# text and white lines\nr = np.array([np.sqrt(np.mean(np.abs(line) ** 2)) for line in sinogram.transpose()])\nrotation = np.argmax(r)\nprint('Rotation: {:.2f} degrees'.format(90 - rotation))\n\n# Rotate and save with the original resolution\nM = cv2.getRotationMatrix2D((w/2, h/2), 90 - rotation, 1)\ndst = cv2.warpAffine(img, M, (w, h))\ncv2.imwrite('rotated.jpg', dst)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:21:59.9379Z","iopub.execute_input":"2023-02-12T01:21:59.939091Z","iopub.status.idle":"2023-02-12T01:22:01.598091Z","shell.execute_reply.started":"2023-02-12T01:21:59.939048Z","shell.execute_reply":"2023-02-12T01:22:01.597079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Wavelet Transforms","metadata":{}},{"cell_type":"code","source":"# Wavelet Transform\nimport matplotlib.pyplot as plt\n\nimport pywt\nimport pywt.data\n\n\n# Load image\nimage1 = cv2.imread(\"../input/rsna-mammography-images-as-pngs/images_as_pngs_cv2_384/train_images_processed_cv2_384/10011/1031443799.png\")\nimage2 = cv2.imread(\"../input/rsna-mammography-images-as-pngs/images_as_pngs_cv2_384/train_images_processed_cv2_384/10011/270344397.png\")\nimage1 = rgb2gray(image1)\nimage2 = rgb2gray(image2)\n\nimages=[image1,image2]\n\n# Wavelet transform of image, and plot approximation and details\ntitles = ['Approximation', ' Horizontal detail',\n          'Vertical detail', 'Diagonal detail']\ncoeffs2 = pywt.dwt2(image1, 'bior1.3')\nLL, (LH, HL, HH) = coeffs2\nfig = plt.figure(figsize=(12, 3))\nfor i, a in enumerate([LL, LH, HL, HH]):\n    ax = fig.add_subplot(1, 4, i + 1)\n    ax.imshow(a, interpolation=\"nearest\", cmap=plt.cm.gray)\n    ax.set_title(titles[i], fontsize=10)\n    ax.set_xticks([])\n    ax.set_yticks([])\n\nfig.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:22:01.599744Z","iopub.execute_input":"2023-02-12T01:22:01.600426Z","iopub.status.idle":"2023-02-12T01:22:01.997006Z","shell.execute_reply.started":"2023-02-12T01:22:01.60038Z","shell.execute_reply":"2023-02-12T01:22:01.995611Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from PIL import Image as Img\nfrom PIL import ImageTk\nimport pywt\nimport pywt.data\nimage1 = cv2.imread(\"../input/rsna-mammography-images-as-pngs/images_as_pngs_cv2_vl_768/train_images_processed_cv2_vl_768/10050/1428987847.png\")\nimage2 = cv2.imread(\"../input/rsna-mammography-images-as-pngs/images_as_pngs_cv2_vl_768/train_images_processed_cv2_vl_768/10050/588678397.png\")\nimage1 = rgb2gray(image1)\nimage2 = rgb2gray(image2)\nimages=[image1,image2]\nfor image in images:\n    image_array = Img.fromarray(image)\n    resize_img = image_array.resize((50 , 50))\n    coeffs2 = pywt.dwt2(resize_img, 'bior1.3')\n    LL, (LH, HL, HH) = coeffs2\n    fig = plt.figure(figsize=(12, 3))\n    # Wavelet transform of image, and plot approximation and details\n    titles = ['Approximation', ' Horizontal detail','Vertical detail', 'Diagonal detail']\n    for i, a in enumerate([LL, LH, HL, HH]):\n        ax = fig.add_subplot(1, 4, i + 1)\n        ax.imshow(a,  interpolation=\"nearest\",cmap=plt.cm.gray)\n        ax.set_title(titles[i], fontsize=10)\n        ax.set_xticks([])\n        ax.set_yticks([])\n\n    fig.tight_layout()\n    plt.show()\n    print('LL : {} | LH : {}'.format(LL.shape , LH.shape))","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:22:01.998475Z","iopub.execute_input":"2023-02-12T01:22:01.999437Z","iopub.status.idle":"2023-02-12T01:22:03.133281Z","shell.execute_reply.started":"2023-02-12T01:22:01.999399Z","shell.execute_reply":"2023-02-12T01:22:03.131926Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install git+https://github.com/AP-Atul/wavelets\n","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:22:03.134946Z","iopub.execute_input":"2023-02-12T01:22:03.135433Z","iopub.status.idle":"2023-02-12T01:22:16.175343Z","shell.execute_reply.started":"2023-02-12T01:22:03.135396Z","shell.execute_reply":"2023-02-12T01:22:16.174132Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Wavelet Transform\nimport cv2\nfrom wavelet import FastWaveletTransform\n\ninputFile = \"/kaggle/input/rsna-mammography-images-as-pngs/images_as_pngs_cv2_384/train_images_processed_cv2_384/10011/541722628.png\"\n\ndata = cv2.imread(inputFile)\ndata = cv2.cvtColor(data, cv2.COLOR_BGR2GRAY)\ndata = np.array(data)\noriginalShape = data.shape\ndata = data.flatten()\n\ntransform = FastWaveletTransform(\"haar\")\n\ncoefficients = transform.waveDec(data)\ncoefficients = transform.waveRec(coefficients)\n\ncoefficients = np.array(coefficients)\ncoefficients = coefficients.reshape(originalShape)\nplt.imshow(coefficients)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:22:16.177638Z","iopub.execute_input":"2023-02-12T01:22:16.178041Z","iopub.status.idle":"2023-02-12T01:22:16.984138Z","shell.execute_reply.started":"2023-02-12T01:22:16.178Z","shell.execute_reply":"2023-02-12T01:22:16.983147Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Function to visualise the effect of pre-processing\ndef vis_preprocess_effect(data,contrast_en=False,median_filter=False):\n    plt.ion()\n    for i in range(0,5):\n        print(i)\n        plt.subplot(121)\n        plt.title('No preprocess')\n        plt.imshow(load_and_preprocess_image(data_all['path'][i]))\n        plt.subplot(122)\n        if (contrast_en==True):\n            plt.title('With contrast enhancement')\n            plt.imshow(load_and_preprocess_image(data_all['path'][i],contrast_en=True))\n            plt.pause(2)\n            plt.close()\n        if (median_filter==True):\n            plt.title('With median filter')\n            plt.imshow(load_and_preprocess_image(data_all['path'][i],median_filter=True))\n            plt.pause(2)\n            plt.close()","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:22:16.985613Z","iopub.execute_input":"2023-02-12T01:22:16.986648Z","iopub.status.idle":"2023-02-12T01:22:16.995497Z","shell.execute_reply.started":"2023-02-12T01:22:16.986609Z","shell.execute_reply":"2023-02-12T01:22:16.994251Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"vis_preprocess_effect(data_all,median_filter=True)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:22:16.997501Z","iopub.execute_input":"2023-02-12T01:22:16.998016Z","iopub.status.idle":"2023-02-12T01:22:28.927641Z","shell.execute_reply.started":"2023-02-12T01:22:16.997979Z","shell.execute_reply":"2023-02-12T01:22:28.926597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"vis_preprocess_effect(data_all,contrast_en=True)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:22:28.929677Z","iopub.execute_input":"2023-02-12T01:22:28.930083Z","iopub.status.idle":"2023-02-12T01:22:40.801097Z","shell.execute_reply.started":"2023-02-12T01:22:28.930047Z","shell.execute_reply":"2023-02-12T01:22:40.800122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#  Generator function to get the images and labels\nfrom tensorflow.keras.utils import to_categorical\n\ndef data_generator(df, batch_size=32,contrast_en=False,median_filter=False):\n  while True:\n    # Shuffle the dataframe rows\n    df = df.sample(frac=1).reset_index(drop=True)\n    \n    # Divide the dataframe into batches\n    for i in range(0, df.shape[0], batch_size):\n      batch_df = df.iloc[i:i+batch_size, :]\n      \n      # Load and preprocess the images\n      images = []\n      for image_path in batch_df['path']:\n        image = load_and_preprocess_image(image_path,contrast_en,median_filter)\n        # Normalise the pre-processed image\n        images.append(image/255)\n      images = np.array(images)\n      \n      # Convert the labels to categorical format\n      labels = to_categorical(batch_df['cancer'].values, num_classes=2)\n      \n      yield images, labels","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:22:40.802537Z","iopub.execute_input":"2023-02-12T01:22:40.803175Z","iopub.status.idle":"2023-02-12T01:22:40.812355Z","shell.execute_reply.started":"2023-02-12T01:22:40.803135Z","shell.execute_reply":"2023-02-12T01:22:40.811375Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\n# Split the dataframe into training and validation sets\ndf_train, df_val = train_test_split(data_all, test_size=0.2)\n\n# Create the generator functions\ntrain_generator = data_generator(df_train,median_filter=True)\nval_generator = data_generator(df_val,median_filter=True)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:22:40.813935Z","iopub.execute_input":"2023-02-12T01:22:40.814363Z","iopub.status.idle":"2023-02-12T01:22:40.878334Z","shell.execute_reply.started":"2023-02-12T01:22:40.814329Z","shell.execute_reply":"2023-02-12T01:22:40.877361Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img,label=next(train_generator)\n","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:22:40.879907Z","iopub.execute_input":"2023-02-12T01:22:40.880294Z","iopub.status.idle":"2023-02-12T01:22:41.485817Z","shell.execute_reply.started":"2023-02-12T01:22:40.880256Z","shell.execute_reply":"2023-02-12T01:22:41.484769Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class pF1(tf.keras.metrics.Metric):\n    def __init__(self, name='pF1', **kwargs):\n        super(pF1, self).__init__(name=name, **kwargs)\n        self.tc = self.add_weight(name='tc', initializer='zeros')\n        self.tp = self.add_weight(name='tp', initializer='zeros')\n        self.fp = self.add_weight(name='fp', initializer='zeros')\n\n    def update_state(self, y_true, y_pred, sample_weight=None):\n        self.tc.assign_add(tf.cast(tf.reduce_sum(y_true), tf.float32))\n        self.tp.assign_add(tf.cast(tf.reduce_sum((y_pred[y_true == 1])), tf.float32))\n        self.fp.assign_add(tf.cast(tf.reduce_sum((y_pred[y_true == 0])), tf.float32))\n\n    def result(self):\n        if self.tc == 0 or (self.tp + self.fp) == 0:\n            return 0.0\n        else:\n            precision = self.tp / (self.tp + self.fp)\n            recall = self.tp / (self.tc)\n            return 2 * (precision * recall) / (precision + recall)\n        \n        def reset_state(self):\n            self.tc.assign(0)\n            self.tp.assign(0)\n            self.fp.assign(0)\n","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:22:41.487474Z","iopub.execute_input":"2023-02-12T01:22:41.487849Z","iopub.status.idle":"2023-02-12T01:22:41.497765Z","shell.execute_reply.started":"2023-02-12T01:22:41.487812Z","shell.execute_reply":"2023-02-12T01:22:41.496797Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Metrics and loss\n\nmetrics = [pF1(),\n           tf.keras.metrics.Precision(),\n           tf.keras.metrics.Recall(),\n           tf.keras.metrics.AUC(),\n           tf.keras.metrics.BinaryAccuracy()\n        ]\nloss=tf.keras.losses.BinaryCrossentropy(from_logits=False)","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:22:41.499093Z","iopub.execute_input":"2023-02-12T01:22:41.500005Z","iopub.status.idle":"2023-02-12T01:22:41.554099Z","shell.execute_reply.started":"2023-02-12T01:22:41.499965Z","shell.execute_reply":"2023-02-12T01:22:41.553245Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def model_pipeline(model,save_model):\n    model = model\n    model.summary()\n    model.compile(loss=loss, optimizer='adam', metrics=metrics)\n    history = model.fit(train_generator, \n                              steps_per_epoch=len(df_train)//32, \n                              epochs=1,\n                              validation_data=val_generator, \n                              validation_steps=len(df_val)//32)\n    model.save(save_model+'.h5')\n    return model","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:22:41.555617Z","iopub.execute_input":"2023-02-12T01:22:41.555967Z","iopub.status.idle":"2023-02-12T01:22:41.564686Z","shell.execute_reply.started":"2023-02-12T01:22:41.555916Z","shell.execute_reply":"2023-02-12T01:22:41.563262Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# from __future__ import division\n# import numpy as np\n# import cv2\n# import glob\n# import sys\n# import os\n\n# def color_transfer(source1):\n#     source = cv2.imread(\"/kaggle/input/rsna-mammography-images-as-pngs/images_as_pngs_512/train_images_processed_512/10006/462822612.png\")\n#     target = cv2.cvtColor(source1, cv2.COLOR_BGR2LAB).astype(\"float32\")\n#     source = cv2.cvtColor(source, cv2.COLOR_BGR2LAB).astype(\"float32\")\n\n#     (lMeanSrc, lStdSrc, aMeanSrc, aStdSrc, bMeanSrc, bStdSrc) = image_stats(source)\n#     (lMeanTar, lStdTar, aMeanTar, aStdTar, bMeanTar, bStdTar) = image_stats(target)\n\n#     (l, a, b) = cv2.split(target)\n#     l -= lMeanTar\n#     a -= aMeanTar\n#     b -= bMeanTar\n\n#     l = (lStdSrc / lStdTar) * l\n#     a = (aStdSrc / aStdTar) * a\n#     b = (bStdSrc / bStdTar) * b\n\n#     l += lMeanSrc\n#     a += aMeanSrc\n#     b += bMeanSrc\n\n#     l = np.clip(l, 0, 255)\n#     a = np.clip(a, 0, 255)\n#     b = np.clip(b, 0, 255)\n\n\n#     transfer = cv2.merge([l, a, b])\n#     transfer = cv2.cvtColor(transfer.astype(\"uint8\"), cv2.COLOR_LAB2BGR)\n#     return transfer\n\n# def image_stats(image):\n\n#     (l, a, b) = cv2.split(image)\n#     (lMean, lStd) = (l.mean(), l.std())\n#     (aMean, aStd) = (a.mean(), a.std())\n#     (bMean, bStd) = (b.mean(), b.std())\n\n#     return (lMean, lStd, aMean, aStd, bMean, bStd)\n\n# if __name__=='__main__':\n#     for ii in ['100X','200X','400X']:\n#         for jj in ['fold1','fold2','fold3','fold4','fold5']:\n#             path=\"./\"+jj+\"/*/\"+ii+\"/*.png\"\n#             print(path)\n#             images = glob.glob(path)\n#             print(images)\n#             for image in images:\n#                 source = cv2.imread(image)\n#                 transfer = color_transfer(source)\n#                 cv2.imwrite('preprocess' + image.replace(\"png\", \"jpg\")[1:],transfer)\n#                 print(image,' Done.')","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:22:41.566245Z","iopub.execute_input":"2023-02-12T01:22:41.566853Z","iopub.status.idle":"2023-02-12T01:22:41.576635Z","shell.execute_reply.started":"2023-02-12T01:22:41.566816Z","shell.execute_reply":"2023-02-12T01:22:41.575566Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow import keras\nfrom keras import layers, optimizers\nfrom keras.layers import Input, Flatten\nfrom keras.models import Sequential, Model\nmodel5 = Sequential([\n    layers.Conv2D(filters=96, kernel_size=(11,11), strides=(4,4), activation='relu', input_shape=(512, 512, 3)),\n    layers.BatchNormalization(),\n    layers.MaxPool2D(pool_size=(3,3), strides=(2,2)),\n    layers.Conv2D(filters=256, kernel_size=(5,5), strides=(1,1), activation='relu', padding=\"same\"),\n    layers.BatchNormalization(),\n    layers.MaxPool2D(pool_size=(3,3), strides=(2,2)),\n    layers.Conv2D(filters=384, kernel_size=(3,3), strides=(1,1), activation='relu', padding=\"same\"),\n    layers.BatchNormalization(),\n    layers.Conv2D(filters=384, kernel_size=(3,3), strides=(1,1), activation='relu', padding=\"same\"),\n    layers.BatchNormalization(),\n    layers.Conv2D(filters=256, kernel_size=(3,3), strides=(1,1), activation='relu', padding=\"same\"),\n    layers.BatchNormalization(),\n    layers.MaxPool2D(pool_size=(3,3), strides=(2,2)),\n    layers.Flatten(),\n    layers.Dense(4096, activation='relu'),\n    layers.Dropout(0.5),\n    layers.Dense(4096, activation='relu'),\n    layers.Dropout(0.5),\n    layers.Dense(2, activation='softmax')\n])\n    \nmodel5.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])\nmodel5.summary()","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:22:41.57839Z","iopub.execute_input":"2023-02-12T01:22:41.578755Z","iopub.status.idle":"2023-02-12T01:22:41.750631Z","shell.execute_reply.started":"2023-02-12T01:22:41.578717Z","shell.execute_reply":"2023-02-12T01:22:41.749493Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_history=model_pipeline(model5,'my_model2')","metadata":{"execution":{"iopub.status.busy":"2023-02-12T01:22:41.753872Z","iopub.execute_input":"2023-02-12T01:22:41.75416Z","iopub.status.idle":"2023-02-12T02:21:18.8581Z","shell.execute_reply.started":"2023-02-12T01:22:41.754134Z","shell.execute_reply":"2023-02-12T02:21:18.85639Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Resnet model\n- ResNet-50 is a pretrained Deep Learning model for image classification of the Convolutional Neural Network(CNN, or ConvNet), which is a class of deep neural networks, most commonly applied to analyzing visual imagery.\n- Resnet model was proposed to solve the issue of diminishing gradient. The idea is to skip the connection and pass the residual to the next layer so that the model can continue to train. With Resnet models, CNN models can go deeper and deeper.\n\n# Architecture of ResNet-50\n- ResNet stands for Residual Network and more specifically it is of a Residual Neural Network architecture. What characterizes a residual network is its identity connections. Identity connections takes the input directly to the end of each residual block\n* - ResNet-50 model consists of 5 stages each with a residual block. Each residual block has 3 layers with both 1*1 and 3*3 convolutions. The concept of residual blocks is quite simple. In traditional neural networks, each layer feeds into the next layer. In a network with residual blocks, each layer feeds into the next layer and directly into the layers about 2–3 hops away, called identity connections.\n\n- https://keras.io/api/applications/#usage-examples-for-image-classification-models\n","metadata":{}},{"cell_type":"code","source":"restnet = ResNet50(include_top = False, weights= None , input_shape=(512, 512, 3))\noutput = restnet.layers[1].output\noutput = layers.Flatten()(output)\n\nrestnet = Model(restnet.input, output)\n\nmodel6 = Sequential([\n            restnet,\n            layers.Dense(2, activation=\"softmax\")\n])\n\n\n","metadata":{"execution":{"iopub.status.busy":"2023-02-12T03:54:16.033401Z","iopub.execute_input":"2023-02-12T03:54:16.033781Z","iopub.status.idle":"2023-02-12T03:54:16.914369Z","shell.execute_reply.started":"2023-02-12T03:54:16.033749Z","shell.execute_reply":"2023-02-12T03:54:16.91339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_history=model_pipeline(model6,'my_model3')","metadata":{"execution":{"iopub.status.busy":"2023-02-12T03:54:16.916136Z","iopub.execute_input":"2023-02-12T03:54:16.916512Z","iopub.status.idle":"2023-02-12T04:44:03.623617Z","shell.execute_reply.started":"2023-02-12T03:54:16.916479Z","shell.execute_reply":"2023-02-12T04:44:03.622613Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}