{"cells":[{"metadata":{},"cell_type":"markdown","source":"### 0. Library Import","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"## installation\n! pip install efficientnet","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"#101\nimport os\nimport sys\nimport pandas as pd\nimport numpy as np\nfrom skimage.io import imread\n\n#plot\nimport matplotlib.pyplot as plt\nfrom PIL import Image, ImageDraw\n\n#files\nfrom keras.preprocessing import image\nimport zipfile\nfrom sklearn.model_selection import train_test_split\n\n#macine learning\nimport tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nimport tensorflow_hub as hub\n\n#model evaluation\nfrom sklearn.metrics import precision_recall_curve, auc, f1_score,accuracy_score, precision_score, recall_score\nfrom keras.callbacks import Callback\n\n##pre-trained model\n#efficientNet\nfrom efficientnet.tfkeras import EfficientNetB0\nfrom efficientnet.tfkeras import center_crop_and_resize, preprocess_input","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tf.__version__","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### 1. Data Import","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# check data availability\nPATH=\"../input/iwildcam-2019-fgvc6/\"\nos.listdir(PATH)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# class\nclasses_wild = {0: 'empty', 1: 'deer', 2: 'moose', 3: 'squirrel', 4: 'rodent', 5: 'small_mammal', \\\n                6: 'elk', 7: 'pronghorn_antelope', 8: 'rabbit', 9: 'bighorn_sheep', 10: 'fox', 11: 'coyote', \\\n                12: 'black_bear', 13: 'raccoon', 14: 'skunk', 15: 'wolf', 16: 'bobcat', 17: 'cat',\\\n                18: 'dog', 19: 'opossum', 20: 'bison', 21: 'mountain_goat', 22: 'mountain_lion'}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"path_to_zip = \"../input/iwildcam-2019-fgvc6/train_images.zip\"\ndirectory_to_extract=\"../output/kaggle/working/train_images\"\n\nwith zipfile.ZipFile(path_to_zip, 'r') as zip_ref:\n    zip_ref.extractall(directory_to_extract)\n\nzip_ref.close()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_image_files = list(os.listdir(os.path.join(directory_to_extract)))\nprint(\"Number of image files: train:{}\".format(len(train_image_files)))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### 2. Data Wrangling","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = pd.read_csv(os.path.join(PATH, 'train.csv'))\ntest_df = pd.read_csv(os.path.join(PATH, 'test.csv'))\n\ndisplay(train_df.head())\ndisplay(test_df.head())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"display(train_df.info())\ndisplay(test_df.info())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig = plt.figure(figsize=(25, 16))\nfor i,im_path in enumerate(train_image_files[:16]):\n    ax = fig.add_subplot(4, 4, i+1, xticks=[], yticks=[])\n    im = Image.open(os.path.join(directory_to_extract,im_path))\n    im = im.resize((480,270))\n    plt.imshow(im)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### 3. Feature Engineering","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df['classes_wild'] = train_df['category_id'].apply(lambda cw: classes_wild[cw])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## dataset splitting\nx_train, x_test = train_test_split(train_df, test_size=0.2, random_state=42)\nx_train.shape, x_test.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_datagen = ImageDataGenerator(rescale = 1./255)\n\ntrain_datagen=ImageDataGenerator(rescale=1./255, \n                                 validation_split=0.25,\n                                 #horizontal_flip = True,    \n                                 #zoom_range = 0.3,\n                                 #width_shift_range = 0.3,\n                                 #height_shift_range=0.3\n                                )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_generator=train_datagen.flow_from_dataframe(\n                    dataframe=x_train,\n                    directory=\"../output/kaggle/working/train_images/\",\n                    x_col=\"file_name\",\n                    y_col=\"classes_wild\",\n                    subset=\"training\",\n                    batch_size=64,\n                    seed=424,\n                    shuffle=True,\n                    class_mode=\"categorical\",\n                    target_size=(128, 128))\n\nvalid_generator=train_datagen.flow_from_dataframe(\n                    dataframe=x_train,\n                    directory=\"../output/kaggle/working/train_images/\",\n                    x_col=\"file_name\",\n                    y_col=\"classes_wild\",\n                    subset=\"validation\",\n                    batch_size=64,\n                    seed=424,\n                    shuffle=True,\n                    class_mode=\"categorical\",\n                    target_size=(128, 128))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(train_generator.class_indices)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(valid_generator.class_indices)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### 4. Modeling","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"num_classes = train_df['classes_wild'].nunique()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"##### 4.1. EfficientNet","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"pre_trained_model = EfficientNetB0(weights=\"imagenet\", include_top=False, input_shape=(128,128,3))\n\nfor layer in pre_trained_model.layers:\n    layer.trainable = False\n    \npre_trained_model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# tuning on pre-trained model\neffnet_model = tf.keras.models.Sequential()\neffnet_model.add(pre_trained_model)\neffnet_model.add(tf.keras.layers.GlobalAveragePooling2D())    \neffnet_model.add(tf.keras.layers.Dense(num_classes, activation=\"softmax\") )\neffnet_model.summary()\n\nopt = tf.keras.optimizers.Adam(lr=0.005, decay=1e-6)\neffnet_model.compile(optimizer = opt, \n              loss = 'categorical_crossentropy', \n              metrics = ['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"early = tf.keras.callbacks.EarlyStopping(monitor='val_loss', min_delta=0, patience=3, verbose=1, mode='auto')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = effnet_model.fit(\n            train_generator,\n            validation_data = valid_generator,\n            steps_per_epoch = 100,\n            epochs = 20,\n            batch_size=64,\n            validation_steps = 50,\n            callbacks = [early]\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def display_training_curves(training, validation, title, subplot):\n    if subplot%10==1: # set up the subplots on the first call\n        plt.subplots(figsize=(10,10), facecolor='#F0F0F0')\n        plt.tight_layout()\n    ax = plt.subplot(subplot)\n    ax.set_facecolor('#F8F8F8')\n    ax.plot(training)\n    ax.plot(validation)\n    ax.set_title('model '+ title)\n    ax.set_ylabel(title)\n    #ax.set_ylim(0.28,1.05)\n    ax.set_xlabel('epoch')\n    ax.legend(['train', 'valid.'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"display_training_curves(history.history['loss'], history.history['val_loss'], 'loss', 211)\ndisplay_training_curves(history.history['accuracy'], history.history['val_accuracy'], 'accuracy', 212)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Testing Dataset","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"test_generator = test_datagen.flow_from_dataframe(\n                    dataframe=x_test,\n                    directory=\"../output/kaggle/working/train_images/\",\n                    x_col=\"file_name\",\n                    y_col=\"classes_wild\",\n                    batch_size=64,\n                    seed=424,\n                    shuffle=True,\n                    class_mode=\"categorical\",\n                    target_size=(128,128))\n\ntest_loss, test_acc =effnet_model.evaluate_generator(test_generator, steps=32)\nprint('test_loss_effnet: {} and test_acc_effnet: {} '.format(test_loss, test_acc))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# # effnet\nconverter = tf.lite.TFLiteConverter.from_keras_model(effnet_model)\nconverter.experimental_new_converter = True\nconverter.optimizations = [tf.lite.Optimize.DEFAULT]\neffnet_tflite_model = converter.convert()\n\n\nmodel_name = \"effnet_tflite_model_b0\"\nopen(f\"{model_name}.tflite\" , \"wb\").write(effnet_tflite_model)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Unfreeze Layers Block7","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow.keras.utils import plot_model\nplot_model(pre_trained_model, to_file='pretrained_model.png', show_shapes=True)\nfrom IPython.display import Image\nImage(filename='pretrained_model.png') ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for layer in pre_trained_model.layers:\n    print(layer.name)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pre_trained_model.trainable = True\n\nset_trainable = False\nfor layer in pre_trained_model.layers:\n    if layer.name == 'block7a_expand_conv':\n        set_trainable = True\n    if set_trainable:\n        layer.trainable = True\n    else:\n        layer.trainable = False","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"effnet_model.compile(optimizer = opt, \n              loss = 'categorical_crossentropy', \n              metrics = ['accuracy'])\n\nhistory = effnet_model.fit(\n            train_generator,\n            validation_data = valid_generator,\n            steps_per_epoch = 100,\n            epochs = 20,\n            batch_size=64,\n            validation_steps = 50,\n            callbacks = [early]\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"effnet_model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"display_training_curves(history.history['loss'], history.history['val_loss'], 'loss', 211)\ndisplay_training_curves(history.history['accuracy'], history.history['val_accuracy'], 'accuracy', 212)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_loss, test_acc =effnet_model.evaluate_generator(test_generator, steps=32)\nprint('test_loss_effnet: {} and test_acc_effnet: {} '.format(test_loss, test_acc))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# # effnet\nconverter = tf.lite.TFLiteConverter.from_keras_model(effnet_model)\nconverter.experimental_new_converter = True\nconverter.optimizations = [tf.lite.Optimize.DEFAULT]\neffnet_tflite_model = converter.convert()\n\n\nmodel_name = \"effnet_tflite_model_b0\"\nopen(f\"{model_name}.tflite\" , \"wb\").write(effnet_tflite_model)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Unfreeze: block6c_add","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"pre_trained_model.trainable = True\n\nset_trainable = False\nfor layer in pre_trained_model.layers:\n    if layer.name == 'block6c_add':\n        set_trainable = True\n    if set_trainable:\n        layer.trainable = True\n    else:\n        layer.trainable = False","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"effnet_model.compile(optimizer = opt, \n              loss = 'categorical_crossentropy', \n              metrics = ['accuracy'])\n\nhistory = effnet_model.fit(\n            train_generator,\n            validation_data = valid_generator,\n            steps_per_epoch = 100,\n            epochs = 20,\n            batch_size=64,\n            validation_steps = 50,\n            callbacks = [early]\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"effnet_model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"display_training_curves(history.history['loss'], history.history['val_loss'], 'loss', 211)\ndisplay_training_curves(history.history['accuracy'], history.history['val_accuracy'], 'accuracy', 212)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_loss, test_acc =effnet_model.evaluate_generator(test_generator, steps=32)\nprint('test_loss_effnet: {} and test_acc_effnet: {} '.format(test_loss, test_acc))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# # effnet\nconverter = tf.lite.TFLiteConverter.from_keras_model(effnet_model)\nconverter.experimental_new_converter = True\nconverter.optimizations = [tf.lite.Optimize.DEFAULT]\neffnet_tflite_model = converter.convert()\n\n\nmodel_name = \"effnet_tflite_model_b2\"\nopen(f\"{model_name}.tflite\" , \"wb\").write(effnet_tflite_model)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Unfreeze: block6a_expand_conv","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"pre_trained_model.trainable = True\n\nset_trainable = False\nfor layer in pre_trained_model.layers:\n    if layer.name == 'block6a_expand_conv':\n        set_trainable = True\n    if set_trainable:\n        layer.trainable = True\n    else:\n        layer.trainable = False","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"effnet_model.compile(optimizer = opt, \n              loss = 'categorical_crossentropy', \n              metrics = ['accuracy'])\n\nhistory = effnet_model.fit(\n            train_generator,\n            validation_data = valid_generator,\n            steps_per_epoch = 100,\n            epochs = 20,\n            batch_size=64,\n            validation_steps = 50,\n            callbacks = [early]\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"display_training_curves(history.history['loss'], history.history['val_loss'], 'loss', 211)\ndisplay_training_curves(history.history['accuracy'], history.history['val_accuracy'], 'accuracy', 212)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"effnet_model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_loss, test_acc =effnet_model.evaluate_generator(test_generator, steps=32)\nprint('test_loss_effnet: {} and test_acc_effnet: {} '.format(test_loss, test_acc))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# # effnet\nconverter = tf.lite.TFLiteConverter.from_keras_model(effnet_model)\nconverter.experimental_new_converter = True\nconverter.optimizations = [tf.lite.Optimize.DEFAULT]\neffnet_tflite_model = converter.convert()\n\n\nmodel_name = \"effnet_tflite_model_b3\"\nopen(f\"{model_name}.tflite\" , \"wb\").write(effnet_tflite_model)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#effnet_TL_6c is equal to effnet_tflite_model_b3\neffnet_model.save('effnet_TL_6c')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}