{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\n# import numpy as np # linear algebra\n# import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\n# import os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-12-12T08:56:55.589794Z","iopub.execute_input":"2021-12-12T08:56:55.590797Z","iopub.status.idle":"2021-12-12T08:56:55.599009Z","shell.execute_reply.started":"2021-12-12T08:56:55.590654Z","shell.execute_reply":"2021-12-12T08:56:55.597690Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# IMPORTING THE NECESSARY LIBRARIES\n\nimport pandas as pd\nimport numpy as np\nimport itertools\nimport os\nimport sys\nfrom prettytable import PrettyTable\nimport pickle\nfrom random import shuffle\nfrom sklearn.model_selection import train_test_split\nimport multiprocessing\nfrom multiprocessing.pool import ThreadPool\nfrom tqdm import tqdm_notebook\n\nfrom sklearn.metrics import confusion_matrix, cohen_kappa_score,accuracy_score\nfrom sklearn.preprocessing import MultiLabelBinarizer\n\nimport tensorflow.keras as keras\nfrom keras import applications\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras import optimizers,Model,Sequential\nfrom keras.layers import Input,GlobalAveragePooling2D,Dropout,Dense,Activation,BatchNormalization,GlobalMaxPooling2D,concatenate,Flatten\nfrom keras.callbacks import EarlyStopping,ReduceLROnPlateau,Callback\nfrom keras.initializers import random_normal\nfrom keras.models import load_model\nfrom keras.losses import binary_crossentropy,categorical_crossentropy,mean_squared_error\nfrom keras import backend as K\n\nimport seaborn as sns\n%matplotlib inline\nimport matplotlib.pyplot as plt\nplt.rcParams[\"axes.grid\"] = False\n\n\nfrom PIL import Image\nimport cv2\nimport tensorflow as tf\n\n\nprint(multiprocessing.cpu_count(),\" CPU cores\")","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:56:55.600710Z","iopub.execute_input":"2021-12-12T08:56:55.601493Z","iopub.status.idle":"2021-12-12T08:57:02.082077Z","shell.execute_reply.started":"2021-12-12T08:56:55.601452Z","shell.execute_reply":"2021-12-12T08:57:02.081093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# CHANGING TO DIRECTORY\n\nimport os\n\nos.chdir('../input/aptos2019-blindness-detection')\nprint(\"We are currently in the folder of \",os.getcwd())","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:02.084770Z","iopub.execute_input":"2021-12-12T08:57:02.085286Z","iopub.status.idle":"2021-12-12T08:57:02.092120Z","shell.execute_reply.started":"2021-12-12T08:57:02.085243Z","shell.execute_reply":"2021-12-12T08:57:02.090867Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# LOADING DATASETS\n\ndef load_data():\n    train = pd.read_csv('train.csv')\n    test = pd.read_csv('test.csv')\n    \n    train_dir = os.path.join('./','train_images/')\n    test_dir = os.path.join('./','test_images/')\n    \n    train['file_path'] = train['id_code'].map(lambda x: os.path.join(train_dir,'{}.png'.format(x)))\n    test['file_path'] = test['id_code'].map(lambda x: os.path.join(test_dir,'{}.png'.format(x)))\n    \n    train['file_name'] = train[\"id_code\"].apply(lambda x: x + \".png\")\n    test['file_name'] = test[\"id_code\"].apply(lambda x: x + \".png\")\n    \n    train['diagnosis'] = train['diagnosis'].astype(str)\n    \n    return train,test","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:02.094687Z","iopub.execute_input":"2021-12-12T08:57:02.095640Z","iopub.status.idle":"2021-12-12T08:57:02.106582Z","shell.execute_reply.started":"2021-12-12T08:57:02.095596Z","shell.execute_reply":"2021-12-12T08:57:02.105501Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# DISPLAYING THE SIZE OF THE TRAIN AND TEST SETS BEFORE PREPROCESSING\n\ndf_train,df_test = load_data()\nprint(df_train.shape,df_test.shape,'\\n')","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:02.107948Z","iopub.execute_input":"2021-12-12T08:57:02.110914Z","iopub.status.idle":"2021-12-12T08:57:02.185380Z","shell.execute_reply.started":"2021-12-12T08:57:02.110867Z","shell.execute_reply":"2021-12-12T08:57:02.184131Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# DISPLAYING THE TRAIN DATASET\n\ndf_train.head(5)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:02.187122Z","iopub.execute_input":"2021-12-12T08:57:02.187587Z","iopub.status.idle":"2021-12-12T08:57:02.209982Z","shell.execute_reply.started":"2021-12-12T08:57:02.187546Z","shell.execute_reply":"2021-12-12T08:57:02.208845Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# DISPLAYING THE TEST DATASET\n\ndf_test.head(5)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:02.211414Z","iopub.execute_input":"2021-12-12T08:57:02.212119Z","iopub.status.idle":"2021-12-12T08:57:02.227002Z","shell.execute_reply.started":"2021-12-12T08:57:02.212079Z","shell.execute_reply":"2021-12-12T08:57:02.225806Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# PLOTTING THE DISTRIBUTION OF CLASSES\n\ndef distribute_classes(df):\n    df_grouping = pd.DataFrame(df.groupby('diagnosis').agg('size').reset_index())\n    df_grouping.columns = ['diagnosis','count']\n\n    sns.set(rc={'figure.figsize':(10,5)}, style = 'whitegrid')\n    sns.barplot(x = 'diagnosis',y='count',data = df_grouping,palette = \"magma\")\n    plt.title('Overall Class Distribution')\n    plt.show()\ndistribute_classes(df_train)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:02.228568Z","iopub.execute_input":"2021-12-12T08:57:02.229065Z","iopub.status.idle":"2021-12-12T08:57:02.468552Z","shell.execute_reply.started":"2021-12-12T08:57:02.228993Z","shell.execute_reply":"2021-12-12T08:57:02.467376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# DECLARING THE IMAGE SIZE FOR PREPROCESSING \n\nIMG_SIZE = 256","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:02.472557Z","iopub.execute_input":"2021-12-12T08:57:02.472889Z","iopub.status.idle":"2021-12-12T08:57:02.477764Z","shell.execute_reply.started":"2021-12-12T08:57:02.472859Z","shell.execute_reply":"2021-12-12T08:57:02.476235Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def convert_to_gray(img):\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n    img = cv2.resize(img, (IMG_SIZE,IMG_SIZE))\n    return img\n  \ndef display_imgs(df,pts_per_class,color_scale):\n    df = df.groupby('diagnosis',group_keys = False).apply(lambda df: df.sample(pts_per_class))\n    df = df.reset_index(drop = True)\n    \n    plt.rcParams[\"axes.grid\"] = False\n    for pt in range(pts_per_class):\n        f, axarr = plt.subplots(1,5,figsize = (15,15))\n        axarr[0].set_ylabel(\"Sample Data Points\")\n        \n        df_temp = df[df.index.isin([pt + (pts_per_class*0),pt + (pts_per_class*1), pt + (pts_per_class*2),pt + (pts_per_class*3),pt + (pts_per_class*4)])]\n        for i in range(5):\n            if color_scale == 'gray':\n                img = convert_to_gray(cv2.imread(df_temp.file_path.iloc[i]))\n                axarr[i].imshow(img,cmap = color_scale)\n            else:\n                axarr[i].imshow(Image.open(df_temp.file_path.iloc[i]).resize((IMG_SIZE,IMG_SIZE)))\n            axarr[i].set_xlabel('Class '+str(df_temp.diagnosis.iloc[i]))\n\n        plt.show()\n\ndisplay_imgs(df_train,3,color_scale = None)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:02.481133Z","iopub.execute_input":"2021-12-12T08:57:02.481822Z","iopub.status.idle":"2021-12-12T08:57:08.819049Z","shell.execute_reply.started":"2021-12-12T08:57:02.481763Z","shell.execute_reply":"2021-12-12T08:57:08.817960Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# APPLYING GAUSSIAN BLUR TO THE IMAGES TO REMOVE IRREGULARITIES\n\nrn = np.random.randint(low = 0,high = len(df_train) - 1)\n\nimg = cv2.imread(df_train.file_path.iloc[rn])\nimg = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\nimg = cv2.resize(img, (IMG_SIZE,IMG_SIZE))\n\nimg_t = cv2.addWeighted(img,4, cv2.GaussianBlur(img , (0,0) , 30) ,-4 ,128)\n\nf, axarr = plt.subplots(1,2,figsize = (11,11))\naxarr[0].imshow(img)\naxarr[1].imshow(img_t)\nplt.title('Images after Gaussian Blur...')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:08.820686Z","iopub.execute_input":"2021-12-12T08:57:08.821356Z","iopub.status.idle":"2021-12-12T08:57:09.497051Z","shell.execute_reply.started":"2021-12-12T08:57:08.821314Z","shell.execute_reply":"2021-12-12T08:57:09.496080Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# APPLYING GAUSSIAN BLUR AND CIRCLE CROP TO THE IMAGES TO BRING ALL THE IMAGES TO ONE FORM\n\ndef crop_image_from_gray(img,tol=7):\n    if img.ndim ==2:\n        mask = img>tol\n        return img[np.ix_(mask.any(1),mask.any(0))]\n    elif img.ndim==3:\n        gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)\n        mask = gray_img>tol\n        \n        check_shape = img[:,:,0][np.ix_(mask.any(1),mask.any(0))].shape[0]\n        if (check_shape == 0): \n            return img \n        else:\n            img1=img[:,:,0][np.ix_(mask.any(1),mask.any(0))]\n            img2=img[:,:,1][np.ix_(mask.any(1),mask.any(0))]\n            img3=img[:,:,2][np.ix_(mask.any(1),mask.any(0))]\n            print(img1.shape,img2.shape,img3.shape)\n            img = np.stack([img1,img2,img3],axis=-1)\n            print(img.shape)\n        return img\n    \n    \ndef circular_crop(img, sigmaX):       \n    img = crop_image_from_gray(img)    \n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    \n    h, w, d = img.shape    \n    \n    x = int(w/2)\n    y = int(h/2)\n    r = np.amin((x,y))\n    \n    circle_img = np.zeros((h, w), np.uint8)\n    cv2.circle(circle_img, (x,y), int(r), 1, thickness=-1)\n    img = cv2.bitwise_and(img, img, mask=circle_img)\n    img = crop_image_from_gray(img)\n    img=cv2.addWeighted(img,4, cv2.GaussianBlur( img , (0,0) , sigmaX) ,-4 ,128)\n    return img","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:09.498941Z","iopub.execute_input":"2021-12-12T08:57:09.499616Z","iopub.status.idle":"2021-12-12T08:57:09.517660Z","shell.execute_reply.started":"2021-12-12T08:57:09.499567Z","shell.execute_reply":"2021-12-12T08:57:09.516390Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"rn = np.random.randint(low = 0,high = len(df_train) - 1)\nimg = cv2.imread(df_train.file_path.iloc[rn])\nimg_t = circular_crop(img,sigmaX = 30)\nf, axarr = plt.subplots(1,2,figsize = (11,11))\naxarr[0].imshow(cv2.resize(cv2.cvtColor(img, cv2.COLOR_BGR2RGB),(IMG_SIZE,IMG_SIZE)))\naxarr[1].imshow(img_t)\nplt.title('Images after applying Circular Crop and Gaussian Blur...')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:09.519609Z","iopub.execute_input":"2021-12-12T08:57:09.520667Z","iopub.status.idle":"2021-12-12T08:57:10.619625Z","shell.execute_reply.started":"2021-12-12T08:57:09.520621Z","shell.execute_reply":"2021-12-12T08:57:10.617824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def visualize_imgs(df,pts_per_class,sigmaX):\n    df = df.groupby('diagnosis',group_keys = False).apply(lambda df: df.sample(pts_per_class))\n    df = df.reset_index(drop = True)\n    \n    plt.rcParams[\"axes.grid\"] = False\n    for pt in range(pts_per_class):\n        f, axarr = plt.subplots(1,5,figsize = (15,15))\n        axarr[0].set_ylabel(\"Sample Data Points\")\n        \n        df_temp = df[df.index.isin([pt + (pts_per_class*0),pt + (pts_per_class*1), pt + (pts_per_class*2),pt + (pts_per_class*3),pt + (pts_per_class*4)])]\n        for i in range(5):\n            img = cv2.imread(df_temp.file_path.iloc[i])\n            img = circular_crop(img,sigmaX)\n            axarr[i].imshow(img)\n            axarr[i].set_xlabel('Class '+str(df_temp.diagnosis.iloc[i]))\n\n        plt.show()\n\nvisualize_imgs(df_train,3,sigmaX = 30)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:10.621373Z","iopub.execute_input":"2021-12-12T08:57:10.622210Z","iopub.status.idle":"2021-12-12T08:57:33.372718Z","shell.execute_reply.started":"2021-12-12T08:57:10.622168Z","shell.execute_reply":"2021-12-12T08:57:33.371478Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# PERFORMING DATA AUGMENTATION\n\ndef generate_augmentations(lim):\n    datagen = ImageDataGenerator(featurewise_center=True,\n                                 featurewise_std_normalization=True,\n                                 rotation_range=20,\n                                 #width_shift_range=0.2,\n                                 #height_shift_range=0.2,\n                                 horizontal_flip=True)\n    img = cv2.imread(df_train.file_path.iloc[np.random.randint(low = 0,high = len(df_train) - 1)])\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    img = cv2.resize(img, (256,256))\n    plt.imshow(img)\n    plt.title('ORIGINAL IMAGE')\n    plt.show()\n    \n    img_arr = img.reshape((1,) + img.shape)\n    \n    i = 0\n    for img_iterator in datagen.flow(x = img_arr,batch_size = 1):\n        i = i + 1\n        if i > lim:\n            break\n        plt.imshow((img_iterator.reshape(img_arr[0].shape)).astype(np.uint8))\n        plt.title('IMAGE AUGMENTATION ' + str(i))\n        plt.show() \n\ngenerate_augmentations(3)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:33.374674Z","iopub.execute_input":"2021-12-12T08:57:33.375157Z","iopub.status.idle":"2021-12-12T08:57:34.490922Z","shell.execute_reply.started":"2021-12-12T08:57:33.375108Z","shell.execute_reply":"2021-12-12T08:57:34.489865Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# PERFORMING TESTING ON TRAINING SET\n\ndf_train_train,df_train_valid = train_test_split(df_train,test_size = 0.2)\nprint(df_train_train.shape,df_train_valid.shape)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:34.492605Z","iopub.execute_input":"2021-12-12T08:57:34.493076Z","iopub.status.idle":"2021-12-12T08:57:34.504601Z","shell.execute_reply.started":"2021-12-12T08:57:34.493031Z","shell.execute_reply":"2021-12-12T08:57:34.503293Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# DISPLAYING THE TRAIN DATASET FOR PROCESSING\n\ndf_train_train.head(5)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:34.506409Z","iopub.execute_input":"2021-12-12T08:57:34.507174Z","iopub.status.idle":"2021-12-12T08:57:34.521709Z","shell.execute_reply.started":"2021-12-12T08:57:34.507114Z","shell.execute_reply":"2021-12-12T08:57:34.520122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# DISPLAYING THE TEST DATASET FOR PROCESSING\n\ndf_train_valid.head(5)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:34.523908Z","iopub.execute_input":"2021-12-12T08:57:34.524503Z","iopub.status.idle":"2021-12-12T08:57:34.545265Z","shell.execute_reply.started":"2021-12-12T08:57:34.524460Z","shell.execute_reply":"2021-12-12T08:57:34.543313Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# CONSIDERING VALID_DATA TO BE THE TEST_DATA\n\ndf_train_test = df_train_valid\nprint(df_train_train.shape,df_train_valid.shape)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:34.546993Z","iopub.execute_input":"2021-12-12T08:57:34.547745Z","iopub.status.idle":"2021-12-12T08:57:34.554855Z","shell.execute_reply.started":"2021-12-12T08:57:34.547702Z","shell.execute_reply":"2021-12-12T08:57:34.553398Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# CREATING FILES TO UPLOAD PROCESSED DATA\n\nfile = open('/kaggle/working/df_train_train', 'wb')\npickle.dump(df_train_train, file)\nfile.close()\n\nfile = open('/kaggle/working/df_train_test', 'wb')\npickle.dump(df_train_test, file)\nfile.close()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:34.556875Z","iopub.execute_input":"2021-12-12T08:57:34.557776Z","iopub.status.idle":"2021-12-12T08:57:34.570294Z","shell.execute_reply.started":"2021-12-12T08:57:34.557729Z","shell.execute_reply":"2021-12-12T08:57:34.569233Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"file = open('/kaggle/working/df_train_train', 'rb')\ndf_train_train = pickle.load(file)\nfile.close()\n\nfile = open('/kaggle/working/df_train_test', 'rb')\ndf_train_test = pickle.load(file)\nfile.close()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:34.572936Z","iopub.execute_input":"2021-12-12T08:57:34.573647Z","iopub.status.idle":"2021-12-12T08:57:34.585622Z","shell.execute_reply.started":"2021-12-12T08:57:34.573602Z","shell.execute_reply":"2021-12-12T08:57:34.584489Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(df_train_train.shape,df_train_test.shape)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:34.587684Z","iopub.execute_input":"2021-12-12T08:57:34.588150Z","iopub.status.idle":"2021-12-12T08:57:34.803596Z","shell.execute_reply.started":"2021-12-12T08:57:34.588106Z","shell.execute_reply":"2021-12-12T08:57:34.802323Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# WE USE IMAGES OF SIZE 512 \n\nIMG_SIZE  = 512","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:34.805263Z","iopub.execute_input":"2021-12-12T08:57:34.805922Z","iopub.status.idle":"2021-12-12T08:57:34.814006Z","shell.execute_reply.started":"2021-12-12T08:57:34.805875Z","shell.execute_reply":"2021-12-12T08:57:34.812920Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# CREATING NEW DIRECTORIES FOR STORING FILES\n\nos.mkdir('/kaggle/working/train_images_resized_preprocessed')\nos.mkdir('/kaggle/working/test_images_resized_preprocessed')","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:34.815771Z","iopub.execute_input":"2021-12-12T08:57:34.816291Z","iopub.status.idle":"2021-12-12T08:57:34.824965Z","shell.execute_reply.started":"2021-12-12T08:57:34.816246Z","shell.execute_reply":"2021-12-12T08:57:34.823730Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def crop_image_from_gray(img,tol=7):\n    if img.ndim ==2:\n        mask = img>tol\n        return img[np.ix_(mask.any(1),mask.any(0))]\n    elif img.ndim==3:\n        gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)\n        mask = gray_img>tol\n        \n        check_shape = img[:,:,0][np.ix_(mask.any(1),mask.any(0))].shape[0]\n        if (check_shape == 0): # image is too dark so that we crop out everything,\n            return img # return original image\n        else:\n            img1=img[:,:,0][np.ix_(mask.any(1),mask.any(0))]\n            img2=img[:,:,1][np.ix_(mask.any(1),mask.any(0))]\n            img3=img[:,:,2][np.ix_(mask.any(1),mask.any(0))]\n    #         print(img1.shape,img2.shape,img3.shape)\n            img = np.stack([img1,img2,img3],axis=-1)\n    #         print(img.shape)\n        return img\n\ndef circle_crop(img, sigmaX = 30):   \n    \"\"\"\n    Create circular crop around image centre    \n    \"\"\"    \n    img = crop_image_from_gray(img)    \n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    \n    height, width, depth = img.shape    \n    \n    x = int(width/2)\n    y = int(height/2)\n    r = np.amin((x,y))\n    \n    circle_img = np.zeros((height, width), np.uint8)\n    cv2.circle(circle_img, (x,y), int(r), 1, thickness=-1)\n    img = cv2.bitwise_and(img, img, mask=circle_img)\n    img = crop_image_from_gray(img)\n    img=cv2.addWeighted(img,4, cv2.GaussianBlur( img , (0,0) , sigmaX) ,-4 ,128)\n    return img \n\ndef generate_augmentations(img, lim=3):\n    datagen = ImageDataGenerator(featurewise_center=True,\n                                 featurewise_std_normalization=True,\n                                 rotation_range=20,\n                                 #width_shift_range=0.2,\n                                 #height_shift_range=0.2,\n                                 horizontal_flip=True)\n    img = cv2.imread(df_train.file_path.iloc[np.random.randint(low = 0,high = len(df_train) - 1)])\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    img = cv2.resize(img, (256,256))\n    img_arr = img.reshape((1,) + img.shape)\n    \n    i = 0\n    imgs = []\n    for img_iterator in datagen.flow(x = img_arr,batch_size = 1):\n        i = i + 1\n        if i > lim:\n            break\n        imgs.append(((img_iterator.reshape(img_arr[0].shape)).astype(np.uint8)))\n    return imgs \n\ndef preprocess_image(file):\n    input_filepath = os.path.join('./','train_images/','{}.png'.format(file))\n    output_filepath = os.path.join('/kaggle/working/','train_images_resized_preprocessed/','{}.png'.format(file))\n    \n    img = cv2.imread(input_filepath)\n    img = circle_crop(img) \n    imgs = generate_augmentations(img)\n    for i in range(3):\n        cv2.imwrite(output_filepath, cv2.resize(imgs[i], (IMG_SIZE,IMG_SIZE)))\n    cv2.imwrite(output_filepath, cv2.resize(img, (IMG_SIZE,IMG_SIZE)))\n    \ndef preprocess_image1(file):\n    input_filepath = os.path.join('./','train_images/','{}.png'.format(file))\n    output_filepath = os.path.join('/kaggle/working/','test_images_resized_preprocessed/','{}.png'.format(file))\n    \n    img = cv2.imread(input_filepath)\n    img = circle_crop(img) \n    imgs = generate_augmentations(img)\n    for i in range(3):\n        cv2.imwrite(output_filepath, cv2.resize(imgs[i], (IMG_SIZE,IMG_SIZE)))","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:34.826737Z","iopub.execute_input":"2021-12-12T08:57:34.827523Z","iopub.status.idle":"2021-12-12T08:57:34.853629Z","shell.execute_reply.started":"2021-12-12T08:57:34.827477Z","shell.execute_reply":"2021-12-12T08:57:34.852469Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''This Function uses Multi processing for faster saving of images into folder'''\n\ndef multiprocess_image_processor(process:int, imgs:list):\n    \"\"\"\n    Inputs:\n        process: (int) number of process to run\n        imgs:(list) list of images\n    \"\"\"\n    print(f'MESSAGE: Running {process} process')\n    results = ThreadPool(process).map(preprocess_image, imgs)\n    return results\ndef multiprocess_image_processor1(process:int, imgs:list):\n    \"\"\"\n    Inputs:\n        process: (int) number of process to run\n        imgs:(list) list of images\n    \"\"\"\n    print(f'MESSAGE: Running {process} process')\n    results = ThreadPool(process).map(preprocess_image1, imgs)\n#     return results","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:34.856177Z","iopub.execute_input":"2021-12-12T08:57:34.856944Z","iopub.status.idle":"2021-12-12T08:57:34.868898Z","shell.execute_reply.started":"2021-12-12T08:57:34.856898Z","shell.execute_reply":"2021-12-12T08:57:34.867838Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Use 6 cores\nmultiprocess_image_processor(4, list(df_train_train.id_code.values))\nmultiprocess_image_processor1(4, list(df_train_test.id_code.values))","metadata":{"execution":{"iopub.status.busy":"2021-12-12T08:57:34.875497Z","iopub.execute_input":"2021-12-12T08:57:34.875851Z","iopub.status.idle":"2021-12-12T10:02:53.684425Z","shell.execute_reply.started":"2021-12-12T08:57:34.875805Z","shell.execute_reply":"2021-12-12T10:02:53.683111Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"FACTOR = 4\nBATCH_SIZE = 8 * FACTOR\nIMG_SIZE = 512\nEPOCHS = 20\nLEARNING_RATE = 1e-4 * FACTOR\nWARMUP_LEARNING_RATE = 1e-3 * FACTOR\nHEIGHT = 320\nWIDTH = 320\nCANAL = 3\nN_CLASSES = df_train_train['diagnosis'].nunique()\nES_PATIENCE = 5\nRLROP_PATIENCE = 3\nDECAY_DROP = 0.5\nWARMUP_EPOCHS = 5\n\n\nLR_WARMUP_EPOCHS_1st = 2\nLR_WARMUP_EPOCHS_2nd = 5\nSTEP_SIZE = len(df_train_train) // BATCH_SIZE\nWARMUP_STEPS_1st = LR_WARMUP_EPOCHS_1st * STEP_SIZE\nWARMUP_STEPS_2nd = LR_WARMUP_EPOCHS_2nd * STEP_SIZE\nTOTAL_STEPS_1st = WARMUP_EPOCHS * STEP_SIZE\nTOTAL_STEPS_2nd = EPOCHS * STEP_SIZE","metadata":{"execution":{"iopub.status.busy":"2021-12-12T12:05:41.252343Z","iopub.execute_input":"2021-12-12T12:05:41.252831Z","iopub.status.idle":"2021-12-12T12:05:41.263338Z","shell.execute_reply.started":"2021-12-12T12:05:41.252761Z","shell.execute_reply":"2021-12-12T12:05:41.261907Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# CONVERTING MULTIPLE LABELS TO BINARY MATRIX\n\ndef multiple_outputs(generator,dataframe, image_dir, batch_size, height,width, subset):\n    gen = generator.flow_from_dataframe(\n        dataframe = dataframe,\n        x_col = \"file_name\",\n        y_col = \"diagnosis\",\n        directory = image_dir,\n        target_size=(height, width),\n        batch_size=batch_size,\n        class_mode='categorical',\n        subset=subset)\n    \n    mlb = MultiLabelBinarizer(classes = range(N_CLASSES))\n    \n    while True:\n        gnext = gen.next()\n        yield gnext[0], [np.argmax(gnext[1],axis = -1),gnext[1],mlb.fit_transform([list(range(x+1)) for x in np.argmax(gnext[1],axis = -1)])]","metadata":{"execution":{"iopub.status.busy":"2021-12-12T12:05:43.237934Z","iopub.execute_input":"2021-12-12T12:05:43.238449Z","iopub.status.idle":"2021-12-12T12:05:43.247471Z","shell.execute_reply.started":"2021-12-12T12:05:43.238417Z","shell.execute_reply":"2021-12-12T12:05:43.245897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_datagen=ImageDataGenerator(rescale=1./255, rotation_range=360,brightness_range=[0.5, 1.5],\n                                     zoom_range=[1, 1.2],zca_whitening=True,horizontal_flip=True,\n                                     vertical_flip=True,fill_mode='constant',cval=0.,validation_split = 0.0)\n\ntrain_generator = multiple_outputs(generator = train_datagen,dataframe = df_train_train,\n                                   image_dir=\"/kaggle/working/train_images_resized_preprocessed/\",\n                                   batch_size=BATCH_SIZE,height = HEIGHT,width = WIDTH,\n                                   subset='training')\n     \nvalid_generator = multiple_outputs(generator = train_datagen,dataframe = df_train_test,\n                                   image_dir=\"/kaggle/working/test_images_resized_preprocessed/\",\n                                   batch_size=BATCH_SIZE,height = HEIGHT,width = WIDTH,\n                                   subset='validation')","metadata":{"execution":{"iopub.status.busy":"2021-12-12T12:05:44.794948Z","iopub.execute_input":"2021-12-12T12:05:44.795584Z","iopub.status.idle":"2021-12-12T12:05:44.803836Z","shell.execute_reply.started":"2021-12-12T12:05:44.795543Z","shell.execute_reply":"2021-12-12T12:05:44.802219Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# APPLYING MUTI-TASK LEARNING USING ResNet50\n\ninput_tensor = Input(shape=(HEIGHT, WIDTH, CANAL))\nbase_model = applications.ResNet50(weights=None, include_top=False,input_tensor=input_tensor)\nbase_model.load_weights('/kaggle/input/resnet50/resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5')\n\n\nx1 = GlobalAveragePooling2D()(base_model.output)\nx1 = BatchNormalization()(x1)\n\nx2 = GlobalMaxPooling2D()(base_model.output)\nx2 = BatchNormalization()(x2)\n\nx = concatenate([x1,x2])\n\n# Regression - 1\nxr = Dense(2048, activation='relu')(x)\nxr = Dropout(0.5)(xr)\nxr = Dense(1,activation = 'linear',name = 'regression_output')(xr)\n\n# Classification - 2\nxc = Dense(2048, activation='relu')(x)\nxc = Dropout(0.5)(xc)\nxc = Dense(N_CLASSES,activation = 'softmax',name = 'classification_output')(xc)\n\n# Ordinal Regression - 3\nxo = Dense(2048, activation='relu')(x)\nxo = Dropout(0.5)(xo)\nxo = Dense(N_CLASSES,activation = 'softmax',name = 'ordinal_regression_output')(xo)\n\nmodel = Model(inputs = [input_tensor], outputs = [xr,xc,xo])","metadata":{"execution":{"iopub.status.busy":"2021-12-12T12:05:48.518193Z","iopub.execute_input":"2021-12-12T12:05:48.518673Z","iopub.status.idle":"2021-12-12T12:05:53.373452Z","shell.execute_reply.started":"2021-12-12T12:05:48.518627Z","shell.execute_reply":"2021-12-12T12:05:53.372103Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for layer in model.layers:\n    layer.trainable = True\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T12:05:53.375385Z","iopub.execute_input":"2021-12-12T12:05:53.375847Z","iopub.status.idle":"2021-12-12T12:05:53.528907Z","shell.execute_reply.started":"2021-12-12T12:05:53.375787Z","shell.execute_reply":"2021-12-12T12:05:53.527763Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"STEP_SIZE_TRAIN = len(df_train_train)//BATCH_SIZE\nSTEP_SIZE_VALID = len(df_train_test)//BATCH_SIZE\nprint(STEP_SIZE_TRAIN,STEP_SIZE_VALID)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T12:06:07.934252Z","iopub.execute_input":"2021-12-12T12:06:07.934945Z","iopub.status.idle":"2021-12-12T12:06:07.950234Z","shell.execute_reply.started":"2021-12-12T12:06:07.934898Z","shell.execute_reply":"2021-12-12T12:06:07.947783Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# We perform cosine learning rate decay as the first few epochs will have a larger error rate and the training done after those will only increase the number of epochs which inevidently increases processing time. In-order to prevent this, we use warm-up factor which increases the learning rate from 0 to a certain value by a factor during a period. The training will begin after the epoch has reached a certain value. \n\ndef cosine_decay_with_warmup(global_step,\n                             learning_rate_base,\n                             total_steps,\n                             warmup_learning_rate=0.0,\n                             warmup_steps=0,\n                             hold_base_rate_steps=0):\n\n    if total_steps < warmup_steps:\n        raise ValueError('total_steps must be larger or equal to warmup_steps.')\n    learning_rate = 0.5 * learning_rate_base * (1 + np.cos(\n        np.pi *\n        (global_step - warmup_steps - hold_base_rate_steps\n         ) / float(total_steps - warmup_steps - hold_base_rate_steps)))\n    if hold_base_rate_steps > 0:\n        learning_rate = np.where(global_step > warmup_steps + hold_base_rate_steps,\n                                 learning_rate, learning_rate_base)\n    if warmup_steps > 0:\n        if learning_rate_base < warmup_learning_rate:\n            raise ValueError('learning_rate_base must be larger or equal to warmup_learning_rate.')\n        slope = (learning_rate_base - warmup_learning_rate) / warmup_steps\n        warmup_rate = slope * global_step + warmup_learning_rate\n        learning_rate = np.where(global_step < warmup_steps, warmup_rate,\n                                 learning_rate)\n    return np.where(global_step > total_steps, 0.0, learning_rate)\n\n\nclass WarmUpCosineDecayScheduler(Callback):\n\n    def __init__(self,\n                 learning_rate_base,\n                 total_steps,\n                 global_step_init=0,\n                 warmup_learning_rate=0.0,\n                 warmup_steps=0,\n                 hold_base_rate_steps=0,\n                 verbose=0):\n\n        super(WarmUpCosineDecayScheduler, self).__init__()\n        self.learning_rate_base = learning_rate_base\n        self.total_steps = total_steps\n        self.global_step = global_step_init\n        self.warmup_learning_rate = warmup_learning_rate\n        self.warmup_steps = warmup_steps\n        self.hold_base_rate_steps = hold_base_rate_steps\n        self.verbose = verbose\n        self.learning_rates = []\n\n    def on_batch_end(self, batch, logs=None):\n        self.global_step = self.global_step + 1\n        lr = K.get_value(self.model.optimizer.lr)\n        self.learning_rates.append(lr)\n\n    def on_batch_begin(self, batch, logs=None):\n        lr = cosine_decay_with_warmup(global_step=self.global_step,\n                                      learning_rate_base=self.learning_rate_base,\n                                      total_steps=self.total_steps,\n                                      warmup_learning_rate=self.warmup_learning_rate,\n                                      warmup_steps=self.warmup_steps,\n                                      hold_base_rate_steps=self.hold_base_rate_steps)\n        K.set_value(self.model.optimizer.lr, lr)\n        if self.verbose > 0:\n            print('\\nBatch %02d: setting learning rate to %s.' % (self.global_step + 1, lr))","metadata":{"execution":{"iopub.status.busy":"2021-12-12T12:06:12.581924Z","iopub.execute_input":"2021-12-12T12:06:12.582349Z","iopub.status.idle":"2021-12-12T12:06:12.596933Z","shell.execute_reply.started":"2021-12-12T12:06:12.582316Z","shell.execute_reply":"2021-12-12T12:06:12.595550Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cosine_lr = WarmUpCosineDecayScheduler(learning_rate_base = LEARNING_RATE,\n                                       total_steps=TOTAL_STEPS_1st,\n                                       warmup_learning_rate=0.0,\n                                       warmup_steps=TOTAL_STEPS_1st,\n                                       hold_base_rate_steps=(2 * STEP_SIZE))\n\ncallback_list = [cosine_lr]","metadata":{"execution":{"iopub.status.busy":"2021-12-12T12:06:15.006432Z","iopub.execute_input":"2021-12-12T12:06:15.006812Z","iopub.status.idle":"2021-12-12T12:06:15.013450Z","shell.execute_reply.started":"2021-12-12T12:06:15.006764Z","shell.execute_reply":"2021-12-12T12:06:15.011645Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# RUNNING THE MODEL....\n\nmodel.compile(optimizer = optimizers.SGD(lr=LEARNING_RATE),\n              loss={'regression_output': 'mean_absolute_error', \n                    'classification_output': 'categorical_crossentropy',\n                    'ordinal_regression_output' : 'binary_crossentropy'\n                    },\n              metrics = ['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2021-12-12T12:08:07.493222Z","iopub.execute_input":"2021-12-12T12:08:07.493603Z","iopub.status.idle":"2021-12-12T12:08:07.520508Z","shell.execute_reply.started":"2021-12-12T12:08:07.493572Z","shell.execute_reply":"2021-12-12T12:08:07.519186Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit_generator(generator=train_generator,\n                               steps_per_epoch=STEP_SIZE_TRAIN,\n                               validation_data=valid_generator,\n                               validation_steps=STEP_SIZE_VALID,\n                               epochs=25,\n                               callbacks = callback_list,\n                               verbose=1).history","metadata":{"execution":{"iopub.status.busy":"2021-12-12T12:08:44.080636Z","iopub.execute_input":"2021-12-12T12:08:44.081154Z","iopub.status.idle":"2021-12-12T12:50:28.087508Z","shell.execute_reply.started":"2021-12-12T12:08:44.081113Z","shell.execute_reply":"2021-12-12T12:50:28.086492Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"model.save(\"/kaggle/working/model_pre_training.h5\")\nf = open(\"/kaggle/working/history_pre_training\",\"wb\")\npickle.dump(history,f)\nf.close()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:04:18.235521Z","iopub.execute_input":"2021-12-12T13:04:18.235910Z","iopub.status.idle":"2021-12-12T13:04:19.218397Z","shell.execute_reply.started":"2021-12-12T13:04:18.235879Z","shell.execute_reply":"2021-12-12T13:04:19.217211Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# THE BASE LAYER IS FREEZED\n\nfor layer in model.layers:\n    layer.trainable = False\n\nfor i in range(-14,0):\n  model.layers[i].trainable = True\n\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T10:44:45.649768Z","iopub.execute_input":"2021-12-12T10:44:45.650213Z","iopub.status.idle":"2021-12-12T10:44:45.809992Z","shell.execute_reply.started":"2021-12-12T10:44:45.650169Z","shell.execute_reply":"2021-12-12T10:44:45.808779Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# APPLYING LOSS FUNCTIONS\n\ndef binary_focal_loss(gamma=2., alpha=.25):\n    def binary_focal_loss_fixed(y_true, y_pred):\n        pt_1 = tf.where(tf.equal(y_true, 1), y_pred, tf.ones_like(y_pred))\n        pt_0 = tf.where(tf.equal(y_true, 0), y_pred, tf.zeros_like(y_pred))\n\n        epsilon = K.epsilon()\n        pt_1 = K.clip(pt_1, epsilon, 1. - epsilon)\n        pt_0 = K.clip(pt_0, epsilon, 1. - epsilon)\n        return -K.mean(alpha * K.pow(1. - pt_1, gamma) * K.log(pt_1)) \\\n               -K.mean((1 - alpha) * K.pow(pt_0, gamma) * K.log(1. - pt_0))\n\n    return binary_focal_loss_fixed","metadata":{"execution":{"iopub.status.busy":"2021-12-12T10:44:45.812340Z","iopub.execute_input":"2021-12-12T10:44:45.812796Z","iopub.status.idle":"2021-12-12T10:44:45.822446Z","shell.execute_reply.started":"2021-12-12T10:44:45.812749Z","shell.execute_reply":"2021-12-12T10:44:45.820506Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# APPLYING CATEGORICAL FOCAL LOSS - SOFTMAX - We apply this to see the probability of the results to reduce class imbalance\n\ndef categorical_focal_loss(gamma=2., alpha=.25):\n    def categorical_focal_loss_fixed(y_true, y_pred):\n\n        # Scale predictions so that the class probas of each sample sum to 1\n        y_pred /= K.sum(y_pred, axis=-1, keepdims=True)\n\n        # Clip the prediction value to prevent NaN's and Inf's\n        epsilon = K.epsilon()\n        y_pred = K.clip(y_pred, epsilon, 1. - epsilon)\n\n        # Calculate Cross Entropy\n        cross_entropy = -y_true * K.log(y_pred)\n\n        # Calculate Focal Loss\n        loss = alpha * K.pow(1 - y_pred, gamma) * cross_entropy\n\n        # Compute mean loss in mini_batch\n        return K.mean(loss, axis=1)\n\n    return categorical_focal_loss_fixed","metadata":{"execution":{"iopub.status.busy":"2021-12-12T10:44:45.824282Z","iopub.execute_input":"2021-12-12T10:44:45.825118Z","iopub.status.idle":"2021-12-12T10:44:45.835606Z","shell.execute_reply.started":"2021-12-12T10:44:45.825073Z","shell.execute_reply":"2021-12-12T10:44:45.834287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(optimizer = optimizers.Adam(lr=WARMUP_LEARNING_RATE),\n              loss={'regression_output': mean_squared_error, \n                    'classification_output': categorical_focal_loss(alpha=.25, gamma=2) ,\n                    'ordinal_regression_output' : binary_focal_loss(alpha=.25, gamma=2)\n                    },\n              metrics = ['accuracy'])\n\nhistory = model.fit_generator(generator=train_generator,\n                              steps_per_epoch=STEP_SIZE_TRAIN,\n                              validation_data=valid_generator,\n                              validation_steps=STEP_SIZE_VALID,\n                              epochs=5,\n                              callbacks = callback_list,\n                              verbose=1).history\nmodel.save(\"/kaggle/working/model_main_training1.h5\")\nf = open(\"/kaggle/working/history_main_training\",\"wb\")\npickle.dump(history,f)\nf.close()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T10:44:45.837390Z","iopub.execute_input":"2021-12-12T10:44:45.838113Z","iopub.status.idle":"2021-12-12T10:52:28.594127Z","shell.execute_reply.started":"2021-12-12T10:44:45.838065Z","shell.execute_reply":"2021-12-12T10:52:28.592986Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# UNFREEZING LAYERS TO INCLUDE THEM IN TRAINING\n\nfor layer in model.layers:\n    layer.trainable = True\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T10:52:28.595840Z","iopub.execute_input":"2021-12-12T10:52:28.596394Z","iopub.status.idle":"2021-12-12T10:52:28.743979Z","shell.execute_reply.started":"2021-12-12T10:52:28.596335Z","shell.execute_reply":"2021-12-12T10:52:28.742745Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(optimizer = optimizers.Adam(lr=LEARNING_RATE),\n              loss={'regression_output': mean_squared_error, \n                    'classification_output': categorical_focal_loss(alpha=.25, gamma=2) ,\n                    'ordinal_regression_output' : binary_focal_loss(alpha=.25, gamma=2)\n                    },\n              metrics = ['accuracy'])\n\nhistory = model.fit_generator(generator=train_generator,\n                              steps_per_epoch=STEP_SIZE_TRAIN,\n                              validation_data=valid_generator,\n                              validation_steps=STEP_SIZE_VALID,\n                              epochs=25,\n                              callbacks = callback_list,\n                              verbose=1).history\n\nmodel.save(\"/kaggle/working/model_main_training.h5\")\nf = open(\"/kaggle/working/history_main_training\",\"wb\")\npickle.dump(history,f)\nf.close()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T10:52:28.746051Z","iopub.execute_input":"2021-12-12T10:52:28.746521Z","iopub.status.idle":"2021-12-12T11:34:22.136409Z","shell.execute_reply.started":"2021-12-12T10:52:28.746476Z","shell.execute_reply":"2021-12-12T11:34:22.135236Z"},"trusted":true},"execution_count":null,"outputs":[]}]}