{"cells":[{"metadata":{},"cell_type":"markdown","source":"# A highly efficient tf.data input pipeline with EfficientNets\n"},{"metadata":{},"cell_type":"markdown","source":"In this notebook, I am going to create a tf.data input pipeline, which is very efficient if done correctly. It not only speeds up preprocessing but alsospeeds up actual training by a bit. \nThis notebook is a reference for me. So, i have made it as explanatory and easy to revise as possible. \nSo, sit tight,relax and enjoy the ride.\n"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"#Import required libraries\nimport tensorflow as tf\nimport os\nimport numpy as np\nimport pandas as pd\nimport cv2","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"As you may note, I have included a new dataset of TFRecords. Credits to [@DimitreOliveira](https://www.kaggle.com/dimitreoliveira). The following functions are inspired by his notebbok itself.\n\nFollowing auxilliary functions are optimized using @tf.function decorator. Thus, many operations are from TensorFlow library and not native python. "},{"metadata":{"trusted":true},"cell_type":"code","source":"#Declaring constants and hyperparameters\n\nclass Hyperparameters:\n    TFRECORDS_FORMAT={'image': tf.io.FixedLenFeature([], tf.string),\n                      'image_name': tf.io.FixedLenFeature([], tf.string),\n                      'target': tf.io.FixedLenFeature([], tf.int64)}\n    BATCH_SIZE=32\n    AUTOTUNE=tf.data.experimental.AUTOTUNE\n    HEIGHT=224\n    WIDTH=224\n    WIDTH_FACTOR=0.2\n    HEIGHT_FACTOR=0.2\n    FILL_MODE='reflect'\n    TRAINING=True","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Reading the TFRecords\n\nclass DataParser(Hyperparameters):\n    #All functions except tf\n    def __init__(self): #Take required hyperparameters\n        self.TFRECORDS_FORMAT=Hyperparameters.TFRECORDS_FORMAT\n        self.BATCH_SIZE=Hyperparameters.BATCH_SIZE\n        self.HEIGHT=Hyperparameters.HEIGHT\n        self.WIDTH=Hyperparameters.WIDTH\n     \n    @tf.function\n    def readTFRecs(self,dir_name): \n        #Read the TFRecords and make a Dataset iterator. \n        #Tensorflow has an object called tf.data.iterator which is created by calling iter() method\n        TFRecFiles=tf.constant(tf.io.gfile.listdir(dir_name))\n        TFRecFiles=tf.map_fn(lambda name:dir_name+'/'+name,TFRecFiles)\n        TFRecDataset=tf.data.TFRecordDataset(TFRecFiles)#.batch(self.BATCH_SIZE).prefetch(1)\n        #self.dataset_len=tf.data.experimental.cardinality(TFRecDataset).numpy()\n        Dataset = TFRecDataset.map(lambda example:tf.io.parse_example(example,self.TFRECORDS_FORMAT))\n        return Dataset\n    \n    @tf.function\n    def decode_image(self,entry):\n       return tf.image.decode_image(entry['image'],channels=3),entry['target'] #[batch_size,h,w,3]\n    \n    \n    #@tf.function\n    def makeDataset(self,TFRecDataset):\n        Dataset = TFRecDataset.map(lambda entry: self.decode_image(entry))\n        Dataset = Dataset.shuffle(3000)\n        #Dataset=Dataset.zip(TFRecDataset.map(lambda entry:entry['target']))\n        Dataset = Dataset.batch(self.BATCH_SIZE).prefetch(1)\n        return Dataset\n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dp=DataParser()\nTFRecDataset=dp.readTFRecs('../input/cassava-tfrecords-512x512')\nDataset=dp.makeDataset(TFRecDataset)\nDataset","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pretrained=tf.keras.applications.EfficientNetB3(include_top=False,input_shape=(224,224,3))\npretrained.trainable=False","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Building model\n\nmodel=tf.keras.Sequential()\nmodel.add(tf.keras.Input((512,512,3)))\n#Augmentation layers\nmodel.add(tf.keras.layers.experimental.preprocessing.Resizing(224,224))\nmodel.add(tf.keras.layers.experimental.preprocessing.Rescaling(1./255.))\nmodel.add(tf.keras.layers.experimental.preprocessing.RandomFlip())\nmodel.add(tf.keras.layers.experimental.preprocessing.RandomTranslation(0.2,0.2))\nmodel.add(tf.keras.layers.experimental.preprocessing.RandomRotation(0.2))\nmodel.add(tf.keras.layers.experimental.preprocessing.RandomZoom(0.2,0.2))\nmodel.add(pretrained)\n\n#Learning layers\n#model.add()\nmodel.compile(optimizer='Adagrad',\n              loss=tf.keras.losses.SparseCategoricalCrossentropy(),\n              metrics=[tf.keras.metrics.SparseCategoricalCrossentropy()])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"   \n#     #@tf.function\n#     def readTFRecs(self,dir_name): \n#         #Read the TFRecords and make a Dataset iterator. \n#         #Tensorflow has an object called tf.data.iterator which is created by calling iter() method\n#         TFRecFiles=tf.constant(tf.io.gfile.listdir(dir_name))\n#         TFRecFiles=tf.map_fn(lambda name:dir_name+'/'+name,TFRecFiles)\n#         TFRecDataset=tf.data.TFRecordDataset(TFRecFiles).batch(self.BATCH_SIZE).prefetch(1)\n#         self.dataset_len=tf.data.experimental.cardinality(TFRecDataset).numpy()\n#         return iter(TFRecDataset)\n\n   \n    \n#     @tf.function\n#     def decode_image(self,raw_image):\n#        return tf.image.decode_image(raw_image,channels=3) #[batch_size,h,w,3]\n\n#     @tf.function\n#     def preprocessBatch(self,batch):\n#         raw_imgs,labels=batch\n#         imgs=tf.map_fn(self.decode_image,raw_imgs,dtype=tf.uint8)\n#         return imgs,labels\n\n\n#     @tf.function\n#     def parseExampleBatch(self,DatasetIterator):\n#         #Take a single image from dataset and resize it to 224x224. \n#         #EfficientNet uses this size as input. \n#         example=next(DatasetIterator) #[batch_size,h,w,3]\n#         parsed_raw=tf.io.parse_example(example,self.TFRECORDS_FORMAT)\n#         preproccessedBatch=self.preprocessBatch((parsed_raw['image'],parsed_raw['target']))\n#         return preproccessedBatch\n    \n    \n#     #Works like a charm!! Returns imgs (32,512,512,3) and labels (32,) as (imgs,labels)\n\n# dp=DataParser()\n# Iterator=dp.readTFRecs('../input/cassava-tfrecords-512x512')\n# dp.parseExampleBatch(Iterator)","execution_count":null,"outputs":[]}],"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}