{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport cv2\nimport random\n\nimport matplotlib.image as mpimg\nfrom PIL import Image\nImage.MAX_IMAGE_PIXELS = None\n\nimport glob\nimport tifffile as tiff \nfrom openslide import OpenSlide\nfrom collections import defaultdict\nfrom skimage.transform import resize\n\nBASE_PATH = \"../input/mayo-clinic-strip-ai\"","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-08-05T12:52:29.752451Z","iopub.execute_input":"2022-08-05T12:52:29.752919Z","iopub.status.idle":"2022-08-05T12:52:31.206826Z","shell.execute_reply.started":"2022-08-05T12:52:29.752809Z","shell.execute_reply":"2022-08-05T12:52:31.205421Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Loss Function**\n#### Loss function implementation notebook - https://www.kaggle.com/code/towhidultonmoy/implementing-custom-weighted-multi-class-log-loss","metadata":{}},{"cell_type":"code","source":"# weighted multi-class log loss\nepsilon = 1e-7 #Define epsilon so that the backpropagation will not result in NaN for 0 divisor case\ndef weighted_mc_log_loss(y_true, y_pred):\n    # Clipping the prediction value\n    y_pred_clipped = K.clip(y_pred, epsilon, 1-epsilon)  \n    #true labels weighted by weights and percent elements per class\n    y_true_weighted = (y_true * weights)/class_proportions\n    #multiply tensors element-wise and then sum\n    loss_num = (y_true_weighted * K.log(y_pred_clipped))\n    loss = -1*K.sum(loss_num)/K.sum(weights)\n    \n    return loss","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:52:31.209958Z","iopub.execute_input":"2022-08-05T12:52:31.2109Z","iopub.status.idle":"2022-08-05T12:52:31.21984Z","shell.execute_reply.started":"2022-08-05T12:52:31.210856Z","shell.execute_reply":"2022-08-05T12:52:31.218109Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Metadata Analysis**","metadata":{}},{"cell_type":"code","source":"train = pd.read_csv(os.path.join(BASE_PATH, \"train.csv\"))\ntest = pd.read_csv(os.path.join(BASE_PATH, \"test.csv\"))\nother = pd.read_csv(os.path.join(BASE_PATH, \"other.csv\"))","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:52:31.222204Z","iopub.execute_input":"2022-08-05T12:52:31.222858Z","iopub.status.idle":"2022-08-05T12:52:31.276164Z","shell.execute_reply.started":"2022-08-05T12:52:31.222814Z","shell.execute_reply":"2022-08-05T12:52:31.275068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:52:31.2796Z","iopub.execute_input":"2022-08-05T12:52:31.280234Z","iopub.status.idle":"2022-08-05T12:52:31.311773Z","shell.execute_reply.started":"2022-08-05T12:52:31.280164Z","shell.execute_reply":"2022-08-05T12:52:31.30962Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sns.countplot(data= train, x=\"label\") ","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:52:31.313266Z","iopub.execute_input":"2022-08-05T12:52:31.313743Z","iopub.status.idle":"2022-08-05T12:52:31.54247Z","shell.execute_reply.started":"2022-08-05T12:52:31.313705Z","shell.execute_reply":"2022-08-05T12:52:31.54119Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def pie_target(feat,df):\n    fig, ax = plt.subplots(3,2,figsize=(22,22))\n    for i in enumerate(feat):\n            fig.suptitle('Pie chart and Count Plot', size = 29)\n            ax[i[0],0].title.set_text(f'Pie of {i[1]}')\n            labels = list(df[i[1]].value_counts().index)\n            values = df[i[1]].value_counts()\n            \n            ax[i[0],0].pie(values,startangle=60, labels=labels,autopct='%1.0f%%', pctdistance=0.6)\n            ax[i[0],1].title.set_text(f'Count Plot for {i[1]}')\n            sns.countplot(x=i[1],data=df ,ax=ax[i[0],1])\n            ax[i[0],0].add_artist(plt.Circle((0,0),0.4,fc='white'))\n    fig.tight_layout()        \n    plt.show()\ncat_features=['center_id','image_num','label']\n\npie_target(cat_features,train)","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:52:31.544578Z","iopub.execute_input":"2022-08-05T12:52:31.545514Z","iopub.status.idle":"2022-08-05T12:52:32.789993Z","shell.execute_reply.started":"2022-08-05T12:52:31.545471Z","shell.execute_reply":"2022-08-05T12:52:32.788137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Image Loading and Analysis**","metadata":{}},{"cell_type":"code","source":"train_images = glob.glob(\"/kaggle/input/mayo-clinic-strip-ai/train/*\")\ntest_images = glob.glob(\"/kaggle/input/mayo-clinic-strip-ai/test/*\")\nother_images = glob.glob(\"/kaggle/input/mayo-clinic-strip-ai/other/*\")\nprint(f\"Number of images in a training set: {len(train_images)}\")\nprint(f\"Number of images in a testing set: {len(test_images)}\")\nprint(f\"Number of other: {len(other_images)}\")","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:52:32.791397Z","iopub.execute_input":"2022-08-05T12:52:32.792847Z","iopub.status.idle":"2022-08-05T12:52:32.934103Z","shell.execute_reply.started":"2022-08-05T12:52:32.792809Z","shell.execute_reply":"2022-08-05T12:52:32.932518Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_prop = defaultdict(list)\n\nfor i, path in enumerate(train_images):\n    img_path = train_images[i]\n    slide = OpenSlide(img_path)    \n    img_prop['image_id'].append(img_path[-12:-4])\n    img_prop['width'].append(slide.dimensions[0])\n    img_prop['height'].append(slide.dimensions[1])\n    img_prop['size'].append(round(os.path.getsize(img_path) / 1e6, 2))\n    img_prop['path'].append(img_path)\n\nimage_data = pd.DataFrame(img_prop)\nimage_data['img_aspect_ratio'] = image_data['width']/image_data['height']\nimage_data.sort_values(by='image_id', inplace=True)\nimage_data.reset_index(inplace=True, drop=True)\n\nimage_data = image_data.merge(train, on='image_id')\nimage_data.head()","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:52:32.936327Z","iopub.execute_input":"2022-08-05T12:52:32.936812Z","iopub.status.idle":"2022-08-05T12:52:54.668827Z","shell.execute_reply.started":"2022-08-05T12:52:32.936753Z","shell.execute_reply":"2022-08-05T12:52:54.667261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"CE_imgs = image_data.loc[image_data['label']=='CE','path']\nLAA_imgs = image_data.loc[image_data['label']=='LAA','path']","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:52:54.670765Z","iopub.execute_input":"2022-08-05T12:52:54.671134Z","iopub.status.idle":"2022-08-05T12:52:54.67963Z","shell.execute_reply.started":"2022-08-05T12:52:54.671105Z","shell.execute_reply":"2022-08-05T12:52:54.67798Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### **CE Data**","metadata":{}},{"cell_type":"code","source":"plt.style.use('default')\nfig, axes = plt.subplots(1,5, figsize=(16,16))\ntrain_images\nfor ax in axes.reshape(-1):\n    img_path = np.random.choice(CE_imgs)\n    img = Image.open(img_path)   \n    img.thumbnail((300,300), Image.Resampling.LANCZOS)\n    ax.imshow(img), ax.set_title(\"target: CE\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:52:54.687321Z","iopub.execute_input":"2022-08-05T12:52:54.687685Z","iopub.status.idle":"2022-08-05T12:54:12.081813Z","shell.execute_reply.started":"2022-08-05T12:52:54.687638Z","shell.execute_reply":"2022-08-05T12:54:12.077624Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### **LAA Data**","metadata":{}},{"cell_type":"code","source":"plt.style.use('default')\nfig, axes = plt.subplots(1,5, figsize=(16,16))\ntrain_images\nfor ax in axes.reshape(-1):\n    img_path = np.random.choice(LAA_imgs)\n    img = Image.open(img_path)   \n    img.thumbnail((300,300), Image.Resampling.LANCZOS)\n    ax.imshow(img), ax.set_title(\"target: LAA\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:54:12.083845Z","iopub.execute_input":"2022-08-05T12:54:12.084765Z","iopub.status.idle":"2022-08-05T12:56:21.38748Z","shell.execute_reply.started":"2022-08-05T12:54:12.084705Z","shell.execute_reply":"2022-08-05T12:56:21.385983Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Resizing the Image**","metadata":{}},{"cell_type":"code","source":"image_data","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:56:21.391988Z","iopub.execute_input":"2022-08-05T12:56:21.394374Z","iopub.status.idle":"2022-08-05T12:56:21.47794Z","shell.execute_reply.started":"2022-08-05T12:56:21.39433Z","shell.execute_reply":"2022-08-05T12:56:21.475983Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_path = train_images[256]\nimg_name = img_path[-12:-4]\nsel_img = image_data[image_data['image_id']==img_name]\nsel_img","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:56:21.486416Z","iopub.execute_input":"2022-08-05T12:56:21.489569Z","iopub.status.idle":"2022-08-05T12:56:21.542901Z","shell.execute_reply.started":"2022-08-05T12:56:21.489495Z","shell.execute_reply":"2022-08-05T12:56:21.540509Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img = mpimg.imread(img_path)   \nplt.imshow(img), plt.axis('off')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:56:21.550325Z","iopub.execute_input":"2022-08-05T12:56:21.552377Z","iopub.status.idle":"2022-08-05T12:57:37.584472Z","shell.execute_reply.started":"2022-08-05T12:56:21.552329Z","shell.execute_reply":"2022-08-05T12:57:37.583104Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)\nimage_resized = cv2.resize(img, (512,512))\n\nfig, ax = plt.subplots(1,2, figsize=(12,12))\nax[0].imshow(img)\nax[1].imshow(image_resized)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:57:37.586388Z","iopub.execute_input":"2022-08-05T12:57:37.586865Z","iopub.status.idle":"2022-08-05T12:58:03.155248Z","shell.execute_reply.started":"2022-08-05T12:57:37.586827Z","shell.execute_reply":"2022-08-05T12:58:03.153991Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_resized.shape","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:58:03.157316Z","iopub.execute_input":"2022-08-05T12:58:03.158073Z","iopub.status.idle":"2022-08-05T12:58:03.166983Z","shell.execute_reply.started":"2022-08-05T12:58:03.158017Z","shell.execute_reply":"2022-08-05T12:58:03.165334Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Tensorflow for Model Training**","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\n%matplotlib inline\nimport matplotlib.image as mpimg\nimport seaborn as sns\n\nfrom tensorflow import keras\nimport tensorflow as tf\nfrom tensorflow.keras import Model,Input\nfrom tensorflow.keras.layers import Dense,Flatten\n\nfrom tensorflow.keras.callbacks import EarlyStopping\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.callbacks import LearningRateScheduler,ReduceLROnPlateau\n\nfrom tensorflow.keras import layers\nfrom tensorflow.keras.applications import MobileNetV2,EfficientNetB0,EfficientNetB4,Xception\n\nimport warnings\nimport glob\nwarnings.filterwarnings(\"ignore\")","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:58:03.169012Z","iopub.execute_input":"2022-08-05T12:58:03.169953Z","iopub.status.idle":"2022-08-05T12:58:10.149566Z","shell.execute_reply.started":"2022-08-05T12:58:03.169911Z","shell.execute_reply":"2022-08-05T12:58:10.148023Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Data Preparation for training**","metadata":{}},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(rescale=1.0/255.0,validation_split=0.2,\n                                   rotation_range=5,shear_range=0.3,\n                                   zoom_range=0.3,width_shift_range=0.05,\n                                   height_shift_range=0.05,horizontal_flip=True,vertical_flip=True)\n\ntest_datagen = ImageDataGenerator(rescale=1.0/255.0)","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:58:10.151783Z","iopub.execute_input":"2022-08-05T12:58:10.152658Z","iopub.status.idle":"2022-08-05T12:58:10.166193Z","shell.execute_reply.started":"2022-08-05T12:58:10.152616Z","shell.execute_reply":"2022-08-05T12:58:10.163243Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data = train_datagen.flow_from_dataframe(image_data,directory=\"../input/mayo-clinic-strip-ai/train\",subset=\"training\",\n                                               x_col=\"path\",y_col=\"label\",target_size=(256, 256),batch_size=4)\n\nval_data = train_datagen.flow_from_dataframe(image_data,directory=\"../input/mayo-clinic-strip-ai/train\",subset=\"validation\",\n                                               x_col=\"path\",y_col=\"label\",target_size=(256, 256),batch_size=4)","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:58:10.168318Z","iopub.execute_input":"2022-08-05T12:58:10.169011Z","iopub.status.idle":"2022-08-05T12:58:10.66168Z","shell.execute_reply.started":"2022-08-05T12:58:10.168954Z","shell.execute_reply":"2022-08-05T12:58:10.660374Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels = ['CE', 'LAA'] \ntrain_data.class_indices.keys()","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:58:10.663396Z","iopub.execute_input":"2022-08-05T12:58:10.664438Z","iopub.status.idle":"2022-08-05T12:58:10.674847Z","shell.execute_reply.started":"2022-08-05T12:58:10.664396Z","shell.execute_reply":"2022-08-05T12:58:10.673338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for image_batch, labels_batch in train_data:\n    print(image_batch.shape)\n    print(labels_batch.shape)\n    break","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:58:10.67687Z","iopub.execute_input":"2022-08-05T12:58:10.677982Z","iopub.status.idle":"2022-08-05T12:58:39.537553Z","shell.execute_reply.started":"2022-08-05T12:58:10.677941Z","shell.execute_reply":"2022-08-05T12:58:39.53602Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(20, 20))\nfor j in range(4):\n    plt.subplot(2, 2, j+1)\n    plt.title(labels[labels_batch[j].tolist().index(1)])\n    plt.imshow(image_batch[j])","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:58:39.540119Z","iopub.execute_input":"2022-08-05T12:58:39.54105Z","iopub.status.idle":"2022-08-05T12:58:40.630706Z","shell.execute_reply.started":"2022-08-05T12:58:39.541009Z","shell.execute_reply":"2022-08-05T12:58:40.629215Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Efficient Net Model**","metadata":{}},{"cell_type":"code","source":"def build_model():\n    effnet = tf.keras.applications.EfficientNetB4(weights=\"imagenet\", include_top=False, input_tensor=Input(shape=(256, 256, 3)))\n\n    effnet.trainable = False\n\n    flatten = effnet.output\n    flatten = Flatten()(flatten)\n\n    dense_out = Dense(128, activation=\"relu\")(flatten)\n    dense_out = Dense(64, activation=\"relu\")(dense_out)\n    dense_out = Dense(32, activation=\"relu\")(dense_out)\n    final_softmax = Dense(2, activation=\"softmax\")(dense_out)\n\n    model = Model(inputs=effnet.input, outputs=final_softmax)\n    \n    return model","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:58:40.632656Z","iopub.execute_input":"2022-08-05T12:58:40.63374Z","iopub.status.idle":"2022-08-05T12:58:40.645433Z","shell.execute_reply.started":"2022-08-05T12:58:40.633702Z","shell.execute_reply":"2022-08-05T12:58:40.643744Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = build_model()","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:58:40.647288Z","iopub.execute_input":"2022-08-05T12:58:40.648964Z","iopub.status.idle":"2022-08-05T12:58:52.000238Z","shell.execute_reply.started":"2022-08-05T12:58:40.648863Z","shell.execute_reply":"2022-08-05T12:58:51.998694Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## **Compile and Callbacks**","metadata":{}},{"cell_type":"code","source":"model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), loss='categorical_crossentropy', metrics=['accuracy'])\n\nsave_best = tf.keras.callbacks.ModelCheckpoint(\"Model.h5\", monitor='val_accuracy', save_best_only=True, verbose=1)","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:58:52.001894Z","iopub.execute_input":"2022-08-05T12:58:52.002418Z","iopub.status.idle":"2022-08-05T12:58:52.029638Z","shell.execute_reply.started":"2022-08-05T12:58:52.002345Z","shell.execute_reply":"2022-08-05T12:58:52.028278Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## **Model Training**","metadata":{}},{"cell_type":"code","source":"model.fit(train_data, validation_data=val_data, epochs=30, callbacks=[save_best])","metadata":{"execution":{"iopub.status.busy":"2022-08-05T12:58:52.033771Z","iopub.execute_input":"2022-08-05T12:58:52.034163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ***Model Tuning in Process...... !!***","metadata":{}}]}