{"cells":[{"metadata":{"_uuid":"a30a772d-d3c1-4505-8eae-29d88eaf3894","_cell_guid":"28d8cd88-8894-41a6-9740-1847adbc23cb","trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"from IPython.display import Image\nImage(filename='../input/landmark-retrieval-2020/train/0/0/0/000014b1f770f640.jpg')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"256189bf-cece-4572-aef6-352bb0922e3b","_cell_guid":"2eaaadd9-633b-4b3a-9a70-db869e973857","trusted":true},"cell_type":"markdown","source":"The purpose of this notebook is to illustrate how to create Resnet50 from scratch on Tensorflow 2.x . This kernel just uses top 100 classes. For actual competition we would need to model all classes with neccessary methods to handle class imbalance","execution_count":null},{"metadata":{"_uuid":"e43547ff-5058-45c1-ace0-59023389f378","_cell_guid":"220bcfe8-2e43-4a59-aad0-b573b56f6646","trusted":true},"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\nimport numpy as np # linear algebra\nimport 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\nimport os\nimport tensorflow as tf\nimport cv2\nimport skimage.io\nfrom skimage.transform import resize\nfrom imgaug import augmenters as iaa\nfrom sklearn import preprocessing\nfrom sklearn.preprocessing import LabelBinarizer,LabelEncoder\nfrom sklearn.utils.class_weight import compute_class_weight\nfrom tensorflow.keras import layers\nfrom tensorflow.keras.layers import Input, Add, Dense, Dropout, Activation, ZeroPadding2D, BatchNormalization, Flatten, Conv2D, AveragePooling2D, MaxPooling2D, GlobalMaxPooling2D,GlobalAveragePooling2D,Concatenate, ReLU, LeakyReLU,Reshape, Lambda\nfrom tensorflow.keras.callbacks import ModelCheckpoint, LearningRateScheduler, EarlyStopping, ReduceLROnPlateau\nfrom tensorflow.keras.optimizers import Adam,SGD\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.models import Sequential, load_model, Model\nfrom tensorflow.keras.callbacks import LearningRateScheduler\nfrom tensorflow.keras.preprocessing import image\nfrom tensorflow.keras.utils import to_categorical\nfrom tensorflow.keras import metrics\nfrom tensorflow.keras.preprocessing import image\nfrom tensorflow.keras.applications.imagenet_utils import preprocess_input\nfrom tensorflow.keras.initializers import glorot_uniform\nfrom tensorflow.keras.applications import ResNet101\nfrom tqdm import tqdm\nimport imgaug as ia\nfrom imgaug import augmenters as iaa\nfrom PIL import Image\nimport keras.backend as K\nK.set_image_data_format('channels_last')\nK.set_learning_phase(1)\n\n\nfrom tensorflow.keras import activations\nfrom tensorflow.keras.datasets import cifar10\nfrom tensorflow.keras.regularizers import l2\nfrom tensorflow.keras.layers import Activation, Add, AveragePooling2D, BatchNormalization, Conv2D, Conv2DTranspose, Dense, Flatten, Input, Reshape, ZeroPadding2D\n# You can write up to 5GB 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","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"e6fb3b9b-d45d-4eca-9e79-3bd4dd834706","_cell_guid":"c280ff0c-9a0d-4f57-9bbe-5bfc4fa25804","trusted":true},"cell_type":"markdown","source":"**Path retrieval**\n\n\nTaken from the public kernel...thanks for sharing this. It was quite helpful for me. Please upvote that kernel if you also found that helpful\nhttps://www.kaggle.com/derinformatiker/landmark-retrieval-all-paths","execution_count":null},{"metadata":{"_uuid":"151b5e01-ce42-40b6-89a1-171a750f1697","_cell_guid":"3f7a923e-5583-4870-a43c-d4795bb0ac50","trusted":true},"cell_type":"code","source":"train = pd.read_csv(\"../input/landmark-retrieval-2020/train.csv\")\ndef get_paths(sub):\n    index = [\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"a\",\"b\",\"c\",\"d\",\"e\",\"f\"]\n\n    paths = []\n\n    for a in index:\n        for b in index:\n            for c in index:\n                try:\n                    paths.extend([f\"../input/landmark-retrieval-2020/{sub}/{a}/{b}/{c}/\" + x for x in os.listdir(f\"../input/landmark-retrieval-2020/{sub}/{a}/{b}/{c}\")])\n                except:\n                    pass\n\n    return paths","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"277eecda-cd78-4eb6-89ca-def6fd898689","_cell_guid":"ff97e2ff-fd98-4fca-b5b1-aafb663e2e3a","trusted":true},"cell_type":"markdown","source":"Thanks and Credits - @nawidsayed for suggesting a change in line number 3 and making it much more efficient. His profile link is given below:   https://www.kaggle.com/nawidsayed","execution_count":null},{"metadata":{"_uuid":"94828641-00c7-46be-9a24-b1aa40851e24","_cell_guid":"40631189-5cf9-4267-bc2d-ae45f89f16c3","trusted":true},"cell_type":"code","source":"\ntrain_path = train\ntrain_path[\"id\"] = train_path.id.map(lambda path: f\"../input/landmark-retrieval-2020/train/{path[0]}/{path[1]}/{path[2]}/{path}.jpg\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"9d3c403b-e4b5-4b67-96df-6be9ebef5ab6","_cell_guid":"6dbe8f9f-df4a-4e29-8726-9f9caa353826","trusted":true},"cell_type":"code","source":"##Old implementation - changed after suggestion from @nawidsayed\n'''\ntrain_path = train\n\nrows = []\nfor i in tqdm(range(len(train))):\n    row = train.iloc[i]\n    path  = list(row[\"id\"])[:3]\n    temp = row[\"id\"]\n    row[\"id\"] = f\"../input/landmark-retrieval-2020/train/{path[0]}/{path[1]}/{path[2]}/{temp}.jpg\"\n    rows.append(row[\"id\"])\n    \nrows = pd.DataFrame(rows)\ntrain_path[\"id\"] = rows\n'''","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"6b1aa806-6434-4e2e-a120-dfaf082e9db5","_cell_guid":"2f12346b-7625-4a08-a9e5-60901600816d","trusted":true},"cell_type":"markdown","source":"**Setting up some basic model specs**","execution_count":null},{"metadata":{"_uuid":"0829b094-fe55-42d9-8018-87c02f36702a","_cell_guid":"2e512c71-310d-421e-b9f8-f080a30ccbb2","trusted":true},"cell_type":"code","source":"batch_size = 128\n# seed = 42\nshape = (64, 64, 3) ##desired shape of the image for resizing purposes\nval_sample = 0.1 # 10 % as validation sample","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"4962fc5a-c448-4f9c-aca4-a930863a9b52","_cell_guid":"474de043-d586-4149-997d-8b32b8eb71a2","trusted":true},"cell_type":"code","source":"train_labels = pd.read_csv('../input/landmark-retrieval-2020/train.csv')\ntrain_labels.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"092553b1-715c-4e42-abd3-588d05a87ce6","_cell_guid":"4091cc67-fcbc-4f39-b1e4-e97c8d68748b","trusted":true},"cell_type":"code","source":"k =train[['id','landmark_id']].groupby(['landmark_id']).agg({'id':'count'})\nk.rename(columns={'id':'Count_class'}, inplace=True)\nk.reset_index(level=(0), inplace=True)\nfreq_ct_df = pd.DataFrame(k)\nfreq_ct_df.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"175cc324-7cde-41d2-a8c2-373f460549f3","_cell_guid":"4614febc-6305-44af-9df7-aaf26b39075a","trusted":true},"cell_type":"code","source":"train_labels = pd.merge(train,freq_ct_df, on = ['landmark_id'], how='left')\ntrain_labels.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"353eccc6-40b8-4e4e-9334-113b6035eafc","_cell_guid":"3e14cc1b-2b50-4b96-b54e-b5117fcd5ba9","trusted":true},"cell_type":"code","source":"freq_ct_df.sort_values(by=['Count_class'],ascending=False,inplace=True)\nfreq_ct_df.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"3f08e74a-191c-4cd5-9508-325867c94205","_cell_guid":"a86225d6-ffa3-422f-a076-0a051810e9dd","trusted":true},"cell_type":"markdown","source":"**Due to Kernel runtime limits, for illustrating the example let's run this for top 100 landmark categories**","execution_count":null},{"metadata":{"_uuid":"5553f7bb-da20-4f0c-82ae-9b9e23f57428","_cell_guid":"bc322d45-64ef-401d-9952-437ca94a2074","trusted":true},"cell_type":"code","source":"freq_ct_df_top100 = freq_ct_df.iloc[:100]\ntop100_class = freq_ct_df_top100['landmark_id'].tolist()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"7084344e-c231-4b72-abb4-bb38c51c8626","_cell_guid":"f33f05e8-ed88-441f-b5cf-01c811dac975","trusted":true},"cell_type":"code","source":"top100class_train = train_path[train_path['landmark_id'].isin (top100_class) ]\ntop100class_train.shape","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"922add3b-a46d-4b05-b1aa-d536c003bf0a","_cell_guid":"fbe49084-265f-47ac-bffb-06c8c242d1e6","trusted":true},"cell_type":"code","source":"def getTrainParams():\n    data = top100class_train.copy()\n    le = preprocessing.LabelEncoder()\n    data['label'] = le.fit_transform(data['landmark_id'])\n    lbls = top100class_train['landmark_id'].tolist()\n    lb = LabelBinarizer()\n    labels = lb.fit_transform(lbls)\n    \n    return np.array(top100class_train['id'].tolist()),np.array(labels),le","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"e9d1f5dc-b92b-4b4a-b149-bf07460ea62b","_cell_guid":"69dfb763-3977-4101-b3d7-9c0913b99284","trusted":true},"cell_type":"markdown","source":"Credit to Michal Haltuf from whose kernel I had first learnt Data Generators two years back.\nYou can check out his kernel here: https://www.kaggle.com/rejpalcz/cnn-128x128x4-keras-from-scratch-lb-0-328","execution_count":null},{"metadata":{"_uuid":"8990b64d-c68a-4560-a325-41cbf69a7284","_cell_guid":"56539c5b-5e3b-43d2-bedf-3ceff050946a","trusted":true},"cell_type":"code","source":"class Landmark2020_DataGenerator(tf.keras.utils.Sequence):\n    def __init__(self, paths, labels, batch_size, shape, shuffle = False, use_cache = False, augment = False):\n        self.paths, self.labels = paths, labels\n        self.batch_size = batch_size\n        self.shape = shape\n        self.shuffle = shuffle\n        self.use_cache = use_cache\n        self.augment = augment\n        if use_cache == True:\n            self.cache = np.zeros((paths.shape[0], shape[0], shape[1], shape[2]), dtype=np.float16)\n            self.is_cached = np.zeros((paths.shape[0]))\n        self.on_epoch_end()\n    \n    def __len__(self):\n        return int(np.ceil(len(self.paths) / float(self.batch_size)))\n    \n    def __getitem__(self, idx):\n        indexes = self.indexes[idx * self.batch_size : (idx+1) * self.batch_size]\n\n        paths = self.paths[indexes]\n        X = np.zeros((paths.shape[0], self.shape[0], self.shape[1], self.shape[2]))\n        y = X\n        # Generate data\n        if self.use_cache == True:\n            X = self.cache[indexes]\n            for i, path in enumerate(paths[np.where(self.is_cached[indexes] == 0)]):\n                image = self.__load_image(path)\n                self.is_cached[indexes[i]] = 1\n                self.cache[indexes[i]] = image\n                X[i] = image\n        else:\n            for i, path in enumerate(paths):\n                X[i] = self.__load_image(path)\n\n        y = X/255.0\n        X = X/255.0\n#         window_name = 'image'\n\n#         print('X:', X)\n#         print('y', y)\n                \n#         if self.augment == True:\n#             seq = iaa.Sequential([\n#                 iaa.OneOf([\n#                     iaa.Fliplr(0.5), # horizontal flips\n                    \n#                     iaa.ContrastNormalization((0.75, 1.5)),\n#                     iaa.AdditiveGaussianNoise(loc=0, scale=(0.0, 0.05*255), per_channel=0.5),\n#                     iaa.Multiply((0.8, 1.2), per_channel=0.2),\n                    \n#                     iaa.Affine(rotate=0),\n#                     #iaa.Affine(rotate=90),\n#                     #iaa.Affine(rotate=180),\n#                     #iaa.Affine(rotate=270),\n#                     iaa.Fliplr(0.5),\n#                     #iaa.Flipud(0.5),\n#                 ])], random_order=True)\n\n#             X = np.concatenate((X, seq.augment_images(X), seq.augment_images(X), seq.augment_images(X)), 0)\n#             y = np.concatenate((y, y, y, y), 0)\n        \n        return X, y\n    \n    def on_epoch_end(self):\n        \n        # Updates indexes after each epoch\n        self.indexes = np.arange(len(self.paths))\n        if self.shuffle == True:\n            np.random.shuffle(self.indexes)\n\n    def __iter__(self):\n        \"\"\"Create a generator that iterate over the Sequence.\"\"\"\n        for item in (self[i] for i in range(len(self))):\n            yield item\n            \n    def __load_image(self, path):\n        im = np.array(Image.open(str(path)).convert('RGB').resize((self.shape[0], self.shape[1])))\n#         print(im)\n        return im","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"84846415-08f6-4199-9333-7fb61851ba45","_cell_guid":"a0b7a4be-7331-4b6f-9caa-90cf95c8c25b","trusted":true},"cell_type":"code","source":"nlabls = top100class_train['landmark_id'].nunique()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"cf6157ed-87dd-43dc-8bf3-93ca742934d9","_cell_guid":"08eb3915-e2cd-452d-91c4-8a58d2f3c202","trusted":true},"cell_type":"code","source":"paths, labels,_ = getTrainParams()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"9ab44a52-1662-44ff-bed9-4b8750880867","_cell_guid":"0784d80b-d0be-416b-8311-d976cd94f898","trusted":true},"cell_type":"code","source":"keys = np.arange(paths.shape[0], dtype=np.int)  \n# np.random.seed(seed)\nnp.random.shuffle(keys)\nlastTrainIndex = int((1-val_sample) * paths.shape[0])\n\npathsTrain = paths[0:lastTrainIndex]\nlabelsTrain = labels[0:lastTrainIndex]\n\npathsVal = paths[lastTrainIndex:]\nlabelsVal = labels[lastTrainIndex:]\n\nprint(paths.shape, labels.shape)\nprint(pathsTrain.shape, labelsTrain.shape, pathsVal.shape, labelsVal.shape)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"688291f4-dce5-4011-9af6-d64f9620256a","_cell_guid":"15c58ba2-5a8d-4df1-910e-233d1776d340","trusted":true},"cell_type":"code","source":"train_generator = Landmark2020_DataGenerator(pathsTrain, labelsTrain, batch_size, shape, use_cache=False, augment = False, shuffle = True)\nval_generator = Landmark2020_DataGenerator(pathsVal, labelsVal, batch_size, shape, use_cache=False, shuffle = False)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"1d79b1df-9f26-411d-a6f6-5899488051f4","_cell_guid":"dbe911b0-96a4-49fa-a9b8-615d4fd0e6f4","trusted":true},"cell_type":"markdown","source":"**Let's build the building blocks of a Resnet model one by one**\n\n\n\nCredits: Prof. Andrew Ng course on deep learning","execution_count":null},{"metadata":{"_uuid":"613c37d2-54e7-4f57-b4d8-225852fa51be","_cell_guid":"5a50e34b-a3a4-4484-a13d-e796e477bf74","trusted":true},"cell_type":"markdown","source":"**The complete architecture of a ResNet50 can be shown as follows:**","execution_count":null},{"metadata":{"_uuid":"43febfb8-c427-42cb-b619-62d72e77efd5","_cell_guid":"9ea551a7-b385-4317-863a-6f4ebdea488c","trusted":true},"cell_type":"markdown","source":"![](https://miro.medium.com/max/2792/1*hEU7S-EiVqcmtAlj6kgfRA.png)","execution_count":null},{"metadata":{"_uuid":"69ba7968-b005-43fb-a91f-ae5cb860be30","_cell_guid":"c6271904-0d57-4343-b393-380acce2ea6d","trusted":true},"cell_type":"markdown","source":"Starting first with the identity block creation","execution_count":null},{"metadata":{"_uuid":"f4a53b3d-fa2f-4b5f-a3de-222a7c183d23","_cell_guid":"cfc8d304-1554-4ede-8c96-58b821810a1e","trusted":true},"cell_type":"markdown","source":"![](https://i.stack.imgur.com/37qzA.png)","execution_count":null},{"metadata":{"_uuid":"b1182109-1890-4589-94db-ccbdc95be242","_cell_guid":"af2087eb-87ca-44fd-b4c4-cda8d8ae1bff","trusted":true},"cell_type":"code","source":"def dres_identity(x, filters): \n    # resnet block where dimension doesnot change.\n    # The skip connection is just simple identity conncection\n    # There will be 3 blocks and then input will be added\n\n    x_skip = x # this will be used for addition with the residual block \n    f1, f2 = filters\n\n    # first block \n    x = Conv2DTranspose(f2, kernel_size=(1, 1), strides=(1, 1), padding='valid')(x)\n    x = BatchNormalization()(x)\n    x = Activation(activations.relu)(x)\n\n\n    # second block # bottleneck (but size kept same with padding)\n    x = Conv2DTranspose(f1, kernel_size=(3, 3), strides=(1, 1), padding='same')(x)\n    x = BatchNormalization()(x)\n    x = Activation(activations.relu)(x)\n\n    # third block activation used after adding the input\n    x = Conv2DTranspose(f1, kernel_size=(1, 1), strides=(1, 1), padding='valid')(x)\n    x = BatchNormalization()(x)\n\n    # add the input \n    x = Add()([x, x_skip])\n    x = Activation(activations.relu)(x)\n\n    return x","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5265bf52-1d3f-499b-9daf-119291459dd9","_cell_guid":"2033218b-c1b2-41e2-85b0-32b775077621","trusted":true},"cell_type":"markdown","source":"Creating the convolutional block","execution_count":null},{"metadata":{"_uuid":"79f477ad-21b9-4433-ac41-08a8d3e2b62d","_cell_guid":"d0c1babe-0539-4c25-8863-6aa63b7b0677","trusted":true},"cell_type":"markdown","source":"![](https://i.stack.imgur.com/0mE2p.png)","execution_count":null},{"metadata":{"_uuid":"fc9fe352-1eba-4f0d-aa11-2769c91a5925","_cell_guid":"8583cfc6-f3ff-47c6-9fbd-2bd3ec4ff64c","trusted":true},"cell_type":"code","source":"def dres_conv(x, s, filters):\n    # here the input size changes\n    x_skip = x\n    f1, f2 = filters\n\n    # third block\n    x = Conv2DTranspose(f2, kernel_size=(1, 1), strides=(1, 1), padding='valid')(x)\n    x = BatchNormalization()(x)\n    x = Activation(activations.relu)(x)\n\n    # second block\n    x = Conv2DTranspose(f1, kernel_size=(3, 3), strides=(1, 1), padding='same')(x)\n    x = BatchNormalization()(x)\n    x = Activation(activations.relu)(x)\n\n    # third block\n    x = Conv2DTranspose(f1, kernel_size=(1, 1), strides=(s, s), padding='valid')(x)\n    # when s = 2 then it is like downsizing the feature map\n    x = BatchNormalization()(x)\n\n    # shortcut \n    x_skip = Conv2DTranspose(f1, kernel_size=(1, 1), strides=(s, s), padding='valid')(x_skip)\n    x_skip = BatchNormalization()(x_skip)\n\n    # add \n    x = Add()([x, x_skip])\n    x = Activation(activations.relu)(x)\n\n    return x","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a914e5ee-c95f-4435-a877-c8174b9f0efd","_cell_guid":"25fca4e9-5aa8-4219-bd4b-baf956fab816","trusted":true},"cell_type":"markdown","source":"**Bringing everything together**\n\nThe architecture we are trying to implement is as follows:\n\nCONV2D -> BATCHNORM -> RELU -> MAXPOOL -> CONVBLOCK -> IDBLOCK*2 -> CONVBLOCK -> IDBLOCK*3\n    -> CONVBLOCK -> IDBLOCK*5 -> CONVBLOCK -> IDBLOCK*2 -> AVGPOOL -> TOPLAYER\n    \n    \nThe detailed architecture of ResNet-50 model is:\n\n* Zero-padding pads the input with a pad of (3,3)\n* Stage 1:\n        The 2D Convolution has 64 filters of shape (7,7) and uses a stride of (2,2). Its name is \"conv1\".\n        BatchNorm is applied to the channels axis of the input.\n        MaxPooling uses a (3,3) window and a (2,2) stride.\n* Stage 2:\n        The convolutional block uses three set of filters of size [64,64,256], \"f\" is 3, \"s\" is 1 and the  block is \"a\".\n        The 2 identity blocks use three set of filters of size [64,64,256], \"f\" is 3 and the blocks are \"b\" and \"c\".\n    Stage 3:\n        The convolutional block uses three set of filters of size [128,128,512], \"f\" is 3, \"s\" is 2 and the block is \"a\".\n        The 3 identity blocks use three set of filters of size [128,128,512], \"f\" is 3 and the blocks are \"b\", \"c\" and \"d\".\n    Stage 4:\n        The convolutional block uses three set of filters of size [256, 256, 1024], \"f\" is 3, \"s\" is 2 and the block is \"a\".\n        The 5 identity blocks use three set of filters of size [256, 256, 1024], \"f\" is 3 and the blocks are \"b\", \"c\", \"d\", \"e\" and \"f\".\n    Stage 5:\n        The convolutional block uses three set of filters of size [512, 512, 2048], \"f\" is 3, \"s\" is 2 and the block is \"a\".\n        The 2 identity blocks use three set of filters of size [512, 512, 2048], \"f\" is 3 and the blocks are \"b\" and \"c\".\n*     The 2D Average Pooling uses a window of shape (2,2) and its name is \"avg_pool\".\n*     The Fully Connected (Dense) layer reduces its input to the number of classes using a softmax activation.","execution_count":null},{"metadata":{"_uuid":"ae1f6e8b-13c9-481c-9df4-aaf47407ce69","_cell_guid":"1ad2e33c-4889-40b4-a08d-efffdce903ca","trusted":true},"cell_type":"code","source":"input_im = Input(shape=(64, 64, 3))\nEncoder = ResNet101(include_top=False, weights='imagenet', input_shape=(64, 64, 3))\nx = Encoder(input_im)\nx = Flatten()(x)\nencoding = Dense(2048, kernel_initializer='he_normal')(x)\nencoder = tf.keras.Model(inputs=input_im, outputs=encoding, name='Encoder')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"e22ef56a-8508-4e4c-abb0-cf5740f6a588","_cell_guid":"e3aaa55e-e2aa-4f94-9ca5-60a7f8101571","trusted":true},"cell_type":"code","source":"# Decoder\ndec_input = Input(shape=(2048,))\nx = Dense(2 * 2 * 2048, kernel_initializer='he_normal')(dec_input)\nx = Reshape((2, 2, 2048))(x)\n\nx = dres_conv(x, s=2, filters=(512, 2048))\nx = dres_identity(x, filters=(512, 2048))\nx = dres_identity(x, filters=(512, 2048))\n\nx = dres_conv(x, s=2, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\nx = dres_identity(x, filters=(256, 1024))\n\n\nx = dres_conv(x, s=2, filters=(128, 512))\nx = dres_identity(x, filters=(128, 512))\nx = dres_identity(x, filters=(128, 512))\nx = dres_identity(x, filters=(128, 512))\n\nx = dres_conv(x, s=2, filters=(64, 256))\nx = dres_identity(x, filters=(64, 256))\nx = dres_identity(x, filters=(64, 256))\nx = Conv2DTranspose(3, kernel_size=(7, 7), strides=(2, 2), padding='same')(x)\nx = BatchNormalization()(x)\n# decoded = Activation(activations.relu)(x)\ndecoded = Activation(activations.sigmoid)(x)\ndecoder = tf.keras.Model(inputs=dec_input, outputs=decoded, name='Decoder')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"50d037ec-acf9-4513-9ab6-546ab05c9b5d","_cell_guid":"f415b78d-e102-46a4-a1ca-8ae0c7c44fab","trusted":true},"cell_type":"code","source":"enc_input = Input(shape=(64, 64, 3))\nencoding = encoder(enc_input)\ndecoded = decoder(encoding)\nauto_encoder = tf.keras.Model(inputs=enc_input, outputs=decoded, name='AutoEncoder')\nauto_encoder.compile(optimizer='adam', loss=tf.keras.losses.MeanSquaredError())\nauto_encoder.summary()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"43a0fa42-dd74-4305-891b-ec3db8548c71","_cell_guid":"17df5e6f-8999-4bb0-addd-26ddaaf6bf17","trusted":true},"cell_type":"code","source":"# epochs = 2\n# use_multiprocessing = True \n#workers = 1","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"225c9534-f6ed-45f5-b210-560960d63ebf","_cell_guid":"2d828daa-0658-4bbf-9b2c-832ba78ff10f","trusted":true},"cell_type":"code","source":"device_name = tf.test.gpu_device_name()\nif device_name != '/device:GPU:0':\n    raise SystemError('GPU device not found')\nprint('Found GPU at: {}'.format(device_name))\nprint(tf.__version__)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"cf1a075d-5aca-4685-b2f3-c256ab316a9c","_cell_guid":"e1e8b860-2896-4e8d-a60e-fb7c81510d20","trusted":true},"cell_type":"code","source":"base_cnn = auto_encoder.fit_generator(\n    train_generator,\n    steps_per_epoch=len(train_generator),\n    validation_data=val_generator,\n    validation_steps=64,\n    #class_weight = class_weights,\n    epochs=5,\n    #callbacks = [clr],\n    use_multiprocessing=True,\n    #workers=workers,\n    verbose=1)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a78b67e6-2e85-4453-8594-bcd4bb10ff8a","_cell_guid":"40a6ede9-c804-4db2-9653-9b7f4414010d","trusted":true},"cell_type":"markdown","source":"**If you found this useful, an upvote would be much appreciated.**","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"auto_encoder.save_weights('Auto_Encoder.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"encoder.save_weights('Encoder.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"decoder.save_weights('Decoder.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from IPython.display import FileLink\nFileLink(r'Encoder.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"FileLink(r'Decoder.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"FileLink(r'Auto_Encoder.h5')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5dd372b4-b29d-4ac6-b5cb-f7762950fb86","_cell_guid":"21f4936e-bd3f-43b3-a310-e3bcb59470b4","trusted":true},"cell_type":"markdown","source":"**Image Credits:**\n\n[Stackoverflow](https://stackoverflow.com/questions/58200107/stuck-understanding-resnets-identity-block-and-convolutional-blocks)\n\n\n[Medium](https://miro.medium.com/max/2792/1*hEU7S-EiVqcmtAlj6kgfRA.png)","execution_count":null}],"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":4,"nbformat_minor":4}