{"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":"markdown","source":"## Import Libraries","metadata":{"id":"MW6l9tA8GPh4"}},{"cell_type":"code","source":"!pip -q install attrdict","metadata":{"execution":{"iopub.status.busy":"2021-08-27T17:20:07.848299Z","iopub.execute_input":"2021-08-27T17:20:07.848706Z","iopub.status.idle":"2021-08-27T17:20:15.718550Z","shell.execute_reply.started":"2021-08-27T17:20:07.848619Z","shell.execute_reply":"2021-08-27T17:20:15.717610Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nfrom glob import glob\nfrom itertools import chain\nimport cv2\nimport random\nfrom tqdm.notebook import tqdm\nimport time\n\nfrom attrdict import AttrDict\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.preprocessing import label_binarize\nfrom sklearn.metrics import accuracy_score, mean_absolute_error, mean_squared_error, roc_auc_score\nfrom sklearn.model_selection import train_test_split\n\nimport tensorflow as tf\nimport tensorflow.keras.backend as K\nfrom tensorflow.keras.layers import Activation, Conv2D, Dense\nfrom tensorflow.keras.layers import Flatten, Input, Layer, MaxPooling2D\nfrom tensorflow.keras.models import Model","metadata":{"id":"iiSvkJJQGRDe","execution":{"iopub.status.busy":"2021-08-27T17:20:15.721626Z","iopub.execute_input":"2021-08-27T17:20:15.721988Z","iopub.status.idle":"2021-08-27T17:20:21.111249Z","shell.execute_reply.started":"2021-08-27T17:20:15.721948Z","shell.execute_reply":"2021-08-27T17:20:21.110364Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Constants","metadata":{"id":"Vklpx80PFn2x"}},{"cell_type":"code","source":"config = dict(SEED = 42,\n              IMG_HEIGHT = 250,\n              IMG_WIDTH = 500,\n              EPOCHS = 5,\n              BATCH_SIZE = 16,\n              MAX_HOURS = 80,\n              LR = 0.0001)\nconfig = AttrDict(config)","metadata":{"id":"ec1i3e4WFmW8","execution":{"iopub.status.busy":"2021-08-27T17:21:30.812352Z","iopub.execute_input":"2021-08-27T17:21:30.812830Z","iopub.status.idle":"2021-08-27T17:21:30.820696Z","shell.execute_reply.started":"2021-08-27T17:21:30.812793Z","shell.execute_reply":"2021-08-27T17:21:30.819846Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Utility Functions","metadata":{"id":"3YbNYza0FsaJ"}},{"cell_type":"code","source":"def seed_everything(seed):\n    np.random.seed(seed)\n    random.seed(seed)\n    tf.random.set_seed(seed)\n    os.environ[\"PYTHONHASHSEED\"] = str(seed)","metadata":{"id":"Ryk0IPFkFphy","execution":{"iopub.status.busy":"2021-08-27T17:20:21.118957Z","iopub.execute_input":"2021-08-27T17:20:21.119461Z","iopub.status.idle":"2021-08-27T17:20:21.132463Z","shell.execute_reply.started":"2021-08-27T17:20:21.119413Z","shell.execute_reply":"2021-08-27T17:20:21.131652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_hist(hist):\n    fig, ax = plt.subplots(1, 2, figsize=(12, 6))\n    ax[0].plot(hist.history[\"loss\"])\n    ax[0].plot(hist.history[\"val_loss\"])\n    ax[0].set_title(\"Loss Plot\")\n    ax[0].set_ylabel(\"Loss\")\n    ax[0].set_xlabel(\"Epoch\")\n    ax[0].legend([\"Train\", \"Validation\"], loc=\"upper left\")\n\n    ax[1].plot(hist.history[\"accuracy\"])\n    ax[1].plot(hist.history[\"val_accuracy\"])\n    ax[1].set_title(\"Accuracy Plot\")\n    ax[1].set_ylabel(\"Accuracy\")\n    ax[1].set_xlabel(\"Epoch\")\n    ax[1].legend([\"Train\", \"Validation\"], loc=\"upper left\")    \n    plt.show()","metadata":{"id":"M3iF7dBvFpkt","execution":{"iopub.status.busy":"2021-08-27T17:20:21.133722Z","iopub.execute_input":"2021-08-27T17:20:21.134350Z","iopub.status.idle":"2021-08-27T17:20:21.142687Z","shell.execute_reply.started":"2021-08-27T17:20:21.134313Z","shell.execute_reply":"2021-08-27T17:20:21.141901Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_metrics(hist):\n    fig, ax = plt.subplots(1, 3, figsize=(15, 6))\n    ax[0].plot(hist.history[\"mean_absolute_error\"])\n    ax[0].plot(hist.history[\"val_mean_absolute_error\"])\n    ax[0].set_title(\"MAE Plot\")\n    ax[0].set_ylabel(\"MAE\")\n    ax[0].set_xlabel(\"Epoch\")\n    ax[0].legend([\"Train\", \"Validation\"], loc=\"upper left\")\n\n    ax[1].plot(hist.history[\"mean_squared_error\"])\n    ax[1].plot(hist.history[\"val_mean_squared_error\"])\n    ax[1].set_title(\"MSE Plot\")\n    ax[1].set_ylabel(\"MSE\")\n    ax[1].set_xlabel(\"Epoch\")\n    ax[1].legend([\"Train\", \"Validation\"], loc=\"upper left\")\n\n    ax[2].plot(hist.history[\"root_mean_squared_error\"])\n    ax[2].plot(hist.history[\"val_root_mean_squared_error\"])\n    ax[2].set_title(\"RMSE Plot\")\n    ax[2].set_ylabel(\"RMSE\")\n    ax[2].set_xlabel(\"Epoch\")\n    ax[2].legend([\"Train\", \"Validation\"], loc=\"upper left\")\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:00:14.679518Z","iopub.execute_input":"2021-08-27T19:00:14.679869Z","iopub.status.idle":"2021-08-27T19:00:14.693706Z","shell.execute_reply.started":"2021-08-27T19:00:14.679839Z","shell.execute_reply":"2021-08-27T19:00:14.691260Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_grid(dataset, h=3, w=3, title=\"\"):\n    f, ax = plt.subplots(h, w, figsize=(30, 30))\n    for images, labels in dataset.shuffle(100).take(1):\n        for i in range(h*w):\n            img = (images[i] * 255).numpy().astype(\"uint8\")\n            ax[i // h, i % w].imshow(img[:, :, 0])\n            ax[i // h, i % w].axis(\"off\")\n            ax[i // h, i % w].set_title(labels[i].numpy(), fontdict={\"fontsize\": 20})\n    plt.tight_layout()\n    f.suptitle(title, fontsize=\"large\", fontweight=\"extra bold\")\n    plt.show()","metadata":{"id":"isKRHpxlFmhQ","execution":{"iopub.status.busy":"2021-08-27T17:20:21.143810Z","iopub.execute_input":"2021-08-27T17:20:21.144280Z","iopub.status.idle":"2021-08-27T17:20:21.152555Z","shell.execute_reply.started":"2021-08-27T17:20:21.144244Z","shell.execute_reply":"2021-08-27T17:20:21.151850Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_roc_auc_score(y_true, y_pred):\n    classes = np.unique(np.array(y_true))\n    y_true = label_binarize(y_true, classes=classes)\n    y_pred = label_binarize(y_pred, classes=classes)\n    print(y_true.shape ,y_pred.shape)\n    return roc_auc_score(y_true, y_pred, average=\"macro\", multi_class=\"ovr\")","metadata":{"execution":{"iopub.status.busy":"2021-08-27T17:20:21.153617Z","iopub.execute_input":"2021-08-27T17:20:21.153995Z","iopub.status.idle":"2021-08-27T17:20:21.163410Z","shell.execute_reply.started":"2021-08-27T17:20:21.153959Z","shell.execute_reply":"2021-08-27T17:20:21.162622Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def print_metrics(stage, y_true, y_pred):\n    auc = get_roc_auc_score(y_true, y_pred)\n    acc = accuracy_score(y_true, y_pred)\n    mae = mean_absolute_error(y_true, y_pred)\n    mse = mean_squared_error(y_true, y_pred)\n    print(f\"{stage} ROC-AUC Score: {auc:.2f}\")\n    print(f\"{stage} Accuracy: {acc:.2f}\")\n    print(f\"{stage} Mean Absolute Error: {mae:.2f}\")\n    print(f\"{stage} Mean Squared Error: {mse:.2f}\")","metadata":{"execution":{"iopub.status.busy":"2021-08-27T17:20:21.166607Z","iopub.execute_input":"2021-08-27T17:20:21.166938Z","iopub.status.idle":"2021-08-27T17:20:21.172429Z","shell.execute_reply.started":"2021-08-27T17:20:21.166907Z","shell.execute_reply":"2021-08-27T17:20:21.171416Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Load Data","metadata":{"id":"N-RW4XhDWw0u"}},{"cell_type":"code","source":"train_files = sorted(glob(\"../input/count-the-blue-boxes/train/train/*/*\"))\ntest_files = sorted(glob(\"../input/count-the-blue-boxes/test/test/*\"))","metadata":{"id":"fahKxr2AGHDt","execution":{"iopub.status.busy":"2021-08-27T17:20:21.174382Z","iopub.execute_input":"2021-08-27T17:20:21.175046Z","iopub.status.idle":"2021-08-27T17:20:59.129389Z","shell.execute_reply.started":"2021-08-27T17:20:21.174958Z","shell.execute_reply":"2021-08-27T17:20:59.128537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"# Train Images: {len(train_files)}\")\nprint(f\"# Test Images: {len(test_files)}\")","metadata":{"id":"WyOkWMTYGVDs","outputId":"99ea5c23-5a58-4593-c465-5a367da5e1bc","execution":{"iopub.status.busy":"2021-08-27T17:20:59.130765Z","iopub.execute_input":"2021-08-27T17:20:59.131119Z","iopub.status.idle":"2021-08-27T17:20:59.138466Z","shell.execute_reply.started":"2021-08-27T17:20:59.131082Z","shell.execute_reply":"2021-08-27T17:20:59.137531Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv(\"../input/count-the-blue-boxes/train.csv\")\ntrain_df[\"image_path\"] = train_df[\"count\"].astype(str) + \"_\" + train_df[\"image_id\"]\ntrain_df[\"image_path\"] = train_df[\"image_path\"].apply(lambda x: f\"../input/count-the-blue-boxes/train/train/{x.split('_')[0]}/{x}.png\")","metadata":{"id":"P3LgIReRGHGO","execution":{"iopub.status.busy":"2021-08-27T17:20:59.139823Z","iopub.execute_input":"2021-08-27T17:20:59.140189Z","iopub.status.idle":"2021-08-27T17:20:59.962438Z","shell.execute_reply.started":"2021-08-27T17:20:59.140152Z","shell.execute_reply":"2021-08-27T17:20:59.961565Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = train_df.loc[train_df[\"count\"] < config.MAX_HOURS]","metadata":{"id":"GcsrWIUXw-SV","execution":{"iopub.status.busy":"2021-08-27T17:20:59.963782Z","iopub.execute_input":"2021-08-27T17:20:59.964168Z","iopub.status.idle":"2021-08-27T17:21:00.005796Z","shell.execute_reply.started":"2021-08-27T17:20:59.964131Z","shell.execute_reply":"2021-08-27T17:21:00.004962Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.shape","metadata":{"id":"zo2fZG_WxFpL","outputId":"80c64f1c-dacf-4336-eafe-211c1e9322c2","execution":{"iopub.status.busy":"2021-08-27T17:21:00.007023Z","iopub.execute_input":"2021-08-27T17:21:00.007403Z","iopub.status.idle":"2021-08-27T17:21:00.015367Z","shell.execute_reply.started":"2021-08-27T17:21:00.007361Z","shell.execute_reply":"2021-08-27T17:21:00.014394Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head()","metadata":{"id":"88tlNTZJW_fw","outputId":"79ba6cc7-232b-4484-8ac6-04d7a4c1e766","execution":{"iopub.status.busy":"2021-08-27T17:21:00.016775Z","iopub.execute_input":"2021-08-27T17:21:00.017129Z","iopub.status.idle":"2021-08-27T17:21:00.035206Z","shell.execute_reply.started":"2021-08-27T17:21:00.017090Z","shell.execute_reply":"2021-08-27T17:21:00.034492Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df[\"count\"].value_counts().head(20)","metadata":{"id":"qyd7JtB6Wpdb","outputId":"6df79947-0b9c-45ae-bca9-b9606cf03509","execution":{"iopub.status.busy":"2021-08-27T17:21:00.036445Z","iopub.execute_input":"2021-08-27T17:21:00.036805Z","iopub.status.idle":"2021-08-27T17:21:00.048079Z","shell.execute_reply.started":"2021-08-27T17:21:00.036769Z","shell.execute_reply":"2021-08-27T17:21:00.047181Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df[\"count\"].value_counts().tail(20)","metadata":{"id":"Sj101gzLX3c0","outputId":"ddb28b38-832f-4206-ffc0-8ae62de8c918","execution":{"iopub.status.busy":"2021-08-27T17:21:00.049336Z","iopub.execute_input":"2021-08-27T17:21:00.049700Z","iopub.status.idle":"2021-08-27T17:21:00.059309Z","shell.execute_reply.started":"2021-08-27T17:21:00.049664Z","shell.execute_reply":"2021-08-27T17:21:00.058251Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Train - Validation Split","metadata":{"id":"MkFaKTOOYFdx"}},{"cell_type":"code","source":"X_train, X_valid, y_train, y_valid = train_test_split(train_df[\"image_path\"].values, train_df[\"count\"].values, \n                                                      stratify=train_df[\"count\"],\n                                                      random_state=config.SEED,\n                                                      test_size=0.2)","metadata":{"id":"c-coTjqEYE9X","execution":{"iopub.status.busy":"2021-08-27T17:21:00.060896Z","iopub.execute_input":"2021-08-27T17:21:00.061248Z","iopub.status.idle":"2021-08-27T17:21:00.201185Z","shell.execute_reply.started":"2021-08-27T17:21:00.061214Z","shell.execute_reply":"2021-08-27T17:21:00.200296Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"Training: {X_train.shape}, {y_train.shape}\")\nprint(f\"Validation: {X_valid.shape}, {y_valid.shape}\")","metadata":{"id":"vivCsM2WYE_0","outputId":"4c01ba43-59fa-466f-cefd-1f225d540dec","execution":{"iopub.status.busy":"2021-08-27T17:21:00.202606Z","iopub.execute_input":"2021-08-27T17:21:00.202964Z","iopub.status.idle":"2021-08-27T17:21:00.208877Z","shell.execute_reply.started":"2021-08-27T17:21:00.202928Z","shell.execute_reply":"2021-08-27T17:21:00.207790Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Create Tensorflow Dataset","metadata":{"id":"LAF482x2YdGx"}},{"cell_type":"code","source":"def encode_single_sample(img_path, label):\n    # 1. Read image\n    img = tf.io.read_file(img_path)\n    # 2. Decode and convert to grayscale\n    img = tf.io.decode_png(img, channels=3)\n    # 3. Convert to float32 in [0, 1] range\n    img = tf.image.convert_image_dtype(img, tf.float32)\n    # 4. Resize to the desired size\n    img = tf.image.resize(img, [config.IMG_HEIGHT, config.IMG_WIDTH])\n    return (img, label)","metadata":{"id":"0K000ALkYFEw","execution":{"iopub.status.busy":"2021-08-27T17:21:00.210455Z","iopub.execute_input":"2021-08-27T17:21:00.210842Z","iopub.status.idle":"2021-08-27T17:21:00.217492Z","shell.execute_reply.started":"2021-08-27T17:21:00.210804Z","shell.execute_reply":"2021-08-27T17:21:00.216666Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = tf.data.Dataset.from_tensor_slices((X_train, y_train))\ntrain_dataset = (\n    train_dataset.map(\n        encode_single_sample, num_parallel_calls=tf.data.experimental.AUTOTUNE\n    )\n    .batch(config.BATCH_SIZE) # pads to the smallest per-batch size that fits all elements\n    .prefetch(buffer_size=tf.data.experimental.AUTOTUNE)\n)","metadata":{"id":"9ujGsWlbYFIk","execution":{"iopub.status.busy":"2021-08-27T17:21:00.218784Z","iopub.execute_input":"2021-08-27T17:21:00.219267Z","iopub.status.idle":"2021-08-27T17:21:02.035736Z","shell.execute_reply.started":"2021-08-27T17:21:00.219230Z","shell.execute_reply":"2021-08-27T17:21:02.034897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_grid(train_dataset, title=\"Training Images\")","metadata":{"id":"o1720QYBX3e9","outputId":"6ffc4ff9-800e-4d49-b202-a1e971f36f4d","execution":{"iopub.status.busy":"2021-08-27T17:21:02.037024Z","iopub.execute_input":"2021-08-27T17:21:02.037360Z","iopub.status.idle":"2021-08-27T17:21:17.596380Z","shell.execute_reply.started":"2021-08-27T17:21:02.037325Z","shell.execute_reply":"2021-08-27T17:21:17.595454Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"validation_dataset = tf.data.Dataset.from_tensor_slices((X_valid, y_valid))\nvalidation_dataset = (\n    validation_dataset.map(\n        encode_single_sample, num_parallel_calls=tf.data.experimental.AUTOTUNE\n    )\n    .batch(config.BATCH_SIZE)\n    .prefetch(buffer_size=tf.data.experimental.AUTOTUNE)\n)","metadata":{"id":"6Xx_nVLMWp-s","execution":{"iopub.status.busy":"2021-08-27T17:21:17.597509Z","iopub.execute_input":"2021-08-27T17:21:17.597834Z","iopub.status.idle":"2021-08-27T17:21:17.625407Z","shell.execute_reply.started":"2021-08-27T17:21:17.597802Z","shell.execute_reply":"2021-08-27T17:21:17.624646Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_grid(validation_dataset, title=\"Validation Images\")","metadata":{"id":"cPty9jbPZJkF","outputId":"95b3cd87-6e42-4a73-d2e6-6e47c5b070ca","execution":{"iopub.status.busy":"2021-08-27T17:21:17.628850Z","iopub.execute_input":"2021-08-27T17:21:17.629122Z","iopub.status.idle":"2021-08-27T17:21:30.252126Z","shell.execute_reply.started":"2021-08-27T17:21:17.629096Z","shell.execute_reply":"2021-08-27T17:21:30.251287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## CNN Regression Model","metadata":{"id":"v3SmFjULZr4E"}},{"cell_type":"code","source":"def build_model():\n    # Inputs to the model\n    input_img = Input(\n        shape=(config.IMG_HEIGHT, config.IMG_WIDTH, 3), name=\"image\", dtype=\"float32\"\n    )\n\n    x = Conv2D(16, (5, 5), activation=\"relu\", padding=\"same\", name=\"conv_1\")(input_img)\n    x = MaxPooling2D((2, 2), name=\"pool_1\")(x)\n    x = Conv2D(32, (5, 5), activation=\"relu\", padding=\"same\", name=\"conv_2\")(x)\n    x = MaxPooling2D((2, 2), name=\"pool_2\")(x)\n    x = Conv2D(64, (5, 5), activation=\"relu\", padding=\"same\", name=\"conv_3\")(x)\n    x = MaxPooling2D((2, 2), name=\"pool_3\")(x)\n    x = Conv2D(128, (5, 5), activation=\"relu\", padding=\"same\", name=\"conv_4\")(x)\n    x = Flatten()(x)\n    x = Dense(512, activation=\"relu\", name=\"dense_1\")(x)\n    x = Dense(256, activation=\"relu\", name=\"dense_2\")(x)\n    output = Dense(1, activation=\"linear\", name=\"output\")(x)\n\n    model = Model(inputs=[input_img], outputs=output, name=\"count_model\")\n\n    opt = tf.keras.optimizers.Adam(learning_rate=config.LR)\n\n    model.compile(optimizer=opt, \n                  loss=tf.keras.losses.MeanSquaredLogarithmicError(), \n                  metrics=[\"accuracy\", tf.keras.metrics.RootMeanSquaredError(), \n                           tf.keras.metrics.MeanAbsoluteError(), \n                           tf.keras.metrics.MeanSquaredError()])\n    return model","metadata":{"id":"nH2dLJjjZqcv","execution":{"iopub.status.busy":"2021-08-27T17:21:30.253619Z","iopub.execute_input":"2021-08-27T17:21:30.253960Z","iopub.status.idle":"2021-08-27T17:21:30.266432Z","shell.execute_reply.started":"2021-08-27T17:21:30.253924Z","shell.execute_reply":"2021-08-27T17:21:30.265637Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training","metadata":{"id":"rZ2Tf4Navd_b"}},{"cell_type":"code","source":"model = build_model()\nmodel.summary()","metadata":{"id":"akA0kNu3vccS","outputId":"d02a7b29-b01b-48f3-8b86-75dca4905cfb","execution":{"iopub.status.busy":"2021-08-27T17:21:30.267836Z","iopub.execute_input":"2021-08-27T17:21:30.268253Z","iopub.status.idle":"2021-08-27T17:21:30.392189Z","shell.execute_reply.started":"2021-08-27T17:21:30.268215Z","shell.execute_reply":"2021-08-27T17:21:30.391300Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tf.keras.utils.plot_model(model)","metadata":{"id":"6CLwgZCT5lcv","outputId":"380b833d-4f8c-42fa-86c8-5f32704db22b","execution":{"iopub.status.busy":"2021-08-27T17:21:30.394452Z","iopub.execute_input":"2021-08-27T17:21:30.394855Z","iopub.status.idle":"2021-08-27T17:21:30.801806Z","shell.execute_reply.started":"2021-08-27T17:21:30.394812Z","shell.execute_reply":"2021-08-27T17:21:30.800883Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"early_stopping_patience = 3\nearly_stopping = tf.keras.callbacks.EarlyStopping(\n    monitor=\"val_loss\", patience=early_stopping_patience, \n    restore_best_weights=True\n)\n\ncheckpoint_filepath = \"model_checkpoint\"\nmodel_checkpoint_callback = tf.keras.callbacks.ModelCheckpoint(\n    filepath=checkpoint_filepath,\n    save_weights_only=False,\n    monitor=\"val_loss\",\n    mode=\"min\",\n    save_best_only=True)","metadata":{"id":"zMw-LAJ6vcrP","execution":{"iopub.status.busy":"2021-08-27T17:21:30.803288Z","iopub.execute_input":"2021-08-27T17:21:30.803599Z","iopub.status.idle":"2021-08-27T17:21:30.810691Z","shell.execute_reply.started":"2021-08-27T17:21:30.803555Z","shell.execute_reply":"2021-08-27T17:21:30.809188Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(\n    train_dataset,\n    validation_data=validation_dataset,\n    epochs=config.EPOCHS,\n    callbacks=[early_stopping, model_checkpoint_callback]\n)","metadata":{"id":"Fi3L4qeKvczc","outputId":"886e9387-e4e9-49f9-e29f-2e3e41ab0f52","execution":{"iopub.status.busy":"2021-08-27T17:22:02.041170Z","iopub.execute_input":"2021-08-27T17:22:02.041507Z","iopub.status.idle":"2021-08-27T18:58:07.307866Z","shell.execute_reply.started":"2021-08-27T17:22:02.041475Z","shell.execute_reply":"2021-08-27T18:58:07.306996Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_hist(history)","metadata":{"id":"kLhwrCSFvc8r","execution":{"iopub.status.busy":"2021-08-27T18:58:07.309831Z","iopub.execute_input":"2021-08-27T18:58:07.310212Z","iopub.status.idle":"2021-08-27T18:58:07.618014Z","shell.execute_reply.started":"2021-08-27T18:58:07.310170Z","shell.execute_reply":"2021-08-27T18:58:07.617040Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_metrics(history)","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:00:20.585638Z","iopub.execute_input":"2021-08-27T19:00:20.585977Z","iopub.status.idle":"2021-08-27T19:00:20.936249Z","shell.execute_reply.started":"2021-08-27T19:00:20.585931Z","shell.execute_reply":"2021-08-27T19:00:20.935520Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Inference\n\nAlways load the best model","metadata":{"id":"-C5Y0AJdvyuS"}},{"cell_type":"code","source":"best_model = tf.keras.models.load_model(checkpoint_filepath)","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:00:28.348214Z","iopub.execute_input":"2021-08-27T19:00:28.348558Z","iopub.status.idle":"2021-08-27T19:00:31.831499Z","shell.execute_reply.started":"2021-08-27T19:00:28.348512Z","shell.execute_reply":"2021-08-27T19:00:31.830673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Validation Data Evaluation**","metadata":{}},{"cell_type":"code","source":"valid_preds = best_model.predict(validation_dataset)","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:00:31.835288Z","iopub.execute_input":"2021-08-27T19:00:31.835549Z","iopub.status.idle":"2021-08-27T19:03:13.645357Z","shell.execute_reply.started":"2021-08-27T19:00:31.835522Z","shell.execute_reply":"2021-08-27T19:03:13.644495Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_pred = list(chain.from_iterable(valid_preds))\ny_pred = np.rint(y_pred)","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:25:22.381660Z","iopub.execute_input":"2021-08-27T19:25:22.382037Z","iopub.status.idle":"2021-08-27T19:25:22.435645Z","shell.execute_reply.started":"2021-08-27T19:25:22.382007Z","shell.execute_reply":"2021-08-27T19:25:22.434664Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print_metrics(\"Validation\", y_valid, y_pred)","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:25:25.672715Z","iopub.execute_input":"2021-08-27T19:25:25.673041Z","iopub.status.idle":"2021-08-27T19:25:26.110292Z","shell.execute_reply.started":"2021-08-27T19:25:25.673010Z","shell.execute_reply":"2021-08-27T19:25:26.109409Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_valid[:5], y_pred[:5]","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:25:29.257460Z","iopub.execute_input":"2021-08-27T19:25:29.257837Z","iopub.status.idle":"2021-08-27T19:25:29.263825Z","shell.execute_reply.started":"2021-08-27T19:25:29.257806Z","shell.execute_reply":"2021-08-27T19:25:29.262937Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Training Data Evaluation**","metadata":{}},{"cell_type":"code","source":"train_preds = best_model.predict(train_dataset)","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:10:47.027800Z","iopub.execute_input":"2021-08-27T19:10:47.028117Z","iopub.status.idle":"2021-08-27T19:22:38.556659Z","shell.execute_reply.started":"2021-08-27T19:10:47.028087Z","shell.execute_reply":"2021-08-27T19:22:38.555736Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_pred = list(chain.from_iterable(train_preds))\ny_pred = np.rint(y_pred)","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:25:37.807419Z","iopub.execute_input":"2021-08-27T19:25:37.807782Z","iopub.status.idle":"2021-08-27T19:25:38.004464Z","shell.execute_reply.started":"2021-08-27T19:25:37.807750Z","shell.execute_reply":"2021-08-27T19:25:38.003549Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print_metrics(\"Training\", y_train, y_pred)","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:25:38.096706Z","iopub.execute_input":"2021-08-27T19:25:38.096977Z","iopub.status.idle":"2021-08-27T19:25:40.120091Z","shell.execute_reply.started":"2021-08-27T19:25:38.096952Z","shell.execute_reply":"2021-08-27T19:25:40.118965Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Submission","metadata":{}},{"cell_type":"code","source":"submission = pd.read_csv(\"../input/count-the-blue-boxes/sample_submission.csv\")\nsubmission[\"image_path\"] = submission[\"image_id\"].apply(lambda x: f\"../input/count-the-blue-boxes/test/test/{x}.png\")","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:25:42.733099Z","iopub.execute_input":"2021-08-27T19:25:42.733401Z","iopub.status.idle":"2021-08-27T19:25:43.021850Z","shell.execute_reply.started":"2021-08-27T19:25:42.733372Z","shell.execute_reply":"2021-08-27T19:25:43.020973Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def encode_single_sample(img_path):\n    img = tf.io.read_file(img_path)\n    img = tf.io.decode_png(img, channels=3)\n    img = tf.image.convert_image_dtype(img, tf.float32)\n    img = tf.image.resize(img, [config.IMG_HEIGHT, config.IMG_WIDTH])\n    return img","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:25:43.023737Z","iopub.execute_input":"2021-08-27T19:25:43.024114Z","iopub.status.idle":"2021-08-27T19:25:43.029483Z","shell.execute_reply.started":"2021-08-27T19:25:43.024085Z","shell.execute_reply":"2021-08-27T19:25:43.028274Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = tf.data.Dataset.from_tensor_slices(submission[\"image_path\"].tolist())\ntest_dataset = (\n    test_dataset.map(\n        encode_single_sample, num_parallel_calls=tf.data.experimental.AUTOTUNE\n    )\n    .batch(config.BATCH_SIZE)\n    .prefetch(buffer_size=tf.data.experimental.AUTOTUNE)\n)","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:25:44.069852Z","iopub.execute_input":"2021-08-27T19:25:44.070169Z","iopub.status.idle":"2021-08-27T19:25:44.529487Z","shell.execute_reply.started":"2021-08-27T19:25:44.070138Z","shell.execute_reply":"2021-08-27T19:25:44.528681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_all_preds(dataset):\n    all_preds = []\n    for batch_images in tqdm(dataset):\n        preds = best_model.predict(batch_images)\n        all_preds.append(preds)\n    # flatten 2D list\n    all_preds = list(chain.from_iterable(all_preds))\n    return all_preds","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:25:45.454629Z","iopub.execute_input":"2021-08-27T19:25:45.454938Z","iopub.status.idle":"2021-08-27T19:25:45.459365Z","shell.execute_reply.started":"2021-08-27T19:25:45.454910Z","shell.execute_reply":"2021-08-27T19:25:45.458546Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_preds = get_all_preds(test_dataset)","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:25:55.863398Z","iopub.execute_input":"2021-08-27T19:25:55.863764Z","iopub.status.idle":"2021-08-27T19:44:24.578641Z","shell.execute_reply.started":"2021-08-27T19:25:55.863730Z","shell.execute_reply":"2021-08-27T19:44:24.576247Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"final_preds = [np.rint(x[0]) for x in test_preds]\nfinal_preds = [int(x) for x in final_preds]\nfinal_preds[:5]","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:48:17.407844Z","iopub.execute_input":"2021-08-27T19:48:17.408188Z","iopub.status.idle":"2021-08-27T19:48:17.713318Z","shell.execute_reply.started":"2021-08-27T19:48:17.408158Z","shell.execute_reply":"2021-08-27T19:48:17.712513Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission[\"count\"] = final_preds\nsubmission = submission[[\"image_id\", \"count\"]]\nprint(submission.shape)\nsubmission.head()","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:48:18.784937Z","iopub.execute_input":"2021-08-27T19:48:18.785275Z","iopub.status.idle":"2021-08-27T19:48:18.858814Z","shell.execute_reply.started":"2021-08-27T19:48:18.785244Z","shell.execute_reply":"2021-08-27T19:48:18.857898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission[\"count\"].describe()","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:48:19.084104Z","iopub.execute_input":"2021-08-27T19:48:19.084354Z","iopub.status.idle":"2021-08-27T19:48:19.098758Z","shell.execute_reply.started":"2021-08-27T19:48:19.084329Z","shell.execute_reply":"2021-08-27T19:48:19.097749Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.to_csv(\"submission.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:48:20.084692Z","iopub.execute_input":"2021-08-27T19:48:20.085000Z","iopub.status.idle":"2021-08-27T19:48:20.390537Z","shell.execute_reply.started":"2021-08-27T19:48:20.084973Z","shell.execute_reply":"2021-08-27T19:48:20.389593Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Random Plots","metadata":{}},{"cell_type":"code","source":"def plot_random(paths, labels, h=4, w=4, title=\"\"):\n    f, ax = plt.subplots(h, w, figsize=(30, 30))\n    for i in range(h*w):\n        img = cv2.imread(paths[i])\n        ax[i // h, i % w].imshow(img)\n        ax[i // h, i % w].axis(\"off\")\n        ax[i // h, i % w].set_title(labels[i], fontdict={\"fontsize\": 20})\n    plt.tight_layout()\n    f.suptitle(title, fontsize=\"large\", fontweight=\"extra bold\")\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:48:21.550998Z","iopub.execute_input":"2021-08-27T19:48:21.551295Z","iopub.status.idle":"2021-08-27T19:48:21.557665Z","shell.execute_reply.started":"2021-08-27T19:48:21.551267Z","shell.execute_reply":"2021-08-27T19:48:21.556585Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission[\"image_path\"] = submission[\"image_id\"].apply(lambda x: f\"../input/count-the-blue-boxes/test/test/{x}.png\")","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:48:22.221792Z","iopub.execute_input":"2021-08-27T19:48:22.222084Z","iopub.status.idle":"2021-08-27T19:48:22.270330Z","shell.execute_reply.started":"2021-08-27T19:48:22.222057Z","shell.execute_reply":"2021-08-27T19:48:22.269545Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample = submission.sample(30)\nplot_random(sample[\"image_path\"].tolist(), sample[\"count\"].tolist())","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:48:22.741970Z","iopub.execute_input":"2021-08-27T19:48:22.742224Z","iopub.status.idle":"2021-08-27T19:48:24.679451Z","shell.execute_reply.started":"2021-08-27T19:48:22.742200Z","shell.execute_reply":"2021-08-27T19:48:24.678648Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample = submission.sample(30)\nplot_random(sample[\"image_path\"].tolist(), sample[\"count\"].tolist())","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:48:25.484099Z","iopub.execute_input":"2021-08-27T19:48:25.484380Z","iopub.status.idle":"2021-08-27T19:48:27.189975Z","shell.execute_reply.started":"2021-08-27T19:48:25.484351Z","shell.execute_reply":"2021-08-27T19:48:27.188984Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample = submission.sample(30)\nplot_random(sample[\"image_path\"].tolist(), sample[\"count\"].tolist())","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:48:27.191515Z","iopub.execute_input":"2021-08-27T19:48:27.191857Z","iopub.status.idle":"2021-08-27T19:48:29.102258Z","shell.execute_reply.started":"2021-08-27T19:48:27.191821Z","shell.execute_reply":"2021-08-27T19:48:29.101472Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample = submission.sample(30)\nplot_random(sample[\"image_path\"].tolist(), sample[\"count\"].tolist())","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:48:29.104964Z","iopub.execute_input":"2021-08-27T19:48:29.105249Z","iopub.status.idle":"2021-08-27T19:48:31.089759Z","shell.execute_reply.started":"2021-08-27T19:48:29.105220Z","shell.execute_reply":"2021-08-27T19:48:31.088954Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample = submission.sample(30)\nplot_random(sample[\"image_path\"].tolist(), sample[\"count\"].tolist())","metadata":{"execution":{"iopub.status.busy":"2021-08-27T19:48:31.091218Z","iopub.execute_input":"2021-08-27T19:48:31.091584Z","iopub.status.idle":"2021-08-27T19:48:32.792906Z","shell.execute_reply.started":"2021-08-27T19:48:31.091529Z","shell.execute_reply":"2021-08-27T19:48:32.792091Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}