{"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":4619805,"sourceType":"datasetVersion","datasetId":2688675}],"dockerImageVersionId":30408,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# TensorFlow libraries\nimport tensorflow as tf\nfrom tensorflow.keras.optimizers import RMSprop\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.layers import Concatenate\n\n# basic libraries\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import classification_report, confusion_matrix\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport cv2\nimport os\n\nimport glob\nfrom glob import glob\n\nimport os\nimport sys\nimport random\nimport warnings\n\nimport numpy as np\nimport pandas as pd\n\nimport matplotlib.pyplot as plt\n\nfrom tqdm import tqdm\nfrom itertools import chain\nfrom skimage.io import imread, imshow, imread_collection, concatenate_images\nfrom skimage.transform import resize\nfrom skimage.morphology import label\n\nfrom keras.models import Model, load_model\nfrom keras.layers import Input\nfrom keras.layers.core import Dropout, Lambda\nfrom keras.layers.convolutional import Conv2D, Conv2DTranspose\nfrom keras.layers.pooling import MaxPooling2D\nfrom keras.callbacks import EarlyStopping, ModelCheckpoint\nfrom keras import backend as K\n\nimport tensorflow as tf\n\nimport warnings\nwarnings.filterwarnings('ignore')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:55.972523Z","iopub.execute_input":"2025-10-14T13:47:55.972899Z","iopub.status.idle":"2025-10-14T13:47:55.983259Z","shell.execute_reply.started":"2025-10-14T13:47:55.972869Z","shell.execute_reply":"2025-10-14T13:47:55.982046Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Read the CSV File\n\nNext, we get the paths to access the image data and csv data. The csv data include various information about patients, such as biopsy, malignant cancer, and invasive cancer.","metadata":{}},{"cell_type":"code","source":"# the path to the image data\nRSNA_512_path = '/kaggle/input/rsna-breast-cancer-512-pngs'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:55.985346Z","iopub.execute_input":"2025-10-14T13:47:55.985644Z","iopub.status.idle":"2025-10-14T13:47:55.994418Z","shell.execute_reply.started":"2025-10-14T13:47:55.985605Z","shell.execute_reply":"2025-10-14T13:47:55.993344Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Read the csv data.\ndf_train = pd.read_csv('/kaggle/input/rsna-breast-cancer-detection/train.csv')\ndf_train.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:55.995733Z","iopub.execute_input":"2025-10-14T13:47:55.996528Z","iopub.status.idle":"2025-10-14T13:47:56.072699Z","shell.execute_reply.started":"2025-10-14T13:47:55.996498Z","shell.execute_reply":"2025-10-14T13:47:56.071629Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Tổng bệnh nhân\nlen(df_train)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:56.074108Z","iopub.execute_input":"2025-10-14T13:47:56.07494Z","iopub.status.idle":"2025-10-14T13:47:56.082189Z","shell.execute_reply.started":"2025-10-14T13:47:56.074898Z","shell.execute_reply":"2025-10-14T13:47:56.080873Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Số người có cấy ghép ngực\nlen(df_train[df_train['implant'] == 1])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:56.085115Z","iopub.execute_input":"2025-10-14T13:47:56.085682Z","iopub.status.idle":"2025-10-14T13:47:56.093703Z","shell.execute_reply.started":"2025-10-14T13:47:56.085649Z","shell.execute_reply":"2025-10-14T13:47:56.092497Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Số người không mắc bệnh\nlen(df_train[df_train['cancer'] == 0])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:56.095059Z","iopub.execute_input":"2025-10-14T13:47:56.095358Z","iopub.status.idle":"2025-10-14T13:47:56.105544Z","shell.execute_reply.started":"2025-10-14T13:47:56.095322Z","shell.execute_reply":"2025-10-14T13:47:56.104428Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Số người đã lấy mẫu để xét nghiệm\nlen(df_train[df_train['biopsy'] == 1])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:56.106663Z","iopub.execute_input":"2025-10-14T13:47:56.106991Z","iopub.status.idle":"2025-10-14T13:47:56.114853Z","shell.execute_reply.started":"2025-10-14T13:47:56.106956Z","shell.execute_reply":"2025-10-14T13:47:56.113728Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Số người mắc bệnh\nlen(df_train[df_train['cancer'] == 1])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:56.1163Z","iopub.execute_input":"2025-10-14T13:47:56.116925Z","iopub.status.idle":"2025-10-14T13:47:56.124743Z","shell.execute_reply.started":"2025-10-14T13:47:56.116888Z","shell.execute_reply":"2025-10-14T13:47:56.123636Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Số ca ung thư có xâm lấn\nlen(df_train[(df_train['cancer'] == 1) & (df_train['invasive'] == 1)])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:56.126014Z","iopub.execute_input":"2025-10-14T13:47:56.126286Z","iopub.status.idle":"2025-10-14T13:47:56.135064Z","shell.execute_reply.started":"2025-10-14T13:47:56.126261Z","shell.execute_reply":"2025-10-14T13:47:56.134003Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data = pd.DataFrame(np.concatenate([['Total'] * len(df_train) , ['Maglignant Cancer'] *  len(df_train[df_train['cancer'] == 1]), ['Invasive Cancer'] *  len(df_train[(df_train['cancer'] == 1) & (df_train['invasive'] == 1)])]), columns = [\"class\"])\n\nsns.countplot(x = 'class', data = data)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:56.136563Z","iopub.execute_input":"2025-10-14T13:47:56.137045Z","iopub.status.idle":"2025-10-14T13:47:56.384092Z","shell.execute_reply.started":"2025-10-14T13:47:56.136994Z","shell.execute_reply":"2025-10-14T13:47:56.383044Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data = pd.DataFrame(np.concatenate([['Biopsy'] * len(df_train[df_train['biopsy'] == 1]) , ['Malignant Cancer'] *  len(df_train[df_train['cancer'] == 1]), ['Invasive Cancer'] *  len(df_train[(df_train['cancer'] == 1) & (df_train['invasive'] == 1)])]), columns = [\"class\"])\n\nsns.countplot(x = 'class', data = data)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:56.385503Z","iopub.execute_input":"2025-10-14T13:47:56.3859Z","iopub.status.idle":"2025-10-14T13:47:56.590048Z","shell.execute_reply.started":"2025-10-14T13:47:56.38586Z","shell.execute_reply":"2025-10-14T13:47:56.588956Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"len(df_train[(df_train['biopsy'] == 1) & (df_train['cancer'] == 0)])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:56.591078Z","iopub.execute_input":"2025-10-14T13:47:56.591324Z","iopub.status.idle":"2025-10-14T13:47:56.600113Z","shell.execute_reply.started":"2025-10-14T13:47:56.591301Z","shell.execute_reply":"2025-10-14T13:47:56.59901Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# the number of malignant cancer cases from biopsy\nlen(df_train[(df_train['biopsy'] == 1) & (df_train['cancer'] == 1)])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:56.601536Z","iopub.execute_input":"2025-10-14T13:47:56.602082Z","iopub.status.idle":"2025-10-14T13:47:56.609758Z","shell.execute_reply.started":"2025-10-14T13:47:56.602054Z","shell.execute_reply":"2025-10-14T13:47:56.608614Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 60% of biopsies resulted in not-malignant cancer.\ndata = pd.DataFrame(np.concatenate([['Biopsy but Not Malignant'] * len(df_train[(df_train['biopsy'] == 1) & (df_train['cancer'] == 0)]) , ['Malignant Cancer'] *  len(df_train[df_train['cancer'] == 1]), ['Invasive Cancer'] *  len(df_train[(df_train['cancer'] == 1) & (df_train['invasive'] == 1)])]), columns = [\"class\"])\n\nsns.countplot(x = 'class', data = data)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:56.614301Z","iopub.execute_input":"2025-10-14T13:47:56.61461Z","iopub.status.idle":"2025-10-14T13:47:56.825717Z","shell.execute_reply.started":"2025-10-14T13:47:56.614556Z","shell.execute_reply":"2025-10-14T13:47:56.824629Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **Từ bệnh nhân đã sinh thiết nhưng không bị ung thư ác tính – phù hợp cho trường hợp nghi ngờ có ung thư**","metadata":{}},{"cell_type":"code","source":"#Lọc dữ liệu\nDF_train = df_train[df_train['biopsy'] == 1].reset_index(drop = True)\nDF_train.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:56.826952Z","iopub.execute_input":"2025-10-14T13:47:56.827249Z","iopub.status.idle":"2025-10-14T13:47:56.845437Z","shell.execute_reply.started":"2025-10-14T13:47:56.827221Z","shell.execute_reply":"2025-10-14T13:47:56.844389Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"DF_train['cancer'].value_counts()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:56.846709Z","iopub.execute_input":"2025-10-14T13:47:56.847012Z","iopub.status.idle":"2025-10-14T13:47:56.854697Z","shell.execute_reply.started":"2025-10-14T13:47:56.846984Z","shell.execute_reply":"2025-10-14T13:47:56.853499Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Cân bằng dữ liệu\nDF_train = DF_train.groupby(['cancer']).apply(lambda x: x.sample(1158, replace = True)\n                                                      ).reset_index(drop = True)\nprint('New Data Size:', DF_train.shape[0])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:56.856119Z","iopub.execute_input":"2025-10-14T13:47:56.856448Z","iopub.status.idle":"2025-10-14T13:47:56.869739Z","shell.execute_reply.started":"2025-10-14T13:47:56.856405Z","shell.execute_reply":"2025-10-14T13:47:56.86855Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Create the Path to Each Image","metadata":{}},{"cell_type":"code","source":"# Create the path to each image.\nfor i in range(len(DF_train)):\n    DF_train.loc[i, 'path'] = os.path.join(RSNA_512_path + '/' + str(DF_train.loc[i, 'patient_id']) + '_' + str(DF_train.loc[i, 'image_id']) + '.png')\nDF_train.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:56.871187Z","iopub.execute_input":"2025-10-14T13:47:56.871591Z","iopub.status.idle":"2025-10-14T13:47:57.683443Z","shell.execute_reply.started":"2025-10-14T13:47:56.871532Z","shell.execute_reply":"2025-10-14T13:47:57.682414Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"DF_train.loc[0, 'path']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:57.685451Z","iopub.execute_input":"2025-10-14T13:47:57.685903Z","iopub.status.idle":"2025-10-14T13:47:57.693198Z","shell.execute_reply.started":"2025-10-14T13:47:57.685858Z","shell.execute_reply":"2025-10-14T13:47:57.692043Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# a sample image\nimg = cv2.imread(DF_train.loc[0, 'path'])\nplt.imshow(img, cmap = 'gray')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:57.694296Z","iopub.execute_input":"2025-10-14T13:47:57.694564Z","iopub.status.idle":"2025-10-14T13:47:57.905222Z","shell.execute_reply.started":"2025-10-14T13:47:57.694539Z","shell.execute_reply":"2025-10-14T13:47:57.904238Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"img","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:57.906636Z","iopub.execute_input":"2025-10-14T13:47:57.906996Z","iopub.status.idle":"2025-10-14T13:47:57.915149Z","shell.execute_reply.started":"2025-10-14T13:47:57.906959Z","shell.execute_reply":"2025-10-14T13:47:57.913926Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"img.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:57.916594Z","iopub.execute_input":"2025-10-14T13:47:57.91748Z","iopub.status.idle":"2025-10-14T13:47:57.923762Z","shell.execute_reply.started":"2025-10-14T13:47:57.917424Z","shell.execute_reply":"2025-10-14T13:47:57.922775Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Chia Training và Validation\n\nThis time we divide the data into training and validation data, because test data originally exist.","metadata":{}},{"cell_type":"code","source":"train_df, val_df = train_test_split(DF_train, \n                                   test_size = 0.30, \n                                   random_state = 2018,\n                                   stratify = DF_train[['cancer']])\n\nprint('train', train_df.shape[0], 'validation', val_df.shape[0])\nprint('train', train_df['cancer'].value_counts())\nprint('validation', val_df['cancer'].value_counts())\ntrain_df.sample(1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:57.924909Z","iopub.execute_input":"2025-10-14T13:47:57.925185Z","iopub.status.idle":"2025-10-14T13:47:57.957785Z","shell.execute_reply.started":"2025-10-14T13:47:57.925142Z","shell.execute_reply":"2025-10-14T13:47:57.956741Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:57.958892Z","iopub.execute_input":"2025-10-14T13:47:57.959173Z","iopub.status.idle":"2025-10-14T13:47:57.97434Z","shell.execute_reply.started":"2025-10-14T13:47:57.95915Z","shell.execute_reply":"2025-10-14T13:47:57.973152Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:57.975697Z","iopub.execute_input":"2025-10-14T13:47:57.976014Z","iopub.status.idle":"2025-10-14T13:47:57.992026Z","shell.execute_reply.started":"2025-10-14T13:47:57.975987Z","shell.execute_reply":"2025-10-14T13:47:57.990998Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Tạo df chứa bình thường\ntrain_df_normal = train_df[train_df['cancer'] == 0].reset_index(drop = True)\nprint(len(train_df_normal))\ntrain_df_normal.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:57.993598Z","iopub.execute_input":"2025-10-14T13:47:57.994022Z","iopub.status.idle":"2025-10-14T13:47:58.013105Z","shell.execute_reply.started":"2025-10-14T13:47:57.993987Z","shell.execute_reply":"2025-10-14T13:47:58.011871Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Tạo df chứa ut\ntrain_df_cancer = train_df[train_df['cancer'] == 1].reset_index(drop = True)\nprint(len(train_df_cancer))\ntrain_df_cancer.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:58.014502Z","iopub.execute_input":"2025-10-14T13:47:58.014958Z","iopub.status.idle":"2025-10-14T13:47:58.034782Z","shell.execute_reply.started":"2025-10-14T13:47:58.014923Z","shell.execute_reply":"2025-10-14T13:47:58.033759Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_df_normal = val_df[val_df['cancer'] == 0].reset_index(drop = True)\nprint(len(val_df_normal))\nval_df_normal.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:58.036078Z","iopub.execute_input":"2025-10-14T13:47:58.036458Z","iopub.status.idle":"2025-10-14T13:47:58.054765Z","shell.execute_reply.started":"2025-10-14T13:47:58.036408Z","shell.execute_reply":"2025-10-14T13:47:58.053483Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_df_cancer = val_df[val_df['cancer'] == 1].reset_index(drop = True)\nprint(len(val_df_cancer))\nval_df_cancer.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:58.056302Z","iopub.execute_input":"2025-10-14T13:47:58.05664Z","iopub.status.idle":"2025-10-14T13:47:58.074628Z","shell.execute_reply.started":"2025-10-14T13:47:58.056605Z","shell.execute_reply":"2025-10-14T13:47:58.073361Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import shutil\n# Khai báo destination directory.\ndestination_dir = '/kaggle/working/train'\ndestination_dir_sub = '/kaggle/working/train/normal'\n\n# Tạo nếu destination directory chưa tồn tại.\nif not os.path.exists(destination_dir):\n    os.makedirs(destination_dir)\n\nif not os.path.exists(destination_dir_sub):\n    os.makedirs(destination_dir_sub)   \n    \n# Copy ảnh vào destination directory.\nfor path in train_df_normal['path']:\n    shutil.copy2(path, destination_dir_sub)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:58.075871Z","iopub.execute_input":"2025-10-14T13:47:58.076189Z","iopub.status.idle":"2025-10-14T13:47:59.913238Z","shell.execute_reply.started":"2025-10-14T13:47:58.076164Z","shell.execute_reply":"2025-10-14T13:47:59.91242Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"destination_dir = '/kaggle/working/train'\ndestination_dir_sub = '/kaggle/working/train/cancer'\n\n# Create the destination directory if it doesn't exist.\nif not os.path.exists(destination_dir):\n    os.makedirs(destination_dir)\n\nif not os.path.exists(destination_dir_sub):\n    os.makedirs(destination_dir_sub)   \n    \n# Copy the images to the destination directory.\nfor path in train_df_cancer['path']:\n    shutil.copy2(path, destination_dir_sub)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:47:59.914353Z","iopub.execute_input":"2025-10-14T13:47:59.914681Z","iopub.status.idle":"2025-10-14T13:48:01.678905Z","shell.execute_reply.started":"2025-10-14T13:47:59.914652Z","shell.execute_reply":"2025-10-14T13:48:01.678135Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Define the destination directory.\ndestination_dir = '/kaggle/working/val'\ndestination_dir_sub = '/kaggle/working/val/normal'\n\n# Create the destination directory if it doesn't exist.\nif not os.path.exists(destination_dir):\n    os.makedirs(destination_dir)\n\nif not os.path.exists(destination_dir_sub):\n    os.makedirs(destination_dir_sub)   \n    \n# Copy the images to the destination directory.\nfor path in val_df_normal['path']:\n    shutil.copy2(path, destination_dir_sub)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:48:01.679958Z","iopub.execute_input":"2025-10-14T13:48:01.680232Z","iopub.status.idle":"2025-10-14T13:48:02.361208Z","shell.execute_reply.started":"2025-10-14T13:48:01.680207Z","shell.execute_reply":"2025-10-14T13:48:02.360305Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Define the destination directory.\ndestination_dir = '/kaggle/working/val'\ndestination_dir_sub = '/kaggle/working/val/cancer'\n\n# Create the destination directory if it doesn't exist.\nif not os.path.exists(destination_dir):\n    os.makedirs(destination_dir)\n\nif not os.path.exists(destination_dir_sub):\n    os.makedirs(destination_dir_sub)   \n    \n# Copy the images to the destination directory.\nfor path in val_df_cancer['path']:\n    shutil.copy2(path, destination_dir_sub)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:48:02.362888Z","iopub.execute_input":"2025-10-14T13:48:02.363268Z","iopub.status.idle":"2025-10-14T13:48:02.878609Z","shell.execute_reply.started":"2025-10-14T13:48:02.363214Z","shell.execute_reply":"2025-10-14T13:48:02.87778Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Sample Images","metadata":{}},{"cell_type":"code","source":"import glob\nnormal_train_images = glob.glob('/kaggle/working/train/normal/*.png')\ncancer_train_images = glob.glob('/kaggle/working/train/cancer/*.png')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:48:02.879846Z","iopub.execute_input":"2025-10-14T13:48:02.880232Z","iopub.status.idle":"2025-10-14T13:48:02.893207Z","shell.execute_reply.started":"2025-10-14T13:48:02.880188Z","shell.execute_reply":"2025-10-14T13:48:02.892139Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# See normal images from the training dataset.\nfig, axes = plt.subplots(nrows = 2, ncols = 5, figsize = (15, 10), subplot_kw = {'xticks':[], 'yticks':[]})\nfor i, ax in enumerate(axes.flat):\n    img = cv2.imread(normal_train_images[i])\n    ax.imshow(img)\n    ax.set_title('Normal')\nfig.tight_layout()    \n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:48:02.894623Z","iopub.execute_input":"2025-10-14T13:48:02.895261Z","iopub.status.idle":"2025-10-14T13:48:03.924912Z","shell.execute_reply.started":"2025-10-14T13:48:02.89522Z","shell.execute_reply":"2025-10-14T13:48:03.92393Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# See cancer images from the training dataset.\nfig, axes = plt.subplots(nrows = 2, ncols = 5, figsize = (15, 10), subplot_kw = {'xticks':[], 'yticks':[]})\nfor i, ax in enumerate(axes.flat):\n    img = cv2.imread(cancer_train_images[i])\n    ax.imshow(img)\n    ax.set_title('Cancer')\n    \nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:48:03.926444Z","iopub.execute_input":"2025-10-14T13:48:03.926854Z","iopub.status.idle":"2025-10-14T13:48:04.721353Z","shell.execute_reply.started":"2025-10-14T13:48:03.926815Z","shell.execute_reply":"2025-10-14T13:48:04.720275Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Create Image data Generators\n\nThe dataset has already been divided into train and validation datasets, and each dataset includes normal and cancer image files. Thus, image data generators were easily created. ","metadata":{}},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(rescale = 1./255.,\n                                   zoom_range = 0.2,\n                                   horizontal_flip = True,\n                                   rotation_range = 10)\nval_datagen = ImageDataGenerator(rescale = 1./255.,)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:48:04.722684Z","iopub.execute_input":"2025-10-14T13:48:04.723191Z","iopub.status.idle":"2025-10-14T13:48:04.728269Z","shell.execute_reply.started":"2025-10-14T13:48:04.723161Z","shell.execute_reply":"2025-10-14T13:48:04.727129Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_path = '/kaggle/working/train'\nval_path = '/kaggle/working/val'\n\nIMG_HEIGHT = 512\nIMG_WIDTH = 512\nIMG_CHANNELS = 3\n\ntrain_generator = train_datagen.flow_from_directory(\n    train_path,\n    target_size = (512, 512),\n    batch_size = 4,\n    class_mode = 'binary'\n)\nvalidation_generator = val_datagen.flow_from_directory(\n        val_path,\n        target_size = (512, 512),\n        batch_size = 2,\n        class_mode = 'binary'\n)\n\ntrain_directory_iterator = train_generator\nvalidation_directory_iterator = validation_generator\n\ndef segmentation_generator(directory_iterator):\n    while True:\n        images, labels = next(directory_iterator)\n        masks = np.ones((labels.shape[0], IMG_HEIGHT, IMG_WIDTH, 1), dtype=np.float32)\n        masks *= labels[:, None, None, None]\n        yield images, masks\n\ntrain_steps_per_epoch = len(train_directory_iterator)\nval_steps_per_epoch = len(validation_directory_iterator)\n\ntrain_generator = segmentation_generator(train_directory_iterator)\nvalidation_generator = segmentation_generator(validation_directory_iterator)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:48:04.729551Z","iopub.execute_input":"2025-10-14T13:48:04.729855Z","iopub.status.idle":"2025-10-14T13:48:04.949173Z","shell.execute_reply.started":"2025-10-14T13:48:04.729829Z","shell.execute_reply":"2025-10-14T13:48:04.948363Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# See which folder includes cancer or normal images.\nprint(train_directory_iterator.class_indices)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:48:04.950221Z","iopub.execute_input":"2025-10-14T13:48:04.950487Z","iopub.status.idle":"2025-10-14T13:48:04.955145Z","shell.execute_reply.started":"2025-10-14T13:48:04.950462Z","shell.execute_reply":"2025-10-14T13:48:04.954203Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Define the Model (Transfer Learning)","metadata":{}},{"cell_type":"code","source":"def mean_iou(y_true, y_pred):\n    y_true = tf.cast(y_true, tf.float32)\n    y_pred = tf.cast(y_pred > 0.5, tf.float32)\n    intersection = tf.reduce_sum(y_true * y_pred, axis=[1, 2, 3])\n    union = tf.reduce_sum(y_true + y_pred, axis=[1, 2, 3]) - intersection\n    iou = tf.math.divide_no_nan(intersection, union)\n    return tf.reduce_mean(iou)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:48:04.956637Z","iopub.execute_input":"2025-10-14T13:48:04.956897Z","iopub.status.idle":"2025-10-14T13:48:04.964772Z","shell.execute_reply.started":"2025-10-14T13:48:04.956873Z","shell.execute_reply":"2025-10-14T13:48:04.963637Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Build U-Net model\ndef unet(input_shape=(IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS)):\n    inputs = Input(shape=input_shape)\n    s = Lambda(lambda x: x / 255.0)(inputs)\n\n    c1 = Conv2D(16, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(s)\n    c1 = Dropout(0.1)(c1)\n    c1 = Conv2D(16, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(c1)\n    p1 = MaxPooling2D((2, 2))(c1)\n\n    c2 = Conv2D(32, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(p1)\n    c2 = Dropout(0.1)(c2)\n    c2 = Conv2D(32, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(c2)\n    p2 = MaxPooling2D((2, 2))(c2)\n\n    c3 = Conv2D(64, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(p2)\n    c3 = Dropout(0.2)(c3)\n    c3 = Conv2D(64, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(c3)\n    p3 = MaxPooling2D((2, 2))(c3)\n\n    c4 = Conv2D(128, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(p3)\n    c4 = Dropout(0.2)(c4)\n    c4 = Conv2D(128, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(c4)\n    p4 = MaxPooling2D(pool_size=(2, 2))(c4)\n\n    c5 = Conv2D(256, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(p4)\n    c5 = Dropout(0.3)(c5)\n    c5 = Conv2D(256, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(c5)\n\n    u6 = Conv2DTranspose(128, (2, 2), strides=(2, 2), padding='same')(c5)\n    u6 = Concatenate()([u6, c4])\n    c6 = Conv2D(128, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(u6)\n    c6 = Dropout(0.2)(c6)\n    c6 = Conv2D(128, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(c6)\n\n    u7 = Conv2DTranspose(64, (2, 2), strides=(2, 2), padding='same')(c6)\n    u7 = Concatenate()([u7, c3])\n    c7 = Conv2D(64, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(u7)\n    c7 = Dropout(0.2)(c7)\n    c7 = Conv2D(64, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(c7)\n\n    u8 = Conv2DTranspose(32, (2, 2), strides=(2, 2), padding='same')(c7)\n    u8 = Concatenate()([u8, c2])\n    c8 = Conv2D(32, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(u8)\n    c8 = Dropout(0.1)(c8)\n    c8 = Conv2D(32, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(c8)\n\n    u9 = Conv2DTranspose(16, (2, 2), strides=(2, 2), padding='same')(c8)\n    u9 = Concatenate()([u9, c1])\n    c9 = Conv2D(16, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(u9)\n    c9 = Dropout(0.1)(c9)\n    c9 = Conv2D(16, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(c9)\n\n    outputs = Conv2D(1, (1, 1), activation='sigmoid')(c9)\n\n    model = Model(inputs=inputs, outputs=outputs)\n    model.compile(optimizer='adam', loss='binary_crossentropy', metrics=[mean_iou])\n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:48:04.97252Z","iopub.execute_input":"2025-10-14T13:48:04.973054Z","iopub.status.idle":"2025-10-14T13:48:04.989288Z","shell.execute_reply.started":"2025-10-14T13:48:04.973029Z","shell.execute_reply":"2025-10-14T13:48:04.988344Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T14:08:32.440339Z","iopub.execute_input":"2025-10-14T14:08:32.441094Z","iopub.status.idle":"2025-10-14T14:08:32.561967Z","shell.execute_reply.started":"2025-10-14T14:08:32.44106Z","shell.execute_reply":"2025-10-14T14:08:32.560968Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create U-Net base model with correct parameters\nmodel = unet(input_shape=(IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS))\n\nfor layer in model.layers:\n    layer.trainable = False","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:48:04.990692Z","iopub.execute_input":"2025-10-14T13:48:04.991141Z","iopub.status.idle":"2025-10-14T13:48:05.273932Z","shell.execute_reply.started":"2025-10-14T13:48:04.991103Z","shell.execute_reply":"2025-10-14T13:48:05.27316Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"    checkpoint = tf.keras.callbacks.ModelCheckpoint('model.h5', verbose=1, save_best_only=True)\ncallbacks = [\n    tf.keras.callbacks.EarlyStopping(patience=5, monitor='val_loss'),\n    tf.keras.callbacks.TensorBoard(log_dir='logs'),\n    checkpoint\n]\n\nhistory = model.fit(\n    x=train_generator,\n    validation_data=validation_generator,\n    steps_per_epoch=20,\n    validation_steps=val_steps_per_epoch,\n    epochs=20,\n    callbacks=callbacks\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T13:48:05.275057Z","iopub.execute_input":"2025-10-14T13:48:05.275358Z","iopub.status.idle":"2025-10-14T14:01:45.731718Z","shell.execute_reply.started":"2025-10-14T13:48:05.275329Z","shell.execute_reply":"2025-10-14T14:01:45.730811Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Model Metrics\n\nIoU and Los","metadata":{}},{"cell_type":"code","source":"mean_iou = history.history['mean_iou']\nval_mean_iou = history.history['val_mean_iou']\n\nloss = history.history['loss']\nval_loss = history.history['val_loss']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T14:01:45.733001Z","iopub.execute_input":"2025-10-14T14:01:45.733291Z","iopub.status.idle":"2025-10-14T14:01:45.738324Z","shell.execute_reply.started":"2025-10-14T14:01:45.733264Z","shell.execute_reply":"2025-10-14T14:01:45.737304Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize = (15,10))\n\nplt.subplot(2, 2, 1)\nplt.plot(mean_iou, label = \"Training IoU\")\nplt.plot(val_mean_iou, label = \"Validation IoU\")\nplt.ylim(0, 1)\nplt.legend(['Train', 'Validation'], loc = 'upper left')\nplt.title(\"Training vs Validation IoU\")\nplt.xlabel('epoch')\nplt.ylabel('IoU')\n\n\nplt.subplot(2, 2, 2)\nplt.plot(loss, label = \"Training Loss\")\nplt.plot(val_loss, label = \"Validation Loss\")\nplt.legend(['Train', 'Validation'], loc = 'upper left')\nplt.title(\"Training vs Validation Loss\")\nplt.xlabel('epoch')\nplt.ylabel('loss')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T14:01:45.739763Z","iopub.execute_input":"2025-10-14T14:01:45.740135Z","iopub.status.idle":"2025-10-14T14:01:46.153403Z","shell.execute_reply.started":"2025-10-14T14:01:45.740096Z","shell.execute_reply":"2025-10-14T14:01:46.152403Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Predictions","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.models import load_model\nmodel = load_model('/kaggle/working/model.h5', custom_objects={'mean_iou': mean_iou})","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T14:06:58.520716Z","iopub.execute_input":"2025-10-14T14:06:58.521711Z","iopub.status.idle":"2025-10-14T14:06:59.022937Z","shell.execute_reply.started":"2025-10-14T14:06:58.521675Z","shell.execute_reply":"2025-10-14T14:06:59.022076Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pred = model.predict(validation_generator)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-14T14:07:03.068632Z","iopub.execute_input":"2025-10-14T14:07:03.068974Z","iopub.status.idle":"2025-10-14T14:08:23.261157Z","shell.execute_reply.started":"2025-10-14T14:07:03.068944Z","shell.execute_reply":"2025-10-14T14:08:23.259549Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pred","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"y_pred = []\nfor prob in pred:\n    if prob >= 0.5:\n        y_pred.append(1)\n    else:\n        y_pred.append(0)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(y_pred)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pd.Series(y_pred).value_counts()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"y_true = validation_generator.classes","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(y_true)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Confusion Matrix\n\nConfusion matrix was created with the predicted and observed values. The matrix indicated almost correct predictions by the trained model except that there were two cases observed as false positive. False positive means that a case is actually negative but predicted as positive.","metadata":{}},{"cell_type":"code","source":"cm = confusion_matrix(y_true, y_pred)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Define the class names.\nclass_names = ['Cancer', 'Normal']\n\n# Create the heatmap with class names as tick labels.\nax = sns.heatmap(cm, annot = True, fmt = '.0f', cmap = \"Blues\", annot_kws = {\"size\": 16},\\\n           xticklabels = class_names, yticklabels = class_names)\n\n# Set the axis labels.\nax.set_xlabel(\"Prediction\")\nax.set_ylabel(\"Truth\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Classification Report\n\nClassification report describes precision, recall, and f1-score as to each value. Many people regard accuracy and f1-score as the most important indicator to evaluate an AI model. This may be correct, but is not necessarily correct in the clinical field. **It must be considered why AI can be useful for and accepted by healthcare professionals. They expect that AI may be able to reduce their workload.** What does it mean to reduce their workload by AI? One idea is to **exclude lots of negative cases by AI that healthcare professionals would not have to see in order that they would be able to concentrate on the remaining positive cases to be treated**. Thus, it is required that the AI should be able to **exclude negative cases without false negatives**, which are actually positive but predicted as negative. **Otherwise, they would have to re-check the negative cases in order not to miss actually positive cases.** They must absolutely avoid clinical negligence! Therefore, **if the AI model does not give rise to false negative cases, the model will be considerably acceptable in the healthcare field** regardless of the accuracy or f1-score.","metadata":{}},{"cell_type":"code","source":"print(classification_report(y_true, y_pred, target_names = ['Cancer' ,'Normal']))","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Analyze the Results\n\nIt is crucial in the medical field to analyze what kinds of cases were misclassified by the AI model, because medical misdiagnosis must be avoided as much as possible. Thus, it is necessary to identify false positive and false negative cases. Making a data frame and confusion table can visualize the results. As discussed above, false negative cases must be particularly avoided.","metadata":{}},{"cell_type":"code","source":"confusion = []\n\nfor i, j in zip(y_true, y_pred):\n  if i == 1 and j == 1:\n    confusion.append('TN')\n  elif i == 0 and j == 0:\n    confusion.append('TP')\n  elif i == 1 and j == 0:\n    confusion.append('FP')\n  else:\n    confusion.append('FN')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(confusion)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"confusion_table = pd.DataFrame(data = confusion, columns = [\"Results\"])\nconfusion_table","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"confusion_table = pd.DataFrame({'Predicton':y_pred,\n                                'Truth': y_true,\n                                'Results': confusion})\nconfusion_table","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"confusion_table.Results == 'FP'","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# list of false positive images\nFPs = confusion_table[confusion_table['Results'] == 'FP']\nFPs","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"FPs.index","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# list of false negative images\nFNs = confusion_table[confusion_table['Results'] == 'FN']\nFNs","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"FNs.index","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Misclassification Cases\n\nIt is important to pick up wrong cases judged by the AI and to analyze why the AI made wrong judgements for these images.","metadata":{}},{"cell_type":"code","source":"import glob\nval_images = glob.glob('/kaggle/working/val/*/*.png')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# False positive images\nfig, axes = plt.subplots(nrows = 2, ncols = 5, figsize = (15, 10), subplot_kw = {'xticks':[], 'yticks':[]})\nfor i, ax in zip(FPs.index, axes.flat):\n    img = cv2.imread(val_images[i])\n    ax.imshow(img)\n    ax.set_title(\"False Positive Case\")\nfig.tight_layout()    \n\nplt.show()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# False negative imgages\nfig, axes = plt.subplots(nrows = 2, ncols = 5, figsize = (15, 10), subplot_kw = {'xticks':[], 'yticks':[]})\nfor i, ax in zip(FNs.index, axes.flat):\n    img = cv2.imread(val_images[i])\n    ax.imshow(img)\n    ax.set_title(\"False Negative Case\")\nfig.tight_layout()    \n\nplt.show()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.summary()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# If val loss decreases for 3 epochs, stop training.\ncallback = tf.keras.callbacks.EarlyStopping(monitor = \"val_loss\", # Watch the val loss metric.\n                                            mode = \"min\",\n                                            patience = 4, \n                                            restore_best_weights = True)\n\nhistory = model.fit(train_generator, validation_data = validation_generator, steps_per_epoch = 20, epochs = 15, callbacks = [callback, checkpoint_callback])","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# This time we use validation data to calculate the final accuracy.\nfinal_accuracy = model.evaluate(validation_generator, verbose=0)[1]","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"final_accuracy","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Model Metrics","metadata":{}},{"cell_type":"markdown","source":"# Visualize Accuracy and Loss","metadata":{}},{"cell_type":"code","source":"accuracy = history.history.get('mean_iou', [])\nval_accuracy = history.history.get('val_mean_iou', [])\nloss = history.history.get('loss', [])\nval_loss = history.history.get('val_loss', [])\n\nplt.figure(figsize = (15,10))\n\nplt.subplot(2, 2, 1)\nplt.plot(accuracy, label = \"Training IoU\")\nplt.plot(val_accuracy, label = \"Validation IoU\")\nplt.ylim(0.0, 1)\nplt.legend(['Train', 'Validation'], loc = 'upper left')\nplt.title(\"Training vs Validation IoU\")\nplt.xlabel('epoch')\nplt.ylabel('IoU')\n\n\nplt.subplot(2, 2, 2)\nplt.plot(loss, label = \"Training Loss\")\nplt.plot(val_loss, label = \"Validation Loss\")\nplt.legend(['Train', 'Validation'], loc = 'upper left')\nplt.title(\"Training vs Validation Loss\")\nplt.xlabel('epoch')\nplt.ylabel('loss')\n\nplt.show()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Actually, Fine Tuning is worse than Transfer Learning, because the number of data images is small!","metadata":{}},{"cell_type":"markdown","source":"# Save the Model","metadata":{}},{"cell_type":"code","source":"model.save('mammography_pred_model_finetuning.h5')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Conclusion\n\nThis AI model may be useful for general physicians who occasionally see female patients for the screening purpose. Further improvement is required to prevent misdiagnosis and unnecessary treatment.","metadata":{}},{"cell_type":"markdown","source":"I am a medical doctor working on **artificial intelligence (AI) for medicine**. At present AI is also widely used in the medical field. Particularly, AI performs in the healthcare sector following tasks: **image classification, object detection, semantic segmentation, GANs, text classification, etc**. **If you are interested in AI for medicine, please see my other notebooks.**","metadata":{}}]}