{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceType":"competition","sourceId":21154,"databundleVersionId":1243559},{"sourceType":"datasetVersion","sourceId":10421266,"datasetId":6459084,"databundleVersionId":10739997}],"dockerImageVersionId":31193,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install efficientnet","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-14T22:30:46.479117Z","iopub.execute_input":"2025-12-14T22:30:46.479338Z","iopub.status.idle":"2025-12-14T22:30:51.104171Z","shell.execute_reply.started":"2025-12-14T22:30:46.479316Z","shell.execute_reply":"2025-12-14T22:30:51.103252Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport pandas as pd\nimport tensorflow as tf\nimport matplotlib.pyplot as plt\nimport re\nimport random\nimport warnings\n\nfrom sklearn.metrics import f1_score\nfrom tensorflow import keras\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import GlobalAveragePooling2D, Dense\nfrom tensorflow.keras.applications import DenseNet201, EfficientNetB7\n\nwarnings.filterwarnings('ignore')\n\nAUTO = tf.data.experimental.AUTOTUNE\nstrategy = tf.distribute.MirroredStrategy()\n\nIMAGE_SHAPE = [224, 224]\nEPOCHS = 1\nBATCH_SIZE = 16 * strategy.num_replicas_in_sync\n\nSEED = 42\nrandom.seed(SEED)\nnp.random.seed(SEED)\ntf.random.set_seed(SEED)\n\nBASE_PATH = \"/kaggle/input/tpu-getting-started\"\nPATH_MAP = {\n    192: BASE_PATH + '/tfrecords-jpeg-192x192',\n    224: BASE_PATH + '/tfrecords-jpeg-224x224',\n    331: BASE_PATH + '/tfrecords-jpeg-331x331',\n    512: BASE_PATH + '/tfrecords-jpeg-512x512'\n}\nDATA_PATH = PATH_MAP[IMAGE_SHAPE[0]]\n\nVAL_FILES = tf.io.gfile.glob(DATA_PATH + '/val/*.tfrec')\nTEST_FILES = tf.io.gfile.glob(DATA_PATH + '/test/*.tfrec')\n\ndef cutout(img, sl=0.1, sh=0.2, rl=0.4):\n    if random.random() < 0.25:\n        return img\n    h, w, c = IMAGE_SHAPE[0], IMAGE_SHAPE[1], 3\n    area = tf.cast(h * w, tf.float32)\n    e_l = tf.cast(tf.round(tf.sqrt(area * sl * rl)), tf.int32)\n    e_h = tf.cast(tf.round(tf.sqrt(area * sh / rl)), tf.int32)\n    e_h = tf.minimum(e_h, h)\n    e_w = tf.minimum(e_h, w)\n    rh = tf.random.uniform([], e_l, e_h, tf.int32)\n    rw = tf.random.uniform([], e_l, e_w, tf.int32)\n    mask = tf.zeros([rh, rw, c], tf.uint8)\n    ph = h - rh\n    pw = w - rw\n    pt = tf.random.uniform([], 0, ph, tf.int32)\n    pl = tf.random.uniform([], 0, pw, tf.int32)\n    pb = ph - pt\n    pr = pw - pl\n    mask = tf.pad([mask], [[0, 0], [pt, pb], [pl, pr], [0, 0]], constant_values=1)\n    mask = tf.squeeze(mask, 0)\n    return tf.cast(tf.cast(img, tf.float32) * tf.cast(mask, tf.float32), img.dtype)\n\ndef decode(img):\n    img = tf.image.decode_jpeg(img, channels=3)\n    img = tf.cast(img, tf.float32) / 255.0\n    img = tf.reshape(img, [*IMAGE_SHAPE, 3])\n    return img\n\ndef parse_labeled(example):\n    fmt = {\n        \"image\": tf.io.FixedLenFeature([], tf.string),\n        \"class\": tf.io.FixedLenFeature([], tf.int64),\n    }\n    ex = tf.io.parse_single_example(example, fmt)\n    return decode(ex[\"image\"]), tf.cast(ex[\"class\"], tf.int32)\n\ndef parse_unlabeled(example):\n    fmt = {\n        \"image\": tf.io.FixedLenFeature([], tf.string),\n        \"id\": tf.io.FixedLenFeature([], tf.string),\n    }\n    ex = tf.io.parse_single_example(example, fmt)\n    return decode(ex[\"image\"]), ex[\"id\"]\n\ndef load_ds(files, labeled=True, ordered=False):\n    opts = tf.data.Options()\n    if not ordered:\n        opts.experimental_deterministic = False\n    ds = tf.data.TFRecordDataset(files, num_parallel_reads=AUTO)\n    ds = ds.with_options(opts)\n    fn = parse_labeled if labeled else parse_unlabeled\n    return ds.map(fn, num_parallel_calls=AUTO)\n\ndef get_val_ds():\n    return load_ds(VAL_FILES).batch(BATCH_SIZE).cache().prefetch(AUTO)\n\ndef get_test_ds(ordered=False):\n    return load_ds(TEST_FILES, labeled=False, ordered=ordered).batch(BATCH_SIZE).prefetch(AUTO)\n\ndef count_items(files):\n    return np.sum([int(re.search(r\"-([0-9]*)\\.\", f).group(1)) for f in files])\n\nNUM_TRAIN = 68094\nNUM_VAL = count_items(VAL_FILES)\nNUM_TEST = count_items(TEST_FILES)\n\nval_ds = get_val_ds()\ntest_ds = get_test_ds()\n\nwith strategy.scope():\n    base1 = EfficientNetB7(input_shape=[*IMAGE_SHAPE, 3], weights='imagenet', include_top=False)\n    model_a = Sequential([base1, GlobalAveragePooling2D(), Dense(104, activation='softmax')])\n    model_a.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])\n    model_a.load_weights(\"/kaggle/input/efficientnetb7-densenet201/EfficientNetB7_best.keras\",\n        skip_mismatch=True\n    )\n\nwith strategy.scope():\n    base2 = tf.keras.applications.DenseNet201(input_shape=[*IMAGE_SHAPE, 3], weights='imagenet', include_top=False)\n    model_b = Sequential([base2, GlobalAveragePooling2D(), Dense(104, activation='softmax')])\n    model_b.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])\n    model_b.load_weights(\"/kaggle/input/efficientnetb7-densenet201/densenet201_best.keras\")\n\nimgs = val_ds.map(lambda x, y: x)\nlabels = next(iter(val_ds.map(lambda x, y: y).unbatch().batch(NUM_VAL))).numpy()\n\npred_a = model_a.predict(imgs, verbose=2)\npred_b = model_b.predict(imgs, verbose=2)\n\nalphas = np.linspace(0, 1, 100)\nscores = [\n    f1_score(labels, np.argmax(a * pred_a + (1 - a) * pred_b, axis=1), average='macro')\n    for a in alphas\n]\nbest_alpha = alphas[np.argmax(scores)]\n\ndef tta_predict(model, n):\n    out = []\n    for _ in range(n):\n        ds = get_test_ds(ordered=True).map(lambda x, i: x)\n        out.append(model.predict(ds, verbose=2))\n    return np.mean(out, axis=0)\n\np1 = tta_predict(model_a, 5)\np2 = tta_predict(model_b, 5)\n\nfinal_prob = best_alpha * p1 + (1 - best_alpha) * p2\nfinal_pred = np.argmax(final_prob, axis=1)\n\nids = next(iter(get_test_ds(ordered=True).map(lambda x, i: i).unbatch().batch(NUM_TEST))).numpy().astype('U')\n\nsubmission = pd.DataFrame({\"id\": ids, \"label\": final_pred})\nsubmission.to_csv(\"submission.csv\", index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-14T22:40:56.712329Z","iopub.execute_input":"2025-12-14T22:40:56.712629Z","iopub.status.idle":"2025-12-14T22:52:05.500891Z","shell.execute_reply.started":"2025-12-14T22:40:56.712608Z","shell.execute_reply":"2025-12-14T22:52:05.499999Z"}},"outputs":[],"execution_count":null}]}