{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"from IPython.display import display, HTML\n\ndisplay(HTML(data=\"\"\"\n<style>\n    div#notebook-container    { width: 95%; }\n    div#menubar-container     { width: 65%; }\n    div#maintoolbar-container { width: 99%; }\n</style>\n\"\"\"))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#to use different versions\n!pip install efficientnet\n#!pip install --upgrade tensorflow-gpu\n#!pip install --upgrade efficientnet","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nimport json, codecs\nimport tensorflow as tf\nfrom efficientnet.keras import EfficientNetB0\nfrom kaggle_datasets import KaggleDatasets\nprint(tf.__version__)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# TPU or GPU Detection","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Detect hardware, return appropriate distribution strategy\ntry:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()  # TPU detection. No parameters necessary if TPU_NAME environment variable is set. On Kaggle this is always the case.\n    print('Running on TPU ', tpu.master())\nexcept ValueError:\n    tpu = None\n\nif tpu:\n    tf.config.experimental_connect_to_cluster(tpu)\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    strategy = tf.distribute.experimental.TPUStrategy(tpu)\nelse:\n    strategy = tf.distribute.get_strategy() # default distribution strategy in Tensorflow. Works on CPU and single GPU.\n\nprint(\"REPLICAS: \", strategy.num_replicas_in_sync)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Data Access","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"#name = !ls /kaggle/input\n#name","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#name = !ls /kaggle/input/\n#GCS_DS_PATH = KaggleDatasets().get_gcs_path('herbarium-2020-fgvc7') # you can list the bucket with \"!gsutil ls $GCS_DS_PATH\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for dirname,_,filenames in os.walk(\"../input/herbarium-2020-fgvc7\"):\n    for filename in filenames:\n        if filename.endswith('.jpg'):\n            break\n        print(os.path.join(dirname,filename))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"with codecs.open(\"../input/herbarium-2020-fgvc7/nybg2020/train/metadata.json\", 'r',\n                 encoding='utf-8', errors='ignore') as f:\n    train_meta = json.load(f)\n    \nwith codecs.open(\"../input/herbarium-2020-fgvc7/nybg2020/test/metadata.json\", 'r',\n                 encoding='utf-8', errors='ignore') as f:\n    test_meta = json.load(f)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_meta.keys()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = pd.DataFrame(train_meta['annotations'])\ntrain_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_cat = pd.DataFrame(train_meta['categories'])\ntrain_cat.columns = ['family', 'genus', 'category_id', 'category_name']\ntrain_cat","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_img = pd.DataFrame(train_meta['images'])\ntrain_img.columns = ['file_name', 'height', 'image_id', 'license', 'width']\ntrain_img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_reg = pd.DataFrame(train_meta['regions'])\ntrain_reg.columns = ['region_id', 'region_name']\ntrain_reg","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = train_df.merge(train_cat, on='category_id', how='outer')\ntrain_df = train_df.merge(train_img, on='image_id', how='outer')\ntrain_df = train_df.merge(train_reg, on='region_id', how='outer')\ntrain_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.info()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"na = train_df.file_name.isna()\nkeep = [x for x in range(train_df.shape[0]) if not na[x]]\ntrain_df = train_df.iloc[keep]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dtypes = ['int32', 'int32', 'int32', 'int32', 'object', 'object', 'object', 'object', 'int32', 'int32', 'int32', 'object']\nfor n, col in enumerate(train_df.columns):\n    train_df[col] = train_df[col].astype(dtypes[n])\nprint(train_df.info())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df = pd.DataFrame(test_meta['images'])\ntest_df.columns = ['file_name', 'height', 'image_id', 'license', 'width']\nprint(test_df.info())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"Total Unique Values for each columns:\")\nprint(\"{0:10s} \\t {1:10d}\".format('train_df', len(train_df)))\nfor col in train_df.columns:\n    print(\"{0:10s} \\t {1:10d}\".format(col, len(train_df[col].unique())))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"family = train_df[['family', 'genus', 'category_name']].groupby(['family', 'genus']).count()\ndisplay(family.describe())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.models import Model\nfrom keras.layers import Dense, Dropout, Conv2D, MaxPool2D, Flatten, BatchNormalization, Input, concatenate\nfrom keras.optimizers import Adam\nfrom keras.utils import plot_model\nfrom sklearn.model_selection import train_test_split as tts\n\n\n\ndef xavier(shape, dtype=None):\n    return np.random.rand(*shape)*np.sqrt(1/in_out_size)\n\n\n\ndef fg_model(shape,lr):\n    \n    actual_shape = shape\n    i = Input(actual_shape)\n    x = EfficientNetB0(weights='imagenet', include_top=False, input_shape=actual_shape, pooling='max')(i)\n    #x = Flatten()(x)\n    o1 = Dense(310, name=\"family\", activation='softmax')(x)\n    o2 = concatenate([x,o1])\n    o2 = Dense(3678, name=\"genus\", activation='softmax')(o2)\n    o3 = concatenate([x,o1,o2])\n    o3 = Dense(32094, name=\"category_id\", activation='softmax')(o3)\n    model = Model(inputs=i,outputs=[o1,o2,o3])\n    \n    model.layers[1].trainable = False\n    model.get_layer('genus').trainable = False\n    model.get_layer('category_id').trainable = False\n    \n    opt = Adam(lr=lr, amsgrad=True)\n    model.compile(optimizer=opt, loss=['sparse_categorical_crossentropy', \n                                   'sparse_categorical_crossentropy', \n                                   'sparse_categorical_crossentropy'],\n                 metrics=['accuracy'])\n    return model\n\n\n#plot_model(model, to_file='full_model_plot.png', show_shapes=True, show_layer_names=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.preprocessing.image import ImageDataGenerator\n\ntrain_datagen = ImageDataGenerator(featurewise_center=False,\n                                     featurewise_std_normalization=False,\n                                     rotation_range=180,\n                                     width_shift_range=0.1,\n                                     height_shift_range=0.1,\n                                     zoom_range=0.2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"m = train_df[['file_name', 'family', 'genus', 'category_id']]\nfam = m.family.unique().tolist()\nm.family = m.family.map(lambda x: fam.index(x))\ngen = m.genus.unique().tolist()\nm.genus = m.genus.map(lambda x: gen.index(x))\ndisplay(m)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train, verif = tts(m, test_size=0.2, shuffle=True, random_state=17)\ntrain = train[:80000]\nverif = verif[:20000]\nshape = (224,224, 3)\nepochs = 8\nbatch_size = 32\n\n#model = fg_model(shape, 0.007)\n#model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = fg_model((224,224,3), 0.007)\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Disable the last two output layers for training the Family\nfor layers in model.layers:\n    if layers.name == 'genus' or layers.name=='category_id':\n        layers.trainable = False","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Train Family for 2 epochs\nmodel.fit_generator(train_datagen.flow_from_dataframe(dataframe=train,\n                                                      directory='../input/herbarium-2020-fgvc7/nybg2020/train/',\n                                                      x_col=\"file_name\",\n                                                      y_col=[\"family\", \"genus\", \"category_id\"],\n                                                      target_size=(224,224),\n                                                      batch_size=batch_size,\n                                                      class_mode='multi_output'),\n                    validation_data=train_datagen.flow_from_dataframe(\n                        dataframe=verif,\n                        directory='../input/herbarium-2020-fgvc7/nybg2020/train/',\n                        x_col=\"file_name\",\n                        y_col=[\"family\", \"genus\", \"category_id\"],\n                        target_size=(224,224),\n                        batch_size=batch_size,\n                        class_mode='multi_output'),\n                    epochs=epochs,\n                    steps_per_epoch=len(train)//batch_size,\n                    validation_steps=len(verif)//batch_size,\n                    verbose=1,\n                    workers=8,\n                    use_multiprocessing=False)\n\nmodel.save_weights(\"weights.h5\")\nmodel.save(\"model.h5\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Reshuffle the inputs\ntrain, verif = tts(m, test_size=0.2, shuffle=True, random_state=17)\ntrain = train#[:500000]\nverif = verif#[:100000]\n#Make the Genus layer Trainable\nfor layers in model.layers:\n    if layers.name == 'genus':\n        layers.trainable = True\n        \n#Train Family and Genus for 2 epochs\nmodel.fit_generator(train_datagen.flow_from_dataframe(dataframe=train,\n                                                      directory='../input/herbarium-2020-fgvc7/nybg2020/train/',\n                                                      x_col=\"file_name\",\n                                                      y_col=[\"family\", \"genus\", \"category_id\"],\n                                                      target_size=(224,224),\n                                                      batch_size=batch_size,\n                                                      class_mode='multi_output'),\n                    validation_data=train_datagen.flow_from_dataframe(\n                        dataframe=verif,\n                        directory='../input/herbarium-2020-fgvc7/nybg2020/train/',\n                        x_col=\"file_name\",\n                        y_col=[\"family\", \"genus\", \"category_id\"],\n                        target_size=(224,224),\n                        batch_size=batch_size,\n                        class_mode='multi_output'),\n                    epochs=epochs,\n                    steps_per_epoch=len(train)//batch_size,\n                    validation_steps=len(verif)//batch_size,\n                    verbose=1,\n                    workers=4,\n                    use_multiprocessing=False)\n\nmodel.save_weights(\"weights.h5\")\nmodel.save(\"model.h5\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Reshuffle the inputs\ntrain, verif = tts(m, test_size=0.2, shuffle=True, random_state=17)\ntrain = train#[:500000]\nverif = verif#[:100000]\n\n#Make the category_id layer Trainable\nfor layers in model.layers:\n    if layers.name == 'category_id':\n        layers.trainable = True\n        \n#Train them all for 2 epochs\nmodel.fit_generator(train_datagen.flow_from_dataframe(dataframe=train,\n                                                      directory='../input/herbarium-2020-fgvc7/nybg2020/train/',\n                                                      x_col=\"file_name\",\n                                                      y_col=[\"family\", \"genus\", \"category_id\"],\n                                                      target_size=(224,224),\n                                                      batch_size=batch_size,\n                                                      class_mode='multi_output'),\n                    validation_data=train_datagen.flow_from_dataframe(\n                        dataframe=verif,\n                        directory='../input/herbarium-2020-fgvc7/nybg2020/train/',\n                        x_col=\"file_name\",\n                        y_col=[\"family\", \"genus\", \"category_id\"],\n                        target_size=(224,224),\n                        batch_size=batch_size,\n                        class_mode='multi_output'),\n                    epochs=epochs,\n                    steps_per_epoch=len(train)//batch_size,\n                    validation_steps=len(verif)//batch_size,\n                    verbose=1,\n                    workers=4,\n                    use_multiprocessing=False)\nmodel.save_weights(\"weights.h5\")\nmodel.save(\"model.h5\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}