{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":39272,"databundleVersionId":4629629,"sourceType":"competition"},{"sourceId":2021025,"sourceType":"datasetVersion","datasetId":1209633},{"sourceId":2527926,"sourceType":"datasetVersion","datasetId":1531638},{"sourceId":4696088,"sourceType":"datasetVersion","datasetId":2687741},{"sourceId":4874049,"sourceType":"datasetVersion","datasetId":2717932}],"dockerImageVersionId":30302,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import sys\nimport os\nimport platform\nprint(sys.version)\nprint(os.name)\nprint(platform.system())\nprint(platform.release())","metadata":{"papermill":{"duration":0.041954,"end_time":"2021-10-24T18:56:45.005241","exception":false,"start_time":"2021-10-24T18:56:44.963287","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:09:34.053111Z","iopub.execute_input":"2024-12-17T19:09:34.053544Z","iopub.status.idle":"2024-12-17T19:09:34.079584Z","shell.execute_reply.started":"2024-12-17T19:09:34.053456Z","shell.execute_reply":"2024-12-17T19:09:34.078678Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install dicomsdl","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:09:35.443143Z","iopub.execute_input":"2024-12-17T19:09:35.443491Z","iopub.status.idle":"2024-12-17T19:09:45.437224Z","shell.execute_reply.started":"2024-12-17T19:09:35.443463Z","shell.execute_reply":"2024-12-17T19:09:45.436054Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pip uninstall nvidia-cublas-cu11 -y\n","metadata":{"papermill":{"duration":1.43331,"end_time":"2021-10-24T18:56:46.465785","exception":false,"start_time":"2021-10-24T18:56:45.032475","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:09:46.666754Z","iopub.execute_input":"2024-12-17T19:09:46.667654Z","iopub.status.idle":"2024-12-17T19:09:48.588633Z","shell.execute_reply.started":"2024-12-17T19:09:46.667583Z","shell.execute_reply":"2024-12-17T19:09:48.58721Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pip install nvidia-cublas-cu12\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:09:50.817694Z","iopub.execute_input":"2024-12-17T19:09:50.818759Z","iopub.status.idle":"2024-12-17T19:10:12.585554Z","shell.execute_reply.started":"2024-12-17T19:09:50.818707Z","shell.execute_reply":"2024-12-17T19:10:12.584448Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nis_cuda_enabled = torch.cuda.is_available()\nprint('Cuda enabled', is_cuda_enabled)\nif torch.cuda.is_available():\n    print(torch.cuda.current_device())\n    print(torch.cuda.device(0))\n    print(torch.cuda.device_count())\n    print(torch.cuda.get_device_name(0))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:10:51.43043Z","iopub.execute_input":"2024-12-17T19:10:51.431461Z","iopub.status.idle":"2024-12-17T19:10:53.11434Z","shell.execute_reply.started":"2024-12-17T19:10:51.431404Z","shell.execute_reply":"2024-12-17T19:10:53.113281Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!nvcc --version","metadata":{"papermill":{"duration":0.704667,"end_time":"2021-10-24T18:56:47.197829","exception":false,"start_time":"2021-10-24T18:56:46.493162","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:10:56.375097Z","iopub.execute_input":"2024-12-17T19:10:56.375874Z","iopub.status.idle":"2024-12-17T19:10:57.625342Z","shell.execute_reply.started":"2024-12-17T19:10:56.375828Z","shell.execute_reply":"2024-12-17T19:10:57.624212Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!nvidia-smi","metadata":{"papermill":{"duration":0.853962,"end_time":"2021-10-24T18:56:48.07905","exception":false,"start_time":"2021-10-24T18:56:47.225088","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:10:58.754816Z","iopub.execute_input":"2024-12-17T19:10:58.755176Z","iopub.status.idle":"2024-12-17T19:10:59.882862Z","shell.execute_reply.started":"2024-12-17T19:10:58.755147Z","shell.execute_reply":"2024-12-17T19:10:59.881669Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%reload_ext autoreload\n%autoreload 2\n%matplotlib inline\n\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nimport pydicom\nimport pandas as pd\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nfrom tqdm import tqdm\nimport binascii\nfrom PIL import Image\n\nfrom fastai.vision.all import *\nimport numpy as np\nimport pandas as pd\nimport random\nimport os\nnp.set_printoptions(threshold=sys.maxsize)","metadata":{"papermill":{"duration":1.565577,"end_time":"2021-10-24T18:56:49.677142","exception":false,"start_time":"2021-10-24T18:56:48.111565","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:01.797655Z","iopub.execute_input":"2024-12-17T19:11:01.79802Z","iopub.status.idle":"2024-12-17T19:11:03.062268Z","shell.execute_reply.started":"2024-12-17T19:11:01.797989Z","shell.execute_reply":"2024-12-17T19:11:03.061281Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pytorch_lightning as pl\nrandom_seed=1\npl.seed_everything(random_seed) #ultra sound data frame\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:08.664969Z","iopub.execute_input":"2024-12-17T19:11:08.665808Z","iopub.status.idle":"2024-12-17T19:11:11.129155Z","shell.execute_reply.started":"2024-12-17T19:11:08.665772Z","shell.execute_reply":"2024-12-17T19:11:11.128203Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"torch.cuda.empty_cache()","metadata":{"papermill":{"duration":0.067379,"end_time":"2021-10-24T18:56:49.771774","exception":false,"start_time":"2021-10-24T18:56:49.704395","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:15.253118Z","iopub.execute_input":"2024-12-17T19:11:15.254214Z","iopub.status.idle":"2024-12-17T19:11:15.315467Z","shell.execute_reply.started":"2024-12-17T19:11:15.254166Z","shell.execute_reply":"2024-12-17T19:11:15.314416Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# Path to the dataset\ndataset_path = '/kaggle/input/breast-ultrasound-images-dataset/Dataset_BUSI_with_GT'\ndataset_append_path = '/input/breast-ultrasound-images-dataset/Dataset_BUSI_with_GT'\nos.makedirs('./ultrasound', exist_ok = True)\nprint('ultrasound foldeepor created')\n\n# Output CSV file\noutput_csv = './ultrasound/ultrasound_data.csv'\n\n# Define possible values for laterality and view\nlaterality_options = ['L', 'R']\nview_options = ['CC', 'MLO']\nages = range(30, 90)  # Assuming age range is between 30 and 90\n\n# Function to generate random patient and site IDs\ndef generate_id():\n    return random.randint(10000, 99999)\n\n# List to store the data\ndata = []\n\n# Iterate over each category folder\nfor category in ['benign', 'malignant', 'normal']:\n    category_path = os.path.join(dataset_path, category)\n    if os.path.exists(category_path):\n        \n        for image_file in os.listdir(category_path):\n            if image_file.endswith('.png'):\n                image_id = os.path.splitext(image_file)[0]\n                site_id = random.choice([1,2,3,4,5])\n                patient_id = generate_id()\n                laterality = random.choice(laterality_options)\n                view = random.choice(view_options)\n                age = random.choice(ages)\n                \n                if category == 'benign':\n                    cancer = 0\n                elif category == 'malignant':\n                    cancer = 1\n                else:\n                    cancer = 0\n#\tsite_id\tpatient_id\timage_id\tlaterality\tview\tage\tcancer\tbiopsy\tinvasive\tBIRADS\timplant\tdensity\tmachine_id\tdifficult_negative_case\n                # Append the row to the data list\n                file = image_file\n                biopsy =0\n                invasive =0\n                BIRADS = float('nan')\n                implant = 0\n                density=float('nan')\n                machine_id = random.choice([1,2,3,4,5])\n                dnf = False\n                \n                data.append([site_id, patient_id, image_id, laterality, view, age, cancer, biopsy,invasive,BIRADS,implant, density, machine_id,dnf, file,dataset_append_path+'/'+category+'/'+file])\n\n# Create a DataFrame\nultrasound_df = pd.DataFrame(data, columns=['site_id', 'patient_id', 'image_id', 'laterality', 'view', 'age', 'cancer','biopsy','invasive','BIRADS','implant','density','machine_id','difficult_negative_case', 'file','path'])\n\n# Save the DataFrame to a CSV file\nultrasound_df.to_csv(output_csv, index=False)\n\nprint(f\"Ultrasound CSV file '{output_csv}' has been created successfully.\")\nultrasound_df.head()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:23.274295Z","iopub.execute_input":"2024-12-17T19:11:23.275287Z","iopub.status.idle":"2024-12-17T19:11:23.468238Z","shell.execute_reply.started":"2024-12-17T19:11:23.275242Z","shell.execute_reply":"2024-12-17T19:11:23.46697Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# values distribution\nplt.figure(figsize=(5, 4))\nsns.countplot(data=ultrasound_df, x=\"cancer\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:25.529888Z","iopub.execute_input":"2024-12-17T19:11:25.530753Z","iopub.status.idle":"2024-12-17T19:11:25.822034Z","shell.execute_reply.started":"2024-12-17T19:11:25.530709Z","shell.execute_reply":"2024-12-17T19:11:25.820789Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Load labels","metadata":{"papermill":{"duration":0.026922,"end_time":"2021-10-24T18:56:49.826788","exception":false,"start_time":"2021-10-24T18:56:49.799866","status":"completed"},"tags":[]}},{"cell_type":"code","source":"EPOCHS = 1\nINPUT_PATH = '/input/rsna-mammography-images-as-pngs/images_as_pngs_512/train_images_processed_512'\nLABELS_PATH = '/kaggle/input/rsna-breast-cancer-detection/train.csv'\nMODEL_EXPORT = 'trained_model'\ndf = pd.read_csv(LABELS_PATH)\n","metadata":{"papermill":{"duration":0.090731,"end_time":"2021-10-24T18:56:49.944474","exception":false,"start_time":"2021-10-24T18:56:49.853743","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:28.603196Z","iopub.execute_input":"2024-12-17T19:11:28.603665Z","iopub.status.idle":"2024-12-17T19:11:28.808642Z","shell.execute_reply.started":"2024-12-17T19:11:28.603624Z","shell.execute_reply":"2024-12-17T19:11:28.807484Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.head()","metadata":{"papermill":{"duration":0.074969,"end_time":"2021-10-24T18:56:50.046629","exception":false,"start_time":"2021-10-24T18:56:49.97166","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:30.014544Z","iopub.execute_input":"2024-12-17T19:11:30.015683Z","iopub.status.idle":"2024-12-17T19:11:30.080067Z","shell.execute_reply.started":"2024-12-17T19:11:30.015639Z","shell.execute_reply":"2024-12-17T19:11:30.078799Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# values distribution\nplt.figure(figsize=(5, 4))\nsns.countplot(data=df, x=\"cancer\")\ndata =ultrasound_df\nages = data.groupby('patient_id')['age'].apply(lambda x: x.unique()[0])\ncancer_ages = data[data['cancer'] == 1].groupby('patient_id')['age'].apply(lambda x: x.unique()[0])\nno_cancer_ages = data[data['cancer'] == 0].groupby('patient_id')['age'].apply(lambda x: x.unique()[0])\n\nplt.figure(figsize=(16, 10))\n\nplt.subplot(1, 2, 1)\nsns.histplot(ages, bins=63, color='orange', kde=True)\nplt.title(\"All the patient\")\nplt.xlim(33, 89)\n\nplt.subplot(2, 2, 2)\nsns.histplot(cancer_ages, bins=51, color='red', kde=True)\nplt.title(\"Patients with cancer\")\nplt.xlim(33, 89)\n\nplt.subplot(2, 2, 4)\nsns.histplot(no_cancer_ages, bins=63, color='green', kde=True)\nplt.title(\"Patients without cancer\")\nplt.xlim(33, 89)\n\nplt.suptitle(\"Age distribution of the patients\")\nplt.show()","metadata":{"papermill":{"duration":0.252681,"end_time":"2021-10-24T18:56:50.327818","exception":false,"start_time":"2021-10-24T18:56:50.075137","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:31.081389Z","iopub.execute_input":"2024-12-17T19:11:31.082417Z","iopub.status.idle":"2024-12-17T19:11:32.161123Z","shell.execute_reply.started":"2024-12-17T19:11:31.082373Z","shell.execute_reply":"2024-12-17T19:11:32.160157Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Insights\n- Most of the patients are **older than 40 years old**\n- There is a a **peak at the age of 50**\n- Then, there is a **plateau until 70 years old** before the count of patients drops\n- **Patients with cancer** are usually **older** than the others\n- **Age will be an important feature** for a future model\n* The number of sample images with cancer is very low compared to the number of healthy breast samples. It will be more difficult to make the model learn the desired pattern.\n* All patients with a cancer had a biopsy\n* Only a small percentage of images without cancer resulted in a biopsy","metadata":{}},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings(\"ignore\", category=FutureWarning)\n\nfig, ax = plt.subplots(2, 3, figsize=(16, 8))\nsns.countplot(data['laterality'], palette='Blues_r', ax=ax[0, 0])\nsns.countplot(data['implant'], palette='Greens_r', ax=ax[0, 1])\nsns.countplot(data['difficult_negative_case'], palette='Reds_r', ax=ax[0, 2])\nsns.countplot(data['view'], palette='Oranges_r', ax=ax[1, 0])\nsns.countplot(data['density'], palette='Purples_r', order=['A', 'B', 'C', 'D'], ax=ax[1, 1])\nsns.countplot(data['site_id'], palette='Greys_r', ax=ax[1, 2])\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:32.909012Z","iopub.execute_input":"2024-12-17T19:11:32.90936Z","iopub.status.idle":"2024-12-17T19:11:33.506552Z","shell.execute_reply.started":"2024-12-17T19:11:32.909331Z","shell.execute_reply":"2024-12-17T19:11:33.505574Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#epo#create output dataset folders\nos.makedirs('./train', exist_ok = True)\nprint('Train folder created')\n\nos.makedirs('./test', exist_ok = True)\nprint('Test folder created')\n\n\nfile_path = '/input/breast-ultrasound-images-dataset/Dataset_BUSI_with_GT/benign/benign (2).png'\n\nif os.path.exists(file_path):\n    print(\"File exists.\")\nelse:\n    print(\"File does not exist.\")","metadata":{"papermill":{"duration":0.071934,"end_time":"2021-10-24T18:56:50.432681","exception":false,"start_time":"2021-10-24T18:56:50.360747","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:34.384525Z","iopub.execute_input":"2024-12-17T19:11:34.385374Z","iopub.status.idle":"2024-12-17T19:11:34.441482Z","shell.execute_reply.started":"2024-12-17T19:11:34.385328Z","shell.execute_reply":"2024-12-17T19:11:34.440353Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df['file'] = df.apply(lambda x: f'{x[\"patient_id\"]}/{x[\"image_id\"]}.png', axis=1)\ndf['path'] = INPUT_PATH+'/'+df['file']\nmerged_df= pd.concat([ultrasound_df, df], ignore_index=True)\ndf.head(2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:35.502081Z","iopub.execute_input":"2024-12-17T19:11:35.502443Z","iopub.status.idle":"2024-12-17T19:11:36.163014Z","shell.execute_reply.started":"2024-12-17T19:11:35.502413Z","shell.execute_reply":"2024-12-17T19:11:36.161838Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"help(ImageDataLoaders.from_df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:37.308361Z","iopub.execute_input":"2024-12-17T19:11:37.308875Z","iopub.status.idle":"2024-12-17T19:11:37.367288Z","shell.execute_reply.started":"2024-12-17T19:11:37.30883Z","shell.execute_reply":"2024-12-17T19:11:37.366249Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# a DataLoaders object is a combination of training and validation data\nimage_data = ImageDataLoaders.from_df(merged_df[['path','cancer']], item_tfms=Resize(224), bs=64, label_col=1, fn_col=0, path='/kaggle')","metadata":{"papermill":{"duration":4.811744,"end_time":"2021-10-24T18:59:08.699444","exception":false,"start_time":"2021-10-24T18:59:03.8877","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:38.663947Z","iopub.execute_input":"2024-12-17T19:11:38.664922Z","iopub.status.idle":"2024-12-17T19:11:46.137125Z","shell.execute_reply.started":"2024-12-17T19:11:38.664878Z","shell.execute_reply":"2024-12-17T19:11:46.13613Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# look at the data\nimage_data.show_batch()","metadata":{"papermill":{"duration":1.041027,"end_time":"2021-10-24T18:59:09.772078","exception":false,"start_time":"2021-10-24T18:59:08.731051","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:47.09824Z","iopub.execute_input":"2024-12-17T19:11:47.0991Z","iopub.status.idle":"2024-12-17T19:11:48.784533Z","shell.execute_reply.started":"2024-12-17T19:11:47.099054Z","shell.execute_reply":"2024-12-17T19:11:48.783322Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Training stage","metadata":{"papermill":{"duration":0.033494,"end_time":"2021-10-24T18:59:09.838759","exception":false,"start_time":"2021-10-24T18:59:09.805265","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"### DICOM files\nThe image data is in DICOM format. **DICOM (Digital Imaging and Communications in Medicine)** is a standard for storing and transmitting medical images and related information.\n\nIt consists of a set of data elements that are organized into a file structure. These data elements contain information about the medical image, such as the patient's name and medical record number, the image modality (e.g., CT, MRI, X-ray), the date and time the image was taken, and the image itself. The image data can be stored in various formats, such as 8-bit or 16-bit grayscale, or 24-bit color.\n\nIn addition to the image data, the DICOM format also includes metadata that describes the characteristics of the image, such as the image resolution, the size of the image in pixels, and the orientation of the image. This metadata is important for accurately displaying and interpreting the image.\n\nThe DICOM format is widely used in the medical community for storing, sharing, and analyzing medical images. It is supported by a wide range of medical devices, such as scanners, modalities, and workstations, and is used in hospitals, clinics, and research facilities around the world.","metadata":{}},{"cell_type":"code","source":"import torch \nimport torch.nn as nn\nimport torch.nn.functional as F\n\nclass Net(nn.Module):\n    def __init__(self, pretrained=False):\n        super().__init__()\n        # 3 input image channel, 6 output channels, 5x5 square convolution\n        # kernel\n        self.conv1 = nn.Conv2d(3, 6, 5)\n        self.pool = nn.MaxPool2d(2, 2)\n        self.conv2 = nn.Conv2d(6, 16, 5)\n        self.fc1 = nn.Linear(16 * 5 * 5, 120)\n        self.fc2 = nn.Linear(120, 84)\n        self.fc3 = nn.Linear(84, 10)\n\n    def forward(self, x):\n        x = self.pool(F.relu(self.conv1(x)))\n        x = self.pool(F.relu(self.conv2(x)))\n        x = torch.flatten(x, 1) # flatten all dimensions except batch\n        x = F.relu(self.fc1(x))\n        x = F.relu(self.fc2(x))\n        x = F.relu(self.fc3(x))\n        return x","metadata":{"papermill":{"duration":0.096605,"end_time":"2021-10-24T18:59:09.968261","exception":false,"start_time":"2021-10-24T18:59:09.871656","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:50.45917Z","iopub.execute_input":"2024-12-17T19:11:50.459538Z","iopub.status.idle":"2024-12-17T19:11:50.702521Z","shell.execute_reply.started":"2024-12-17T19:11:50.459508Z","shell.execute_reply":"2024-12-17T19:11:50.701477Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = Net()\nprint(model)","metadata":{"papermill":{"duration":0.10169,"end_time":"2021-10-24T18:59:10.103208","exception":false,"start_time":"2021-10-24T18:59:10.001518","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:51.849791Z","iopub.execute_input":"2024-12-17T19:11:51.85072Z","iopub.status.idle":"2024-12-17T19:11:51.906514Z","shell.execute_reply.started":"2024-12-17T19:11:51.850684Z","shell.execute_reply":"2024-12-17T19:11:51.905367Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"params = list(model.parameters())\nprint(len(params))\nprint(params[0].size())  # conv1's .weight","metadata":{"papermill":{"duration":0.093462,"end_time":"2021-10-24T18:59:10.230611","exception":false,"start_time":"2021-10-24T18:59:10.137149","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:52.796446Z","iopub.execute_input":"2024-12-17T19:11:52.797195Z","iopub.status.idle":"2024-12-17T19:11:52.852258Z","shell.execute_reply.started":"2024-12-17T19:11:52.797161Z","shell.execute_reply":"2024-12-17T19:11:52.851275Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# chooses an appropriate loss function\n#https://docs.fast.ai/metrics.html\nlearn = vision_learner(image_data, Net, metrics=[error_rate, accuracy], model_dir=\"/tmp/model/\").to_fp16()\n# auc_score = RocAuc()\n# f1 = F1Score()\n# learn = vision_learner(image_data, Net, metrics=[auc_score, f1], model_dir=\"/tmp/model/\").to_fp16()","metadata":{"papermill":{"duration":0.191923,"end_time":"2021-10-24T18:59:10.457334","exception":false,"start_time":"2021-10-24T18:59:10.265411","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:53.723165Z","iopub.execute_input":"2024-12-17T19:11:53.724105Z","iopub.status.idle":"2024-12-17T19:11:53.825927Z","shell.execute_reply.started":"2024-12-17T19:11:53.724069Z","shell.execute_reply":"2024-12-17T19:11:53.824972Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"learn.lr_find()","metadata":{"papermill":{"duration":37.266086,"end_time":"2021-10-24T18:59:47.799589","exception":false,"start_time":"2021-10-24T18:59:10.533503","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:11:54.998975Z","iopub.execute_input":"2024-12-17T19:11:54.999936Z","iopub.status.idle":"2024-12-17T19:12:29.811017Z","shell.execute_reply.started":"2024-12-17T19:11:54.999891Z","shell.execute_reply":"2024-12-17T19:12:29.809901Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Print model's state_dict\nprint(\"Model's state_dict:\")\nfor param_tensor in model.state_dict():\n    print(param_tensor, \"\\t\", model.state_dict()[param_tensor].size())","metadata":{"papermill":{"duration":0.109149,"end_time":"2021-10-24T18:59:47.945083","exception":false,"start_time":"2021-10-24T18:59:47.835934","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:13:16.794683Z","iopub.execute_input":"2024-12-17T19:13:16.795286Z","iopub.status.idle":"2024-12-17T19:13:16.859117Z","shell.execute_reply.started":"2024-12-17T19:13:16.795248Z","shell.execute_reply":"2024-12-17T19:13:16.858112Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\nlearn.fit_one_cycle(EPOCHS, lr_max=1e-2)","metadata":{"papermill":{"duration":29.299863,"end_time":"2021-10-24T19:00:17.28136","exception":false,"start_time":"2021-10-24T18:59:47.981497","status":"completed"},"tags":[],"scrolled":true,"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:13:18.101238Z","iopub.execute_input":"2024-12-17T19:13:18.101619Z","iopub.status.idle":"2024-12-17T19:17:07.381962Z","shell.execute_reply.started":"2024-12-17T19:13:18.101575Z","shell.execute_reply":"2024-12-17T19:17:07.380599Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# show results of prediction\nlearn.show_results()","metadata":{"papermill":{"duration":1.677093,"end_time":"2021-10-24T19:00:19.01842","exception":false,"start_time":"2021-10-24T19:00:17.341327","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:17:09.456326Z","iopub.execute_input":"2024-12-17T19:17:09.456729Z","iopub.status.idle":"2024-12-17T19:17:10.715599Z","shell.execute_reply.started":"2024-12-17T19:17:09.456695Z","shell.execute_reply":"2024-12-17T19:17:10.714682Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Insights\n* It is impossible for me to distinguish by eye an image with cancer from a healthy image\n* on the first image in the second row, we can see that there is discrepancy in the model prediction and actual image status ","metadata":{}},{"cell_type":"code","source":"#save model to disk\nlearn.save(MODEL_EXPORT)","metadata":{"papermill":{"duration":0.104405,"end_time":"2021-10-24T19:00:19.168585","exception":false,"start_time":"2021-10-24T19:00:19.06418","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:17:11.655703Z","iopub.execute_input":"2024-12-17T19:17:11.656083Z","iopub.status.idle":"2024-12-17T19:17:11.717054Z","shell.execute_reply.started":"2024-12-17T19:17:11.656054Z","shell.execute_reply":"2024-12-17T19:17:11.716086Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"interp = ClassificationInterpretation.from_learner(learn)\ninterp.plot_top_losses(9, figsize=(15,11))","metadata":{"papermill":{"duration":1.564351,"end_time":"2021-10-24T19:00:20.773945","exception":false,"start_time":"2021-10-24T19:00:19.209594","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:17:12.477711Z","iopub.execute_input":"2024-12-17T19:17:12.478056Z","iopub.status.idle":"2024-12-17T19:17:52.036664Z","shell.execute_reply.started":"2024-12-17T19:17:12.478028Z","shell.execute_reply":"2024-12-17T19:17:52.035556Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Prepare test images","metadata":{}},{"cell_type":"code","source":"%%capture\n\n!pip install /kaggle/input/rsnamodules/dicomsdl-0.109.1-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl \n\ntry:\n    import pylibjpeg\nexcept:\n   !pip install /kaggle/input/rsna-2022-whl/{pylibjpeg-1.4.0-py3-none-any.whl,python_gdcm-3.0.15-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:17:55.836296Z","iopub.execute_input":"2024-12-17T19:17:55.837232Z","iopub.status.idle":"2024-12-17T19:18:06.121464Z","shell.execute_reply.started":"2024-12-17T19:17:55.837187Z","shell.execute_reply":"2024-12-17T19:18:06.120164Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import dicomsdl as dicoml\nimport cv2\nimport pydicom\n\nfrom joblib import Parallel, delayed\nimport glob","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:18:07.85216Z","iopub.execute_input":"2024-12-17T19:18:07.853139Z","iopub.status.idle":"2024-12-17T19:18:08.066618Z","shell.execute_reply.started":"2024-12-17T19:18:07.853101Z","shell.execute_reply":"2024-12-17T19:18:08.065885Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\nfrom pathlib import Path\nimport numpy as np\nfrom PIL import Image\n\nRESIZE_TO = (512, 512)\n!rm -rf test\n!mkdir test\n\ndef dicom_file_to_ary_v1(path):\n    dicom = pydicom.read_file(path)\n    data = dicom.pixel_array\n    if dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        data = np.amax(data) - data\n    data = data - np.min(data)\n    data = data / np.max(data)\n    data = (data * 255).astype(np.uint8)\n    return data\n\ndef dicom_file_to_ary(path):\n    dicom = dicoml.open(path)\n    data = dicom.pixelData()\n\n    if dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        data = np.amax(data) - data\n    data = data - np.min(data)\n    data = data / np.max(data)\n    data = (data * 255).astype(np.uint8)\n    return data\n\ndirectories = list(Path('/kaggle/input/rsna-breast-cancer-detection/test_images').iterdir())\n\ndef process_directory(directory_path):\n    parent_directory = str(directory_path).split('/')[-1]\n    !mkdir -p test/{parent_directory}\n    for image_path in directory_path.iterdir():\n        processed_ary = dicom_file_to_ary(str(image_path))\n        im = Image.fromarray(processed_ary).resize(RESIZE_TO)\n        im.save(f'test/{parent_directory}/{image_path.stem}.png')\n        \nimport multiprocessing as mp\n\nwith mp.Pool(64) as p:\n    p.map(process_directory, directories)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:18:09.591579Z","iopub.execute_input":"2024-12-17T19:18:09.592363Z","iopub.status.idle":"2024-12-17T19:18:19.742403Z","shell.execute_reply.started":"2024-12-17T19:18:09.592327Z","shell.execute_reply":"2024-12-17T19:18:19.741274Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_test = pd.read_csv(\"/kaggle/input/rsna-breast-cancer-detection/test.csv\")\ndf_test['file'] = df_test.apply(lambda x: f'{x[\"patient_id\"]}/{x[\"image_id\"]}.png', axis=1)\ndf_test.head(5)","metadata":{"papermill":{"duration":0.120071,"end_time":"2021-10-24T19:00:20.941485","exception":false,"start_time":"2021-10-24T19:00:20.821414","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:18:28.685558Z","iopub.execute_input":"2024-12-17T19:18:28.685944Z","iopub.status.idle":"2024-12-17T19:18:28.769503Z","shell.execute_reply.started":"2024-12-17T19:18:28.685911Z","shell.execute_reply":"2024-12-17T19:18:28.768679Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Predict stage","metadata":{"papermill":{"duration":0.045747,"end_time":"2021-10-24T19:00:21.032654","exception":false,"start_time":"2021-10-24T19:00:20.986907","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# load weights\nlearn = vision_learner(image_data, Net, metrics=[error_rate, accuracy], model_dir=\"/tmp/model/\").to_fp16()\nlearn_new = learn.load(MODEL_EXPORT)","metadata":{"papermill":{"duration":0.102848,"end_time":"2021-10-24T19:00:21.18075","exception":false,"start_time":"2021-10-24T19:00:21.077902","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:18:30.75698Z","iopub.execute_input":"2024-12-17T19:18:30.757336Z","iopub.status.idle":"2024-12-17T19:18:30.832051Z","shell.execute_reply.started":"2024-12-17T19:18:30.757308Z","shell.execute_reply":"2024-12-17T19:18:30.831024Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\npreds = []\nfor _, row in df_test.iterrows():\n    full_path = f'./test/{row[\"file\"]}'\n    prediction = learn.predict(full_path)\n    probability = prediction[2][1].item()\n    print(probability)\n    preds.append(probability)","metadata":{"papermill":{"duration":2.291883,"end_time":"2021-10-24T19:00:23.518459","exception":false,"start_time":"2021-10-24T19:00:21.226576","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:18:32.077776Z","iopub.execute_input":"2024-12-17T19:18:32.078381Z","iopub.status.idle":"2024-12-17T19:18:32.289208Z","shell.execute_reply.started":"2024-12-17T19:18:32.07835Z","shell.execute_reply":"2024-12-17T19:18:32.28826Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_test['cancer']=preds","metadata":{"papermill":{"duration":0.165168,"end_time":"2021-10-24T19:00:23.78773","exception":false,"start_time":"2021-10-24T19:00:23.622562","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:18:33.314887Z","iopub.execute_input":"2024-12-17T19:18:33.31559Z","iopub.status.idle":"2024-12-17T19:18:33.370094Z","shell.execute_reply.started":"2024-12-17T19:18:33.315561Z","shell.execute_reply":"2024-12-17T19:18:33.369155Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_output = df_test[['prediction_id', 'cancer']].groupby('prediction_id').mean().reset_index()\ndf_output.to_csv('submission.csv', index=False)\ndf_output.head()","metadata":{"papermill":{"duration":0.169518,"end_time":"2021-10-24T19:00:24.334656","exception":false,"start_time":"2021-10-24T19:00:24.165138","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:18:33.952997Z","iopub.execute_input":"2024-12-17T19:18:33.953834Z","iopub.status.idle":"2024-12-17T19:18:34.019022Z","shell.execute_reply.started":"2024-12-17T19:18:33.953803Z","shell.execute_reply":"2024-12-17T19:18:34.017892Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"###  Additonal Training Models","metadata":{}},{"cell_type":"code","source":"\nimport numpy as np\nimport time\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nimport torchvision.transforms as transforms\nfrom torch.utils.data import DataLoader\nfrom PIL import Image\nfrom torchvision import models\nimport os\nimport shutil\nfrom sklearn.model_selection import train_test_split\nfrom pathlib import Path\n\ndensenet = models.densenet121(pretrained=False)\nresnet = models.resnet50(pretrained=False)\nvgg = models.vgg16(pretrained=False)\nmobilenet = models.mobilenet_v2(pretrained=False)\n\n\ntransform_train = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.RandomHorizontalFlip(p=0.5),\n    transforms.RandomRotation(15),\n    transforms.ColorJitter(brightness=0.2, contrast=0.2),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\ntransform_val = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:18:36.788284Z","iopub.execute_input":"2024-12-17T19:18:36.789073Z","iopub.status.idle":"2024-12-17T19:18:39.735906Z","shell.execute_reply.started":"2024-12-17T19:18:36.78904Z","shell.execute_reply":"2024-12-17T19:18:39.735166Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Snippet 2: Directory Creation and Dataset Organization\ndataset_path = '/kaggle/input/breast-ultrasound-images-dataset/Dataset_BUSI_with_GT'\n\n# Create directories\nos.makedirs('./train/benign', exist_ok=True)\nos.makedirs('./train/malignant', exist_ok=True)\nos.makedirs('./train/normal', exist_ok=True)\nos.makedirs('./val/benign', exist_ok=True)\nos.makedirs('./val/malignant', exist_ok=True)\nos.makedirs('./val/normal', exist_ok=True)\nos.makedirs('./test/benign', exist_ok=True)\nos.makedirs('./test/malignant', exist_ok=True)\nos.makedirs('./test/normal', exist_ok=True)\n\ndef organize_dataset(dataset_path, train_ratio=0.7, val_ratio=0.15, test_ratio=0.15):\n    for category in ['benign', 'malignant', 'normal']:\n        category_path = os.path.join(dataset_path, category)\n        if os.path.exists(category_path):\n            files = [f for f in os.listdir(category_path) if f.endswith('.png')]\n            \n            train_files, temp_files = train_test_split(files, train_size=train_ratio, random_state=42)\n            val_files, test_files = train_test_split(temp_files, train_size=val_ratio/(val_ratio + test_ratio), random_state=42)\n            \n            for file in train_files:\n                src = os.path.join(category_path, file)\n                dst = os.path.join(f'./train/{category}', file)\n                shutil.copy2(src, dst)\n                \n            for file in val_files:\n                src = os.path.join(category_path, file)\n                dst = os.path.join(f'./val/{category}', file)\n                shutil.copy2(src, dst)\n                \n            for file in test_files:\n                src = os.path.join(category_path, file)\n                dst = os.path.join(f'./test/{category}', file)\n                shutil.copy2(src, dst)\n            \n            print(f\"{category}: {len(train_files)} train, {len(val_files)} validation, {len(test_files)} test\")\n\n# Organize the dataset\norganize_dataset(dataset_path)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:18:43.168081Z","iopub.execute_input":"2024-12-17T19:18:43.168496Z","iopub.status.idle":"2024-12-17T19:18:45.103266Z","shell.execute_reply.started":"2024-12-17T19:18:43.168458Z","shell.execute_reply":"2024-12-17T19:18:45.102357Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Snippet 3: Data Loaders\nfrom torchvision.datasets import ImageFolder\n\n\ntrain_dataset = ImageFolder(root='./train', transform=transform_train)\nval_dataset = ImageFolder(root='./val', transform=transform_val)\ntest_dataset = ImageFolder(root='./test', transform=transform_val)\n\n# Modify batch size\ntrain_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=16, shuffle=False)\ntest_loader = DataLoader(test_dataset, batch_size=16, shuffle=False)\n\n# Set device\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nprint(f\"Using device: {device}\")\n\n# Print dataset information\nprint(f\"Number of training samples: {len(train_dataset)}\")\nprint(f\"Number of validation samples: {len(val_dataset)}\")\nprint(f\"Number of test samples: {len(test_dataset)}\")\nprint(f\"Classes: {train_dataset.classes}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:18:48.462669Z","iopub.execute_input":"2024-12-17T19:18:48.463017Z","iopub.status.idle":"2024-12-17T19:18:48.53189Z","shell.execute_reply.started":"2024-12-17T19:18:48.462988Z","shell.execute_reply":"2024-12-17T19:18:48.530541Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class ImageClassifier(nn.Module):\n    def __init__(self, base_model, num_classes=3):\n        super(ImageClassifier, self).__init__()\n        self.base_model = base_model\n        \n        # Get number of features before modifying the model\n        if isinstance(base_model, models.DenseNet):\n            self.base_model = models.densenet121(pretrained=False)\n            num_features = self.base_model.classifier.in_features\n        elif isinstance(base_model, models.ResNet):\n            self.base_model = models.resnet50(pretrained=False)\n            num_features = self.base_model.fc.in_features\n        elif isinstance(base_model, models.VGG):\n            self.base_model = models.vgg16(pretrained=False)\n            num_features = 25088\n        elif isinstance(base_model, models.MobileNetV2):\n            self.base_model = models.mobilenet_v2(pretrained=False)\n            num_features = self.base_model.classifier[-1].in_features\n            \n        # Enhanced classifier architecture\n        if isinstance(base_model, models.VGG) or isinstance(base_model, models.MobileNetV2):\n            self.classifier = nn.Sequential(\n                nn.Linear(num_features, 1024),\n                nn.BatchNorm1d(1024),\n                nn.ReLU(),\n                nn.Dropout(0.4),\n                nn.Linear(1024, 512),\n                nn.BatchNorm1d(512),\n                nn.ReLU(),\n                nn.Dropout(0.4),\n                nn.Linear(512, num_classes)\n            )\n        else:\n            self.classifier = nn.Sequential(\n                nn.Linear(num_features, 512),\n                nn.BatchNorm1d(512),\n                nn.ReLU(),\n                nn.Dropout(0.3),\n                nn.Linear(512, num_classes)\n            )\n        \n        # Replace original classifiers\n        if isinstance(base_model, models.DenseNet):\n            self.base_model.classifier = nn.Identity()\n        elif isinstance(base_model, models.ResNet):\n            self.base_model.fc = nn.Identity()\n        elif isinstance(base_model, models.VGG):\n            self.base_model.classifier = nn.Identity()\n        elif isinstance(base_model, models.MobileNetV2):\n            self.base_model.classifier = nn.Identity()\n    \n    def forward(self, x):\n        features = self.base_model(x)\n        if isinstance(self.base_model, models.VGG):\n            features = features.view(features.size(0), -1)\n        return self.classifier(features)\n\n# Initialize models with custom classifier\nmodels_dict = {\n    'DenseNet': ImageClassifier(densenet),\n    'ResNet': ImageClassifier(resnet),\n    'VGG': ImageClassifier(vgg),\n    'MobileNet': ImageClassifier(mobilenet)\n}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:18:52.71925Z","iopub.execute_input":"2024-12-17T19:18:52.719853Z","iopub.status.idle":"2024-12-17T19:18:56.194411Z","shell.execute_reply.started":"2024-12-17T19:18:52.719822Z","shell.execute_reply":"2024-12-17T19:18:56.193636Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train_model(model, train_loader, val_loader, num_epochs=20, device='cpu'):\n    from sklearn.metrics import f1_score, precision_score, recall_score, cohen_kappa_score, roc_auc_score\n    \n    model = model.to(device)\n    criterion = nn.CrossEntropyLoss()\n    optimizer = torch.optim.Adam(model.parameters(), lr=0.0001, weight_decay=1e-4)\n    scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(\n        optimizer, mode='min', factor=0.1, patience=3, verbose=True\n    )\n    \n    best_val_acc = 0.0\n    patience = 5\n    patience_counter = 0\n    history = {'train_loss': [], 'val_loss': [], 'train_acc': [], 'val_acc': []}\n    \n    for epoch in range(num_epochs):\n        # Training phase\n        model.train()\n        train_loss = 0.0\n        train_correct = 0\n        train_total = 0\n        train_labels = []\n        train_predictions = []\n        \n        for inputs, labels in train_loader:\n            inputs, labels = inputs.to(device), labels.to(device)\n            optimizer.zero_grad()\n            outputs = model(inputs)\n            loss = criterion(outputs, labels)\n            loss.backward()\n            torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)\n            optimizer.step()\n            \n            train_loss += loss.item()\n            _, predicted = outputs.max(1)\n            train_total += labels.size(0)\n            train_correct += predicted.eq(labels).sum().item()\n            train_labels.extend(labels.cpu().numpy())\n            train_predictions.extend(predicted.cpu().numpy())\n        \n        train_loss = train_loss / len(train_loader)\n        train_acc = 100. * train_correct / train_total\n        \n        # Validation phase\n        model.eval()\n        val_loss = 0.0\n        val_correct = 0\n        val_total = 0\n        val_labels = []\n        val_predictions = []\n        \n        with torch.no_grad():\n            for inputs, labels in val_loader:\n                inputs, labels = inputs.to(device), labels.to(device)\n                outputs = model(inputs)\n                loss = criterion(outputs, labels)\n                \n                val_loss += loss.item()\n                _, predicted = outputs.max(1)\n                val_total += labels.size(0)\n                val_correct += predicted.eq(labels).sum().item()\n                val_labels.extend(labels.cpu().numpy())\n                val_predictions.extend(predicted.cpu().numpy())\n        \n        val_loss = val_loss / len(val_loader)\n        val_acc = 100. * val_correct / val_total\n        \n        # Calculate additional metrics\n        train_f1 = f1_score(train_labels, train_predictions, average='weighted')\n        train_precision = precision_score(train_labels, train_predictions, average='weighted')\n        train_recall = recall_score(train_labels, train_predictions, average='weighted')\n        train_kappa = cohen_kappa_score(train_labels, train_predictions)\n        train_auc = roc_auc_score(train_labels, nn.functional.one_hot(torch.tensor(train_predictions), num_classes=3), multi_class='ovr')\n        \n        val_f1 = f1_score(val_labels, val_predictions, average='weighted')\n        val_precision = precision_score(val_labels, val_predictions, average='weighted')\n        val_recall = recall_score(val_labels, val_predictions, average='weighted')\n        val_kappa = cohen_kappa_score(val_labels, val_predictions)\n        val_auc = roc_auc_score(val_labels, nn.functional.one_hot(torch.tensor(val_predictions), num_classes=3), multi_class='ovr')\n        \n        print(f'Epoch [{epoch+1}/{num_epochs}]')\n        print(f'Train Loss: {train_loss:.4f}, Train Acc: {train_acc:.2f}%')\n        print(f'Train Metrics - F1: {train_f1:.4f}, Precision: {train_precision:.4f}, Recall: {train_recall:.4f}')\n        print(f'Train Metrics - Kappa: {train_kappa:.4f}, AUC: {train_auc:.4f}')\n        print(f'Val Loss: {val_loss:.4f}, Val Acc: {val_acc:.2f}%')\n        print(f'Val Metrics - F1: {val_f1:.4f}, Precision: {val_precision:.4f}, Recall: {val_recall:.4f}')\n        print(f'Val Metrics - Kappa: {val_kappa:.4f}, AUC: {val_auc:.4f}')\n        print('-' * 50)\n        \n        scheduler.step(val_loss)\n        \n        if val_acc > best_val_acc:\n            best_val_acc = val_acc\n            best_model_state = model.state_dict()\n            patience_counter = 0\n        else:\n            patience_counter += 1\n            if patience_counter >= patience:\n                print(f'Early stopping triggered at epoch {epoch+1}')\n                break\n        \n        history['train_loss'].append(train_loss)\n        history['val_loss'].append(val_loss)\n        history['train_acc'].append(train_acc)\n        history['val_acc'].append(val_acc)\n    \n    model.load_state_dict(best_model_state)\n    return model, history","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:19:01.284591Z","iopub.execute_input":"2024-12-17T19:19:01.284976Z","iopub.status.idle":"2024-12-17T19:19:01.352439Z","shell.execute_reply.started":"2024-12-17T19:19:01.284946Z","shell.execute_reply":"2024-12-17T19:19:01.351423Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Snippet 6: Training Execution\ndef train_all_models(models_dict, train_loader, val_loader, num_epochs=10, device='cpu'):\n    results = {}\n    histories = {}\n    \n    for name, model in models_dict.items():\n        print(f'\\nTraining {name}...')\n        print('=' * 50)\n        \n        trained_model, history = train_model(\n            model, \n            train_loader, \n            val_loader, \n            num_epochs=num_epochs, \n            device=device\n        )\n        \n        results[name] = trained_model\n        histories[name] = history\n    \n    return results, histories","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:19:03.660169Z","iopub.execute_input":"2024-12-17T19:19:03.661227Z","iopub.status.idle":"2024-12-17T19:19:03.715748Z","shell.execute_reply.started":"2024-12-17T19:19:03.661181Z","shell.execute_reply":"2024-12-17T19:19:03.714886Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Snippet 7: Final Execution and Evaluation\ntry:\n    print(\"Starting model training...\")\n    \n    # Train all models\n    trained_models, histories = train_all_models(\n        models_dict,\n        train_loader,\n        val_loader,\n        num_epochs=10,  # You can adjust this\n        device=device\n    )\n    \n    # Evaluate models\n    print(\"\\nEvaluating models on test set...\")\n    for name, model in trained_models.items():\n        model.eval()\n        correct = 0\n        total = 0\n        \n        with torch.no_grad():\n            for inputs, labels in test_loader:\n                inputs, labels = inputs.to(device), labels.to(device)\n                outputs = model(inputs)\n                _, predicted = outputs.max(1)\n                total += labels.size(0)\n                correct += predicted.eq(labels).sum().item()\n        \n        accuracy = 100. * correct / total\n        print(f\"{name} Test Accuracy: {accuracy:.2f}%\")\n\nexcept Exception as e:\n    print(f\"An error occurred: {str(e)}\")\n    import traceback\n    traceback.print_exc()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:19:05.947188Z","iopub.execute_input":"2024-12-17T19:19:05.948036Z","iopub.status.idle":"2024-12-17T19:35:55.212855Z","shell.execute_reply.started":"2024-12-17T19:19:05.948004Z","shell.execute_reply":"2024-12-17T19:35:55.211799Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"###  Implementing DATTNet (Dual Attention Network)","metadata":{}},{"cell_type":"code","source":"pip install einops","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:36:34.693563Z","iopub.execute_input":"2024-12-17T19:36:34.694546Z","iopub.status.idle":"2024-12-17T19:36:43.38101Z","shell.execute_reply.started":"2024-12-17T19:36:34.694498Z","shell.execute_reply":"2024-12-17T19:36:43.379439Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 1: Imports and Setup\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom PIL import Image\nimport os\nimport numpy as np\nfrom torch.optim.lr_scheduler import ReduceLROnPlateau\n\n# Define transforms\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:36:46.713177Z","iopub.execute_input":"2024-12-17T19:36:46.713588Z","iopub.status.idle":"2024-12-17T19:36:46.780811Z","shell.execute_reply.started":"2024-12-17T19:36:46.713551Z","shell.execute_reply":"2024-12-17T19:36:46.779666Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 2: Modified DATTNet for Classification\nclass DATTNet(nn.Module):\n    def __init__(self, in_channels=3, num_classes=3):\n        super(DATTNet, self).__init__()\n        \n        # Encoder\n        self.enc1 = self._make_layer(in_channels, 64)\n        self.enc2 = self._make_layer(64, 128)\n        self.enc3 = self._make_layer(128, 256)\n        self.enc4 = self._make_layer(256, 512)\n        \n        # Channel Attention\n        self.channel_att = nn.Sequential(\n            nn.AdaptiveAvgPool2d(1),\n            nn.Conv2d(512, 32, 1),\n            nn.ReLU(),\n            nn.Conv2d(32, 512, 1),\n            nn.Sigmoid()\n        )\n        \n        # Spatial Attention\n        self.spatial_att = nn.Sequential(\n            nn.Conv2d(512, 1, 7, padding=3),\n            nn.Sigmoid()\n        )\n        \n        # Classification head\n        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n        self.classifier = nn.Sequential(\n            nn.Linear(512, 256),\n            nn.ReLU(),\n            nn.Dropout(0.5),\n            nn.Linear(256, num_classes)\n        )\n        \n    def _make_layer(self, in_channels, out_channels):\n        return nn.Sequential(\n            nn.Conv2d(in_channels, out_channels, 3, padding=1),\n            nn.BatchNorm2d(out_channels),\n            nn.ReLU(inplace=True),\n            nn.Conv2d(out_channels, out_channels, 3, padding=1),\n            nn.BatchNorm2d(out_channels),\n            nn.ReLU(inplace=True)\n        )\n    \n    def forward(self, x):\n        # Encoder\n        e1 = self.enc1(x)\n        e2 = self.enc2(F.max_pool2d(e1, 2))\n        e3 = self.enc3(F.max_pool2d(e2, 2))\n        e4 = self.enc4(F.max_pool2d(e3, 2))\n        \n        # Attention\n        ca = self.channel_att(e4) * e4\n        sa = self.spatial_att(ca) * ca\n        \n        # Classification\n        x = self.avgpool(sa)\n        x = torch.flatten(x, 1)\n        x = self.classifier(x)\n        \n        return x","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:36:55.816914Z","iopub.execute_input":"2024-12-17T19:36:55.817265Z","iopub.status.idle":"2024-12-17T19:36:55.879331Z","shell.execute_reply.started":"2024-12-17T19:36:55.817237Z","shell.execute_reply":"2024-12-17T19:36:55.878283Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 3: Dataset Class (Same as before)\nclass BreastUltrasoundDataset(Dataset):\n    def __init__(self, root_dir, transform=None):\n        self.root_dir = root_dir\n        self.transform = transform\n        self.classes = ['benign', 'malignant', 'normal']\n        self.images = []\n        self.labels = []\n        \n        for class_idx, class_name in enumerate(self.classes):\n            class_path = os.path.join(root_dir, class_name)\n            if os.path.exists(class_path):\n                for img_name in os.listdir(class_path):\n                    if img_name.endswith('.png'):\n                        self.images.append(os.path.join(class_path, img_name))\n                        self.labels.append(class_idx)\n    \n    def __len__(self):\n        return len(self.images)\n    \n    def __getitem__(self, idx):\n        img_path = self.images[idx]\n        image = Image.open(img_path).convert('RGB')\n        label = self.labels[idx]\n        \n        if self.transform:\n            image = self.transform(image)\n        \n        return image, torch.tensor(label, dtype=torch.long)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:37:10.609967Z","iopub.execute_input":"2024-12-17T19:37:10.610322Z","iopub.status.idle":"2024-12-17T19:37:10.673734Z","shell.execute_reply.started":"2024-12-17T19:37:10.610295Z","shell.execute_reply":"2024-12-17T19:37:10.672773Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 4: Data Loading Function (Same as before)\ndef prepare_data(dataset_path, batch_size=16):\n    full_dataset = BreastUltrasoundDataset(dataset_path, transform=transform)\n    \n    train_size = int(0.7 * len(full_dataset))\n    val_size = int(0.15 * len(full_dataset))\n    test_size = len(full_dataset) - train_size - val_size\n    \n    train_dataset, val_dataset, test_dataset = torch.utils.data.random_split(\n        full_dataset, [train_size, val_size, test_size]\n    )\n    \n    train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\n    val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False)\n    test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)\n    \n    return train_loader, val_loader, test_loader","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:37:24.635857Z","iopub.execute_input":"2024-12-17T19:37:24.636251Z","iopub.status.idle":"2024-12-17T19:37:24.695491Z","shell.execute_reply.started":"2024-12-17T19:37:24.636219Z","shell.execute_reply":"2024-12-17T19:37:24.694464Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train_dattnet(model, train_loader, val_loader, num_epochs=20, device='cuda'):\n    from sklearn.metrics import f1_score, precision_score, recall_score, cohen_kappa_score, roc_auc_score\n    \n    criterion = nn.CrossEntropyLoss()\n    optimizer = torch.optim.AdamW(model.parameters(), lr=0.0001, weight_decay=1e-4)\n    scheduler = ReduceLROnPlateau(optimizer, mode='min', patience=3)\n    \n    best_val_loss = float('inf')\n    \n    for epoch in range(num_epochs):\n        # Training\n        model.train()\n        train_loss = 0\n        train_correct = 0\n        train_total = 0\n        \n        for batch_idx, (images, labels) in enumerate(train_loader):\n            images, labels = images.to(device), labels.to(device)\n            \n            optimizer.zero_grad()\n            outputs = model(images)\n            loss = criterion(outputs, labels)\n            loss.backward()\n            optimizer.step()\n            \n            train_loss += loss.item()\n            _, predicted = outputs.max(1)\n            train_total += labels.size(0)\n            train_correct += predicted.eq(labels).sum().item()\n            \n            if batch_idx % 10 == 0:\n                print(f'Epoch: {epoch+1}, Batch: {batch_idx}, Loss: {loss.item():.4f}')\n        \n        # Validation\n        model.eval()\n        val_loss = 0\n        val_correct = 0\n        val_total = 0\n        all_labels = []\n        all_predictions = []\n        \n        with torch.no_grad():\n            for images, labels in val_loader:\n                images, labels = images.to(device), labels.to(device)\n                outputs = model(images)\n                loss = criterion(outputs, labels)\n                \n                val_loss += loss.item()\n                _, predicted = outputs.max(1)\n                val_total += labels.size(0)\n                val_correct += predicted.eq(labels).sum().item()\n                \n                all_labels.extend(labels.cpu().numpy())\n                all_predictions.extend(predicted.cpu().numpy())\n        \n        # Calculate metrics\n        train_loss = train_loss / len(train_loader)\n        train_acc = 100. * train_correct / train_total\n        val_loss = val_loss / len(val_loader)\n        val_acc = 100. * val_correct / val_total\n        \n        # Additional metrics\n        f1 = f1_score(all_labels, all_predictions, average='weighted')\n        precision = precision_score(all_labels, all_predictions, average='weighted')\n        recall = recall_score(all_labels, all_predictions, average='weighted')\n        kappa = cohen_kappa_score(all_labels, all_predictions)\n        auc = roc_auc_score(all_labels, nn.functional.one_hot(torch.tensor(all_predictions), num_classes=3), multi_class='ovr')\n        \n        print(f'Epoch [{epoch+1}/{num_epochs}]')\n        print(f'Train Loss: {train_loss:.4f}, Train Acc: {train_acc:.2f}%')\n        print(f'Val Loss: {val_loss:.4f}, Val Acc: {val_acc:.2f}%')\n        print(f'F1 Score: {f1:.4f}, Precision: {precision:.4f}, Recall: {recall:.4f}')\n        print(f'Cohen Kappa: {kappa:.4f}, AUC: {auc:.4f}')\n        print('-' * 50)\n        \n        scheduler.step(val_loss)\n        \n        if val_loss < best_val_loss:\n            best_val_loss = val_loss\n            torch.save(model.state_dict(), 'best_dattnet.pth')\n    \n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:37:54.847038Z","iopub.execute_input":"2024-12-17T19:37:54.847409Z","iopub.status.idle":"2024-12-17T19:37:54.913032Z","shell.execute_reply.started":"2024-12-17T19:37:54.847378Z","shell.execute_reply":"2024-12-17T19:37:54.911896Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 6: Main Execution\nif __name__ == \"__main__\":\n    # Set device\n    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n    print(f\"Using device: {device}\")\n    \n    # Path to your dataset\n    dataset_path = '/kaggle/input/breast-ultrasound-images-dataset/Dataset_BUSI_with_GT'\n    \n    # Prepare data\n    train_loader, val_loader, test_loader = prepare_data(dataset_path)\n    \n    # Initialize model\n    model = DATTNet(in_channels=3, num_classes=3).to(device)\n    \n    # Train model\n    trained_model = train_dattnet(\n        model=model,\n        train_loader=train_loader,\n        val_loader=val_loader,\n        num_epochs=20,\n        device=device\n    )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:38:00.355303Z","iopub.execute_input":"2024-12-17T19:38:00.35569Z","iopub.status.idle":"2024-12-17T19:46:59.25575Z","shell.execute_reply.started":"2024-12-17T19:38:00.355659Z","shell.execute_reply":"2024-12-17T19:46:59.254684Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Cell 7: Prediction Stage\n\ndef predict_cancer_likelihood(model, image_path, device='cuda'):\n    # Prepare image\n    image = Image.open(image_path).convert('RGB')\n    image_tensor = transform(image).unsqueeze(0).to(device)\n    \n    model.eval()\n    with torch.no_grad():\n        outputs = model(image_tensor)\n        probabilities = F.softmax(outputs, dim=1)\n        cancer_prob = probabilities[0][1].item() * 100  # Probability of malignant class\n    \n    return cancer_prob\n\ndef evaluate_and_show_examples(model, test_loader, device='cuda'):\n    from sklearn.metrics import accuracy_score, classification_report\n    \n    model.eval()\n    all_labels = []\n    all_predictions = []\n    example_images = []\n    \n    with torch.no_grad():\n        for images, labels in test_loader:\n            images, labels = images.to(device), labels.to(device)\n            outputs = model(images)\n            probabilities = F.softmax(outputs, dim=1)\n            _, predicted = torch.max(outputs, 1)\n            \n            all_labels.extend(labels.cpu().numpy())\n            all_predictions.extend(predicted.cpu().numpy())\n            \n            # Store first few examples\n            if len(example_images) < 3:\n                for i in range(min(3 - len(example_images), len(images))):\n                    example_images.append({\n                        'image_id': f'sample_{len(example_images) + 1}',\n                        'true_label': labels[i].item(),\n                        'predicted': predicted[i].item(),\n                        'cancer_likelihood': probabilities[i][1].item() * 100\n                    })\n    \n    # Print overall metrics\n    accuracy = accuracy_score(all_labels, all_predictions)\n    report = classification_report(all_labels, all_predictions, \n                                 target_names=['benign', 'malignant', 'normal'])\n    \n    print(f\"Overall Test Accuracy: {accuracy*100:.2f}%\")\n    print(\"\\nDetailed Classification Report:\")\n    print(report)\n    \n    # Print example predictions\n    print(\"\\nExample Predictions:\")\n    print(\"-\" * 50)\n    for example in example_images:\n        print(f\"Image ID: {example['image_id']}\")\n        print(f\"True Label: {'malignant' if example['true_label'] == 1 else 'benign/normal'}\")\n        print(f\"Cancer Likelihood: {example['cancer_likelihood']:.1f}%\")\n        print(\"-\" * 50)\n\n# Run evaluation\nevaluate_and_show_examples(trained_model, test_loader, device)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-17T19:48:17.775196Z","iopub.execute_input":"2024-12-17T19:48:17.77586Z","iopub.status.idle":"2024-12-17T19:48:21.091387Z","shell.execute_reply.started":"2024-12-17T19:48:17.775824Z","shell.execute_reply":"2024-12-17T19:48:21.090477Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}