{"cells":[{"metadata":{},"cell_type":"markdown","source":"**Simple example of transfer learning from pretrained model using Keras.**\n* Loss: Focal loss\n* Metrics: f2_score"},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"import os\nimport cv2\nimport matplotlib.pyplot as plt\nimport pandas as pd\nimport numpy as np\nimport json\nfrom keras.models import Sequential, Model\nfrom keras.layers import Dense, Flatten, Activation, Dropout, GlobalAveragePooling2D\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras import optimizers, applications\nfrom keras.callbacks import ModelCheckpoint, LearningRateScheduler, TensorBoard, EarlyStopping\nfrom keras import backend as K ","execution_count":1,"outputs":[{"output_type":"stream","text":"Using TensorFlow backend.\n","name":"stderr"}]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = pd.read_csv(\"../input/imet-2019-fgvc6/train.csv\")\ntrain_df[\"attribute_ids\"]=train_df[\"attribute_ids\"].apply(lambda x:x.split(\" \"))\ntrain_df[\"id\"]=train_df[\"id\"].apply(lambda x:x+\".png\")\ntrain_df.head()","execution_count":2,"outputs":[{"output_type":"execute_result","execution_count":2,"data":{"text/plain":"                     id              attribute_ids\n0  1000483014d91860.png            [147, 616, 813]\n1  1000fe2e667721fe.png        [51, 616, 734, 813]\n2  1001614cb89646ee.png                      [776]\n3  10041eb49b297c08.png  [51, 671, 698, 813, 1092]\n4  100501c227f8beea.png  [13, 404, 492, 903, 1093]","text/html":"<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>id</th>\n      <th>attribute_ids</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>1000483014d91860.png</td>\n      <td>[147, 616, 813]</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>1000fe2e667721fe.png</td>\n      <td>[51, 616, 734, 813]</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>1001614cb89646ee.png</td>\n      <td>[776]</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>10041eb49b297c08.png</td>\n      <td>[51, 671, 698, 813, 1092]</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>100501c227f8beea.png</td>\n      <td>[13, 404, 492, 903, 1093]</td>\n    </tr>\n  </tbody>\n</table>\n</div>"},"metadata":{}}]},{"metadata":{"trusted":true},"cell_type":"code","source":"label_df = pd.read_csv(\"../input/imet-2019-fgvc6/labels.csv\")\nprint(label_df.shape)\nlabel_df.head()","execution_count":3,"outputs":[{"output_type":"stream","text":"(1103, 2)\n","name":"stdout"},{"output_type":"execute_result","execution_count":3,"data":{"text/plain":"   attribute_id          attribute_name\n0             0        culture::abruzzi\n1             1     culture::achaemenid\n2             2         culture::aegean\n3             3         culture::afghan\n4             4  culture::after british","text/html":"<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>attribute_id</th>\n      <th>attribute_name</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>0</td>\n      <td>culture::abruzzi</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>1</td>\n      <td>culture::achaemenid</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>2</td>\n      <td>culture::aegean</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>3</td>\n      <td>culture::afghan</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>4</td>\n      <td>culture::after british</td>\n    </tr>\n  </tbody>\n</table>\n</div>"},"metadata":{}}]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Example of images with tags\n\ni = 1\nplt.figure(figsize=[30,30])\nfor img_name in os.listdir(\"../input/imet-2019-fgvc6/train/\")[5:10]:   \n    img = cv2.imread(\"../input/imet-2019-fgvc6/train/%s\" % img_name)[...,[2, 1, 0]]\n    plt.subplot(5, 1, i)\n    plt.imshow(img)\n    ids = train_df[train_df[\"id\"] == img_name][\"attribute_ids\"]\n    title_val = []\n    for tag_id in ids.values[0]:\n        att_name = label_df[label_df['attribute_id'].astype(str) == tag_id]['attribute_name'].values[0]\n        title_val.append(att_name)\n    plt.title(title_val)\n    i += 1\n    \nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"nb_classes = 1103\nbatch_size = 300\nimg_size = 75\nnb_epochs = 25","execution_count":4,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"lbls = list(map(str, range(nb_classes)))","execution_count":5,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\n\ntrain_datagen=ImageDataGenerator(\n    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    )\n\ntrain_generator=train_datagen.flow_from_dataframe(\n    dataframe=train_df,\n    directory=\"../input/imet-2019-fgvc6/train\",\n    x_col=\"id\",\n    y_col=\"attribute_ids\",\n    batch_size=batch_size,\n    shuffle=True,\n    class_mode=\"categorical\",\n    classes=lbls,\n    target_size=(img_size,img_size),\n    subset='training')\n\nvalid_generator=train_datagen.flow_from_dataframe(\n    dataframe=train_df,\n    directory=\"../input/imet-2019-fgvc6/train\",\n    x_col=\"id\",\n    y_col=\"attribute_ids\",\n    batch_size=batch_size,\n    shuffle=True,\n    class_mode=\"categorical\",    \n    classes=lbls,\n    target_size=(img_size,img_size),\n    subset='validation')","execution_count":6,"outputs":[{"output_type":"stream","text":"Found 81928 images belonging to 1103 classes.\nFound 27309 images belonging to 1103 classes.\nCPU times: user 5.04 s, sys: 7.2 s, total: 12.2 s\nWall time: 1min 5s\n","name":"stdout"}]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Loss\n\ngamma = 2.0\nepsilon = K.epsilon()\ndef focal_loss(y_true, y_pred):\n    pt = y_pred * y_true + (1-y_pred) * (1-y_true)\n    pt = K.clip(pt, epsilon, 1-epsilon)\n    CE = -K.log(pt)\n    FL = K.pow(1-pt, gamma) * CE\n    loss = K.sum(FL, axis=1)\n    return loss","execution_count":7,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Metric\n\ndef f2_score(y_true, y_pred):\n    beta = 2\n    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)), axis=1)\n    predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)), axis=1)\n    possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)), axis=1)\n    \n    precision = true_positives / (predicted_positives + K.epsilon())\n    recall = true_positives / (possible_positives + K.epsilon())\n    \n    return K.mean(((1+beta**2)*precision*recall) / ((beta**2)*precision+recall+K.epsilon()))","execution_count":8,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = applications.InceptionResNetV2(weights=None, \n                          include_top=False, \n                          input_shape=(img_size, img_size, 3))\nmodel.load_weights('../input/inceptionresnetv2/inception_resnet_v2_weights_tf_dim_ordering_tf_kernels_notop.h5')","execution_count":9,"outputs":[{"output_type":"stream","text":"WARNING:tensorflow:From /opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/op_def_library.py:263: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.\nInstructions for updating:\nColocations handled automatically by placer.\n","name":"stdout"}]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.trainable = False","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Freeze some layers\n# for layer in model.layers[:-4]:\n#     layer.trainable = False","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"#Adding custom layers \nx = model.output\nx = Flatten()(x)\nx = Dense(1024, activation=\"relu\")(x)\nx = Dropout(0.5)(x)\npredictions = Dense(nb_classes, activation=\"softmax\")(x)\nmodel_final = Model(input = model.input, output = predictions)\n\nmodel_final.compile(optimizers.rmsprop(lr=0.001, decay=1e-6),loss=focal_loss,metrics=[f2_score])","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-output":true,"trusted":true,"collapsed":true},"cell_type":"code","source":"# model_final.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Callbacks\n\ncheckpoint = ModelCheckpoint(\"model_1.h5\", monitor='val_loss', verbose=1, save_best_only=True, save_weights_only=False, mode='auto', period=1)\nearly = EarlyStopping(monitor='val_loss', min_delta=0, patience=5, verbose=1, mode='auto')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\nhistory = model_final.fit_generator(generator=train_generator,                   \n                                    steps_per_epoch=500,\n                                    validation_data=valid_generator,                    \n                                    validation_steps=200,\n                                    epochs=nb_epochs,\n                                    callbacks = [checkpoint, early],\n                                    max_queue_size=16,\n                                    workers=2,\n                                    use_multiprocessing=True,\n                                    verbose=0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"with open('history.json', 'w') as f:\n    json.dump(history.history, f)\n\nhistory_df = pd.DataFrame(history.history)\nhistory_df[['loss', 'val_loss']].plot()\nhistory_df[['f2_score', 'val_f2_score']].plot()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sam_sub_df = pd.read_csv('../input/imet-2019-fgvc6/sample_submission.csv')\nsam_sub_df[\"id\"]=sam_sub_df[\"id\"].apply(lambda x:x+\".png\")\nprint(sam_sub_df.shape)\nsam_sub_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\ntest_datagen = ImageDataGenerator(rescale=1./255)\ntest_generator = test_datagen.flow_from_dataframe(  \n        dataframe=sam_sub_df,\n        directory = \"../input/imet-2019-fgvc6/test\",    \n        x_col=\"id\",\n        target_size = (img_size,img_size),\n        batch_size = 1,\n        shuffle = False,\n        class_mode = None\n        )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\ntest_generator.reset()\npredict = model_final.predict_generator(test_generator, steps = len(test_generator.filenames))","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"len(predict)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\nimport operator\npredicted_class_indices_3=[]\nfor i in range(len(predict)):         \n    d = {}\n    for index, value in enumerate(predict[i]):               \n        if value > 0.03:            \n            d[index] = value \n    sorted_d = sorted(d.items(), key=operator.itemgetter(1), reverse=True)\n    \n    # Take only first 10 items\n    predicted_class_indices_3.append([i[0] for i in sorted_d[:10]])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\npredictions_3=[]\n\nfor i in range(len(predicted_class_indices_3)):\n    labels = (train_generator.class_indices)\n    labels = dict((v,k) for k,v in labels.items())\n    predictions = [labels[k] for k in predicted_class_indices_3[i]]\n    predictions_3.append(predictions)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predict_3 = []\nfor i in range(len(predictions_3)):\n    str3 = \" \".join(predictions_3[i])\n    predict_3.append(str3)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"filenames=test_generator.filenames\nresults=pd.DataFrame({\"id\":filenames,\n                      \"attribute_ids\":predict_3})\nresults['id'] = results['id'].map(lambda x: str(x)[:-4])\nresults.to_csv(\"submission.csv\",index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results.head()","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}