{"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":"markdown","source":"**Aim of this notebook**\n\n    The aim of this notebook is to implement a very basic but powerful Classification Model Resnet50's backbone with modified top.\n\n    This is only the Training procedure but soon I will upload the Inference Pipeline.","metadata":{}},{"cell_type":"markdown","source":"**IF YOU LIKE THIS NOTEBOOK THEN, PLEASE UPVOTE!**","metadata":{}},{"cell_type":"markdown","source":"**Install Dependencies**","metadata":{}},{"cell_type":"code","source":"!pip install -q noisereduce","metadata":{"_kg_hide-output":true,"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-03-08T13:10:48.127455Z","iopub.execute_input":"2022-03-08T13:10:48.127782Z","iopub.status.idle":"2022-03-08T13:10:57.315415Z","shell.execute_reply.started":"2022-03-08T13:10:48.127685Z","shell.execute_reply":"2022-03-08T13:10:57.314587Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Imports**","metadata":{}},{"cell_type":"code","source":"import os\nimport json\nimport tqdm\nimport librosa\nimport librosa.display\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nfrom PIL import Image\nimport plotly.express as px\nimport IPython.display as ipd\nimport matplotlib.pyplot as plt\n\npd.set_option('max_rows', 250)\npd.set_option('max_columns', 100)","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:10:57.317680Z","iopub.execute_input":"2022-03-08T13:10:57.317974Z","iopub.status.idle":"2022-03-08T13:11:01.506346Z","shell.execute_reply.started":"2022-03-08T13:10:57.317937Z","shell.execute_reply":"2022-03-08T13:11:01.505579Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Configs**","metadata":{}},{"cell_type":"code","source":"seed = 42\nos.environ['PYTHONHASHSEED'] = str(seed)\nnp.random.seed(seed)\n\nDURATION = 15\nSPEC_SHAPE = (48, 128)\nSAMPLE_RATE = 32000\nTEST_DURATION = 5\nSPEC_SHAPE = (48, 128)\nFMIN = 500\nFMAX = 12500","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:01.507964Z","iopub.execute_input":"2022-03-08T13:11:01.508224Z","iopub.status.idle":"2022-03-08T13:11:01.513847Z","shell.execute_reply.started":"2022-03-08T13:11:01.508189Z","shell.execute_reply":"2022-03-08T13:11:01.512807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Load the files**","metadata":{}},{"cell_type":"code","source":"main_dir = '../input/birdclef-2022'\ntrain_audio_dir = main_dir+'/train_audio'\ntest_audio_dir = main_dir+'/test_soundscapes'\ntrain = pd.read_csv(main_dir+'/train_metadata.csv')\ntrain['time_dt'] = pd.to_datetime(train['time'], errors='coerce')\ntrain['time_dt'] = train['time_dt'].dt.round('30min')\ntrain['time_H_M'] = train['time_dt'].dt.strftime('%H:%M')\ntrain['secondary_label_len'] = train.secondary_labels.apply(lambda x:len(x.split(','))) \ntest = pd.read_csv(main_dir+'/test.csv') \nsubmission = pd.read_csv(main_dir+'/sample_submission.csv')\ntaxonomy = pd.read_csv(main_dir+'/eBird_Taxonomy_v2021.csv')\nscored_birds = json.load(open(main_dir+'/scored_birds.json', 'r'))","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:01.515280Z","iopub.execute_input":"2022-03-08T13:11:01.515502Z","iopub.status.idle":"2022-03-08T13:11:01.916849Z","shell.execute_reply.started":"2022-03-08T13:11:01.515471Z","shell.execute_reply":"2022-03-08T13:11:01.916086Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.head(5)","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:01.919411Z","iopub.execute_input":"2022-03-08T13:11:01.919707Z","iopub.status.idle":"2022-03-08T13:11:01.944607Z","shell.execute_reply.started":"2022-03-08T13:11:01.919670Z","shell.execute_reply":"2022-03-08T13:11:01.943808Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test.head(5)","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:01.946041Z","iopub.execute_input":"2022-03-08T13:11:01.946302Z","iopub.status.idle":"2022-03-08T13:11:01.955483Z","shell.execute_reply.started":"2022-03-08T13:11:01.946267Z","shell.execute_reply":"2022-03-08T13:11:01.954809Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Number of rows in train data: {}\\nNumber of columns in train data: {}\".format(train.shape[0],train.shape[1]))\nprint(\"Number of rows in test data: {}\\nNumber of columns in train data: {}\".format(test.shape[0],test.shape[1]))","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:01.956965Z","iopub.execute_input":"2022-03-08T13:11:01.957537Z","iopub.status.idle":"2022-03-08T13:11:01.964524Z","shell.execute_reply.started":"2022-03-08T13:11:01.957502Z","shell.execute_reply":"2022-03-08T13:11:01.963807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.head(5)","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:01.966073Z","iopub.execute_input":"2022-03-08T13:11:01.966570Z","iopub.status.idle":"2022-03-08T13:11:01.977504Z","shell.execute_reply.started":"2022-03-08T13:11:01.966534Z","shell.execute_reply":"2022-03-08T13:11:01.976673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"taxonomy.head(5)","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:01.978876Z","iopub.execute_input":"2022-03-08T13:11:01.979389Z","iopub.status.idle":"2022-03-08T13:11:01.995355Z","shell.execute_reply.started":"2022-03-08T13:11:01.979352Z","shell.execute_reply":"2022-03-08T13:11:01.994621Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"There are {} no of unique classes but we will be evaluated only on {} no of classes\".format(len(train.primary_label.unique()), len(scored_birds)))","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:01.996569Z","iopub.execute_input":"2022-03-08T13:11:01.997173Z","iopub.status.idle":"2022-03-08T13:11:02.003796Z","shell.execute_reply.started":"2022-03-08T13:11:01.997147Z","shell.execute_reply":"2022-03-08T13:11:02.002982Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's look at the scored classes ","metadata":{}},{"cell_type":"code","source":"print(scored_birds)","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:02.005279Z","iopub.execute_input":"2022-03-08T13:11:02.005632Z","iopub.status.idle":"2022-03-08T13:11:02.011712Z","shell.execute_reply.started":"2022-03-08T13:11:02.005597Z","shell.execute_reply":"2022-03-08T13:11:02.010696Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"    Though we will be evaluated on 21 classes there's not much data for these 21 classes - just 1266 entries (based on primary_label). So one idea could be to train on all the classes but use about those 21 classes as validation.","metadata":{}},{"cell_type":"markdown","source":"**EDA**","metadata":{}},{"cell_type":"markdown","source":"**Distributions**","metadata":{}},{"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(24, 8))\nsns.countplot(data=train, x='primary_label', ax=ax, order=train['primary_label'].value_counts().index)\nplt.xticks(rotation=90);","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:02.013404Z","iopub.execute_input":"2022-03-08T13:11:02.013658Z","iopub.status.idle":"2022-03-08T13:11:04.090551Z","shell.execute_reply.started":"2022-03-08T13:11:02.013627Z","shell.execute_reply":"2022-03-08T13:11:04.089126Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(16, 8))\nx_labels = pd.date_range(start='00:00', periods=48, freq='30min')\nx_labels = list(x_labels.strftime('%H:%M'))\nsns.countplot(data=train, x='time_H_M', ax=ax)\nax.set_xticklabels(x_labels, rotation=90);","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:04.092799Z","iopub.execute_input":"2022-03-08T13:11:04.094341Z","iopub.status.idle":"2022-03-08T13:11:04.857323Z","shell.execute_reply.started":"2022-03-08T13:11:04.094296Z","shell.execute_reply":"2022-03-08T13:11:04.856589Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.scatter_geo(\n    train,\n    lat=\"latitude\",\n    lon=\"longitude\",\n    color=\"common_name\",\n    width=1_000,\n    height=500,\n    title=\"BirdCLEF 2022 Training Data\",\n)\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:04.860510Z","iopub.execute_input":"2022-03-08T13:11:04.860722Z","iopub.status.idle":"2022-03-08T13:11:06.288309Z","shell.execute_reply.started":"2022-03-08T13:11:04.860698Z","shell.execute_reply":"2022-03-08T13:11:06.287612Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Play a Few Samples**","metadata":{}},{"cell_type":"code","source":"ipd.Audio('../input/birdclef-2022/train_audio/bcnher/XC115512.ogg')","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:06.289271Z","iopub.execute_input":"2022-03-08T13:11:06.289518Z","iopub.status.idle":"2022-03-08T13:11:06.317168Z","shell.execute_reply.started":"2022-03-08T13:11:06.289482Z","shell.execute_reply":"2022-03-08T13:11:06.316531Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ipd.Audio('../input/birdclef-2022/train_audio/barpet/XC189894.ogg')","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:06.318262Z","iopub.execute_input":"2022-03-08T13:11:06.318986Z","iopub.status.idle":"2022-03-08T13:11:06.332508Z","shell.execute_reply.started":"2022-03-08T13:11:06.318951Z","shell.execute_reply":"2022-03-08T13:11:06.331813Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ipd.Audio('../input/birdclef-2022/train_audio/akekee/XC210201.ogg')","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:06.333807Z","iopub.execute_input":"2022-03-08T13:11:06.334464Z","iopub.status.idle":"2022-03-08T13:11:06.385907Z","shell.execute_reply.started":"2022-03-08T13:11:06.334426Z","shell.execute_reply":"2022-03-08T13:11:06.384932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ipd.Audio('../input/birdclef-2022/train_audio/afrsil1/XC125458.ogg')","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:06.387410Z","iopub.execute_input":"2022-03-08T13:11:06.387643Z","iopub.status.idle":"2022-03-08T13:11:06.403421Z","shell.execute_reply.started":"2022-03-08T13:11:06.387613Z","shell.execute_reply":"2022-03-08T13:11:06.402710Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ipd.Audio('../input/birdclef-2022/train_audio/apapan/XC139974.ogg')","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:06.404623Z","iopub.execute_input":"2022-03-08T13:11:06.404870Z","iopub.status.idle":"2022-03-08T13:11:06.445968Z","shell.execute_reply.started":"2022-03-08T13:11:06.404840Z","shell.execute_reply":"2022-03-08T13:11:06.445379Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Spectograms**","metadata":{}},{"cell_type":"code","source":"import torch\nimport torchaudio\nimport noisereduce as nr\nfrom math import ceil\n\ndef create_spectrogram(\n    fname: str,\n    reduce_noise: bool = False,\n    frame_size: int = 5,\n    frame_step: int = 2,\n    channel: int = 0,\n    device = \"cpu\",\n) -> list:\n    waveform, sample_rate = torchaudio.load(fname)\n    \n    transform = torchaudio.transforms.Spectrogram(n_fft=1800, win_length=512).to(device)\n    if reduce_noise:\n        waveform = torch.tensor(nr.reduce_noise(\n            y=waveform,\n            sr=sample_rate,\n            win_length=transform.win_length,\n            use_tqdm=False,\n            n_jobs=2,\n        ))\n    step = int(frame_step * sample_rate)\n    size = int(frame_size * sample_rate)\n    spectrograms = []\n    for i in range(ceil((waveform.size()[-1] - size) / step)):\n        begin = i * step\n        frame = waveform[channel][begin:begin + size]\n        if len(frame) < size:\n            if i == 0:\n                rep = round(float(size) / len(frame))\n                frame = frame.repeat(int(rep))\n            elif len(frame) < (size * 0.33):\n                continue\n            else:\n                frame = waveform[channel][-size:]\n        sg = transform(frame.to(device))\n        spectrograms.append(np.nan_to_num(torch.log(sg).numpy()))\n        # spectrograms.append(np.nan_to_num(sg.numpy()))\n    return spectrograms\n\n\npath_audio = os.path.join(train_audio_dir, train[\"filename\"][0])\nprint(path_audio)\nsgs = create_spectrogram(path_audio, reduce_noise=True)\n\n\nfig, axarr = plt.subplots(ncols=len(sgs), figsize=(4 * len(sgs), 4))\nfor i, sg in enumerate(sgs):\n    ax = axarr[i].imshow(sg, vmin=-50, vmax=10)\nplt.colorbar(ax)","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:06.447145Z","iopub.execute_input":"2022-03-08T13:11:06.447546Z","iopub.status.idle":"2022-03-08T13:11:09.691213Z","shell.execute_reply.started":"2022-03-08T13:11:06.447515Z","shell.execute_reply":"2022-03-08T13:11:09.690578Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Now let's get back to the modeling**\n\n**Define the OneHotEncoder in order to convert all the classes beforehand**","metadata":{}},{"cell_type":"code","source":"from sklearn.preprocessing import OneHotEncoder\n\nohe = OneHotEncoder()\nohe.fit(train.primary_label.unique().reshape(-1, 1))\n\nt_values = np.argmax(np.array(ohe.transform(train['primary_label'].values.reshape(-1, 1)).toarray()), 1)\ntrain['target'] = t_values","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:09.692788Z","iopub.execute_input":"2022-03-08T13:11:09.693230Z","iopub.status.idle":"2022-03-08T13:11:09.728109Z","shell.execute_reply.started":"2022-03-08T13:11:09.693196Z","shell.execute_reply":"2022-03-08T13:11:09.727436Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Genarating The Train Data**\n\nThe main idea behind generating the data is that:-\n           \n    The test predictions only requires audio for 5 seconds but the length of audio in           training set varies so here we will split the audio in 5 seconds intervals\n    For example if the audio is 13 seconds long then we will divide it to\n      1)1-5 seconds audio\n      2)6-10 seconds audio\n    The disadvantages of this technique is that i)We are loosing some information by \n                                                  removing the last portion of the audio\n                                                  (I think that we can just pad it to use                                                     that portion)\n                                                  \n                                                ii)We are assuming that the bird's call will be present in all the sub audio samples which may or may not be the case.                                            ","metadata":{}},{"cell_type":"code","source":"train.head(3)","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:09.730401Z","iopub.execute_input":"2022-03-08T13:11:09.730831Z","iopub.status.idle":"2022-03-08T13:11:09.748864Z","shell.execute_reply.started":"2022-03-08T13:11:09.730794Z","shell.execute_reply":"2022-03-08T13:11:09.747923Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.primary_label.value_counts().describe()","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:09.750438Z","iopub.execute_input":"2022-03-08T13:11:09.750698Z","iopub.status.idle":"2022-03-08T13:11:09.765694Z","shell.execute_reply.started":"2022-03-08T13:11:09.750663Z","shell.execute_reply":"2022-03-08T13:11:09.764868Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\nx_train, x_val, y_train, y_val = train_test_split(train[train.primary_label!='maupar'], train[train.primary_label!='maupar']['primary_label'], stratify=train[train.primary_label!='maupar']['primary_label'], test_size=0.2, random_state=seed)","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:09.766986Z","iopub.execute_input":"2022-03-08T13:11:09.767313Z","iopub.status.idle":"2022-03-08T13:11:09.811837Z","shell.execute_reply.started":"2022-03-08T13:11:09.767274Z","shell.execute_reply":"2022-03-08T13:11:09.811183Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''\nHere I am generating the data for all entries of all classes but if require we can just\nkeep some images per class to use as validation.\nEx. Use 80% images from each class for train and\n    Keep 20% of images from each class for validation.\n    \n'''\ndef get_data(df):\n    X = []\n    Y = []\n    for ul in tqdm.tqdm(df.primary_label.unique()):\n        records = df[df.primary_label==ul]\n        for r in records[['filename','primary_label','secondary_labels']].values:\n            file = r[0]\n            pl = r[1]\n            sl = r[2]\n            y = ohe.transform(np.array([pl]).reshape(-1, 1)).todense()\n            arr, sr = librosa.load(os.path.join(train_audio_dir, file), sr=SAMPLE_RATE, duration=DURATION)\n            chunks = []\n            for c_ in range(0, len(arr), (TEST_DURATION*SAMPLE_RATE)):\n                chunk = arr[c_:c_ + TEST_DURATION * SAMPLE_RATE]\n                if len(chunk) < int(TEST_DURATION * SAMPLE_RATE):\n                    break\n                chunks.append(chunk)\n            y_arr = []\n            mel_chunks = []\n            for c_ in chunks:\n                hop_length = int(TEST_DURATION * SAMPLE_RATE / (SPEC_SHAPE[1] - 1))\n                #Extract Mel Spec\n                mel_spec = librosa.feature.melspectrogram(y=c_,sr=SAMPLE_RATE,n_fft=1024, hop_length=hop_length, \n                                                      n_mels=SPEC_SHAPE[0], fmin=FMIN, fmax=FMAX)\n\n                mel_spec = librosa.power_to_db(mel_spec, ref=np.max) \n                # Normalize\n                mel_spec = (mel_spec - mel_spec.min())/(mel_spec.max() - mel_spec.min())\n                mel_chunks.append(np.asarray(Image.fromarray(mel_spec * 255.0).convert(\"RGB\")))\n                y_arr.append(y)\n            y_arr = np.array(y_arr).reshape(-1, 152)\n            mel_chunks = np.array(mel_chunks)\n            X.extend(mel_chunks)\n            Y.extend(y_arr)\n\n    X = np.array(X)\n    Y = np.array(Y) \n    print(X.shape,Y.shape)\n    return X, Y","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:09.814418Z","iopub.execute_input":"2022-03-08T13:11:09.814606Z","iopub.status.idle":"2022-03-08T13:11:09.828209Z","shell.execute_reply.started":"2022-03-08T13:11:09.814583Z","shell.execute_reply":"2022-03-08T13:11:09.826467Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_X, train_Y = get_data(x_train)\nval_X, val_Y = get_data(x_val)","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:11:09.829221Z","iopub.execute_input":"2022-03-08T13:11:09.829560Z","iopub.status.idle":"2022-03-08T13:28:06.602428Z","shell.execute_reply.started":"2022-03-08T13:11:09.829526Z","shell.execute_reply":"2022-03-08T13:28:06.601497Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Define and Plot The Model**\n\n    1)We are using the ResNet50 as backbone with weights freezed you can try to train them if you like","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nimport tensorflow_addons as tfa\n\ntf.random.set_seed(seed)\n\nipt = tf.keras.layers.Input((48, 128, 3))\nbb = tf.keras.applications.resnet.ResNet50(include_top=False, weights='imagenet')\nbb.trainable = False\nx = bb(ipt)\nx = tf.keras.layers.GlobalAveragePooling2D()(x)\nx = tf.keras.layers.Dense(1024, activation='relu')(x)\nx = tf.keras.layers.Dropout(0.6)(x)\nx = tf.keras.layers.Dense(512, activation='relu')(x)\nx = tf.keras.layers.Dropout(0.6)(x)\nx = tf.keras.layers.Dense(256, activation='relu')(x)\nx = tf.keras.layers.Dropout(0.6)(x)\nopt = tf.keras.layers.Dense(152, activation='softmax')(x)\n\nmodel = tf.keras.models.Model(ipt, opt)\nmodel.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy', tfa.metrics.F1Score(num_classes=len(train.primary_label.unique()))])\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:28:06.606965Z","iopub.execute_input":"2022-03-08T13:28:06.607344Z","iopub.status.idle":"2022-03-08T13:28:18.704136Z","shell.execute_reply.started":"2022-03-08T13:28:06.607298Z","shell.execute_reply":"2022-03-08T13:28:18.703377Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**For Now I am just using the \"validation_split\" but later on I will change it to better approach and will also add K-Fold so stay tuned for that!**\n\n**We are using ModelCheckpoint and EarlyStopping as Callbacks**","metadata":{}},{"cell_type":"code","source":"callbacks = [tf.keras.callbacks.EarlyStopping(monitor='val_loss', \n                                              verbose=1,\n                                              patience=5),\n             tf.keras.callbacks.ModelCheckpoint(filepath='best_model.h5', \n                                                monitor='val_loss',\n                                                verbose=0,\n                                                save_best_only=True)]\n\nmodel.fit(train_X, train_Y, batch_size = 32, epochs=200, validation_data = (val_X, val_Y),\n         callbacks=[])","metadata":{"execution":{"iopub.status.busy":"2022-03-08T13:28:18.705331Z","iopub.execute_input":"2022-03-08T13:28:18.705643Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Conclution: **\n        \n    For Now the model is doing pretty bad but I will keep updating it's weights in my local machine and if the result it fair enough then I will publish!\n    \n    \n       ","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}