{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport pandas as pd\nimport tensorflow as tf\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2021-08-21T16:01:26.860498Z","iopub.execute_input":"2021-08-21T16:01:26.860878Z","iopub.status.idle":"2021-08-21T16:01:31.421679Z","shell.execute_reply.started":"2021-08-21T16:01:26.860799Z","shell.execute_reply":"2021-08-21T16:01:31.420783Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Introduction\nIn this notebook we will disccus\n* How to load images and do data augmentation with Keras\n* How to use pretrained models and fine-tune them","metadata":{}},{"cell_type":"markdown","source":"# Training Data","metadata":{}},{"cell_type":"code","source":"base_dir = '../input/state-farm-distracted-driver-detection'\ntrain_dir = os.path.join(base_dir, \"imgs/train\")\ntest_dir = os.path.join(base_dir, \"imgs\")\ndata = pd.read_csv(os.path.join(base_dir, 'driver_imgs_list.csv'))\ndata.head()","metadata":{"execution":{"iopub.status.busy":"2021-08-21T16:01:31.425090Z","iopub.execute_input":"2021-08-21T16:01:31.425360Z","iopub.status.idle":"2021-08-21T16:01:31.480678Z","shell.execute_reply.started":"2021-08-21T16:01:31.425331Z","shell.execute_reply":"2021-08-21T16:01:31.479643Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_samples = data.sample(12)\n\nfig, axs = plt.subplots(3, 4, figsize=(17, 12))\nfor i, ax in enumerate(axs.flatten()):\n    ax.imshow(plt.imread(os.path.join(train_dir, data_samples['classname'].iloc[i], data_samples['img'].iloc[i])))\n    ax.axis(False)\n    ax.set_title(data_samples['classname'].iloc[i])","metadata":{"execution":{"iopub.status.busy":"2021-08-21T16:01:31.483697Z","iopub.execute_input":"2021-08-21T16:01:31.483975Z","iopub.status.idle":"2021-08-21T16:01:32.787007Z","shell.execute_reply.started":"2021-08-21T16:01:31.483949Z","shell.execute_reply":"2021-08-21T16:01:32.786105Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"args ={\n    \"kind\":\"bar\",\n    \"title\":\"Classes Count\",\n    \"figsize\": (7,5)\n}\n\nclasses_count = data['classname'].value_counts() \nfig = classes_count.plot(**args)","metadata":{"execution":{"iopub.status.busy":"2021-08-21T16:01:32.788305Z","iopub.execute_input":"2021-08-21T16:01:32.788618Z","iopub.status.idle":"2021-08-21T16:01:32.964906Z","shell.execute_reply.started":"2021-08-21T16:01:32.788587Z","shell.execute_reply":"2021-08-21T16:01:32.964069Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Average images per class = {:.3f} with std = {:.3f}\".format(classes_count.mean(),\n                                                          classes_count.std()))","metadata":{"execution":{"iopub.status.busy":"2021-08-21T16:01:32.966176Z","iopub.execute_input":"2021-08-21T16:01:32.966543Z","iopub.status.idle":"2021-08-21T16:01:32.971867Z","shell.execute_reply.started":"2021-08-21T16:01:32.966504Z","shell.execute_reply":"2021-08-21T16:01:32.970887Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# constats\nval_ratio = 0.2\nIMG_SIZE = (224, 224)\nBATCH_SIZE = 32","metadata":{"execution":{"iopub.status.busy":"2021-08-21T16:01:32.973211Z","iopub.execute_input":"2021-08-21T16:01:32.973582Z","iopub.status.idle":"2021-08-21T16:01:32.983013Z","shell.execute_reply.started":"2021-08-21T16:01:32.973547Z","shell.execute_reply":"2021-08-21T16:01:32.982160Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## ImageDataGenerator\nTensorflow through keras API provides a very easy way to load images and do real-time data augmentation check the [documentation](https://www.tensorflow.org/api_docs/python/tf/keras/preprocessing/image/ImageDataGenerator) for more details\n","metadata":{}},{"cell_type":"code","source":"train_gen = tf.keras.preprocessing.image.ImageDataGenerator(\n    validation_split = val_ratio\n)\n\ntest_gen = tf.keras.preprocessing.image.ImageDataGenerator()","metadata":{"execution":{"iopub.status.busy":"2021-08-21T16:01:33.061487Z","iopub.execute_input":"2021-08-21T16:01:33.061748Z","iopub.status.idle":"2021-08-21T16:01:33.066347Z","shell.execute_reply.started":"2021-08-21T16:01:33.061724Z","shell.execute_reply":"2021-08-21T16:01:33.065157Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data = train_gen.flow_from_directory(\n    train_dir,\n    target_size = IMG_SIZE,\n    batch_size = BATCH_SIZE,\n    seed = 42,\n    subset = \"training\"\n)\n\nval_data = train_gen.flow_from_directory(\n    train_dir,\n    target_size = IMG_SIZE,\n    batch_size = BATCH_SIZE,\n    seed = 42,\n    subset = \"validation\"\n)","metadata":{"execution":{"iopub.status.busy":"2021-08-21T16:01:33.501117Z","iopub.execute_input":"2021-08-21T16:01:33.501439Z","iopub.status.idle":"2021-08-21T16:01:46.786396Z","shell.execute_reply.started":"2021-08-21T16:01:33.501406Z","shell.execute_reply":"2021-08-21T16:01:46.785122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Modeling\n[keras Applications](https://keras.io/api/applications/) API provides a set of deep learning models that can be used for prediction, feature extraction, and fine-tuning.\nIn this notebook we will use the EfficientNet model which is devolped by Mingxing Tan and Quoc V. Le of Google Research, Brain team. they proposed a new scaling method that uniformly scales all dimensions of depth, width and resolution of a CNN network using a simple compound coefficient.\n\nThey developed a new baseline network using neural architecture search (NAS). the main building block for the network is the __MBConv__ which was introduced in MobileNetV2 architecture  \n\n<img src=\"https://amaarora.github.io/images/mbconv.png\" style = \"display: block;\n  margin-left: auto; margin-right: auto; width: 300;\"/>\n  \n <div align=\"center\"><i>MBConv Layer</i></div>\n <br/>\n  \n#### The baseline network is called EfficientNet-B0 and the network is scalled to B7\n\n<img src=\"https://1.bp.blogspot.com/-DjZT_TLYZok/XO3BYqpxCJI/AAAAAAAAEKM/BvV53klXaTUuQHCkOXZZGywRMdU9v9T_wCLcBGAs/s1600/image2.png\" style = \"display: block;\n  margin-left: auto; margin-right: auto; width: 300;\"/>\n  \n <div align=\"center\"><i>The Baseline Architecture</i></div>\n <br/>\n \n <img src=\"https://1.bp.blogspot.com/-oNSfIOzO8ko/XO3BtHnUx0I/AAAAAAAAEKk/rJ2tHovGkzsyZnCbwVad-Q3ZBnwQmCFsgCEwYBhgL/s1600/image3.png\" width=\"500\" style = \"display: block;\n  margin-left: auto; margin-right: auto; width: 500;\"/>\n  \n <div align=\"center\"><i>EfficientNet Performance</i></div>\n <br/>\n  \n**Additional Resources**\n\nMBConv Block: https://paperswithcode.com/method/inverted-residual-block\n\nGreat Article About EfficientNet: https://amaarora.github.io/2020/08/13/efficientnet.html\n\nEfficientNet Orginal Paper: [Rethinking Model Scaling for Convolutional Neural Networks](https://arxiv.org/pdf/1905.11946.pdf)\n\nGoogle AI Blog Post: https://ai.googleblog.com/2019/05/efficientnet-improving-accuracy-and.html","metadata":{}},{"cell_type":"code","source":"def build_model(num_class):\n    inputs = tf.keras.layers.Input(shape=(IMG_SIZE[0], IMG_SIZE[1], 3))\n    model = tf.keras.applications.efficientnet.EfficientNetB3(include_top=False, weights='imagenet', input_tensor=inputs)\n    \n    x = tf.keras.layers.GlobalAveragePooling2D()(model.output)\n    x = tf.keras.layers.BatchNormalization()(x)\n\n    x = tf.keras.layers.Dropout(0.2)(x)\n    outputs = tf.keras.layers.Dense(units=num_class, activation=tf.keras.activations.softmax)(x)\n    \n    model = tf.keras.Model(inputs, outputs)\n    model.compile(\n    optimizer=tf.optimizers.Adam(learning_rate=1e-4),\n    loss= tf.keras.losses.CategoricalCrossentropy(),\n    metrics=['accuracy','Recall'],\n    )\n    return model","metadata":{"execution":{"iopub.status.busy":"2021-08-21T16:01:46.787823Z","iopub.execute_input":"2021-08-21T16:01:46.788160Z","iopub.status.idle":"2021-08-21T16:01:46.796080Z","shell.execute_reply.started":"2021-08-21T16:01:46.788126Z","shell.execute_reply":"2021-08-21T16:01:46.795101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = build_model(10)\nmodel.summary()","metadata":{"scrolled":true,"_kg_hide-input":false,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-08-21T16:01:46.798094Z","iopub.execute_input":"2021-08-21T16:01:46.798566Z","iopub.status.idle":"2021-08-21T16:01:52.334729Z","shell.execute_reply.started":"2021-08-21T16:01:46.798532Z","shell.execute_reply":"2021-08-21T16:01:52.333917Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(train_data,epochs=3,validation_data=val_data)","metadata":{"execution":{"iopub.status.busy":"2021-08-21T16:01:52.336265Z","iopub.execute_input":"2021-08-21T16:01:52.336630Z","iopub.status.idle":"2021-08-21T16:15:24.943094Z","shell.execute_reply.started":"2021-08-21T16:01:52.336593Z","shell.execute_reply":"2021-08-21T16:15:24.942244Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save_weights('my_checkpoint')","metadata":{"execution":{"iopub.status.busy":"2021-08-21T16:15:24.945386Z","iopub.execute_input":"2021-08-21T16:15:24.945736Z","iopub.status.idle":"2021-08-21T16:15:25.839725Z","shell.execute_reply.started":"2021-08-21T16:15:24.945697Z","shell.execute_reply":"2021-08-21T16:15:25.838808Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Predictions","metadata":{}},{"cell_type":"code","source":"test_data = test_gen.flow_from_directory(\n    test_dir,\n    shuffle = False,\n    target_size = IMG_SIZE,\n    classes = ['test'],\n    batch_size = 32\n)","metadata":{"execution":{"iopub.status.busy":"2021-08-21T16:15:25.841992Z","iopub.execute_input":"2021-08-21T16:15:25.842261Z","iopub.status.idle":"2021-08-21T16:17:42.423212Z","shell.execute_reply.started":"2021-08-21T16:15:25.842224Z","shell.execute_reply":"2021-08-21T16:17:42.422290Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds = model.predict(test_data)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_imgs = os.path.join(base_dir, \"imgs/test\")\n\ntest_ids = sorted(os.listdir(test_imgs))\npred_df = pd.DataFrame(columns = ['img','c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9'])\nfor i in range(len(preds)):\n    pred_df.loc[i, 'img'] = test_ids[i]\n    pred_df.loc[i, 'c0':'c9'] = preds[i]\n    \npred_df.to_csv('predictions2.csv', index=False)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}