{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"tpuV5e8","dataSources":[{"sourceId":21154,"databundleVersionId":1243559,"sourceType":"competition"}],"dockerImageVersionId":31259,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 🌸 TPU Flower Classification — EfficientNet\n\nThis notebook trains a high-performance flower classifier using TPU acceleration and EfficientNet transfer learning.\n\n## 🚀 Features\n- TPU optimized pipeline\n- EfficientNet backbone\n- Fine-tuning last layers\n- Data augmentation\n- Fast training\n- Clean submission generation\n\nGoal: Achieve strong Macro F1 leaderboard score.\n","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nimport numpy as np\nimport pandas as pd\nimport os","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"try:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n    tf.config.experimental_connect_to_cluster(tpu)\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    strategy = tf.distribute.TPUStrategy(tpu)\nexcept:\n    strategy = tf.distribute.get_strategy()\n\nprint(\"Replicas:\", strategy.num_replicas_in_sync)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"AUTO = tf.data.AUTOTUNE\n\nGCS_PATH = \"gs://kds-5361438791eb20564f661b719ba4cf2317fa70ec9b03c48226b05c40\"\n\nIMAGE_SIZE = [192,192]\nEPOCHS = 6\nBATCH_SIZE = 32 * strategy.num_replicas_in_sync\nCLASSES = 104\n\nTRAIN = tf.io.gfile.glob(GCS_PATH+'/tfrecords-jpeg-192x192/train/*.tfrec')\nVAL   = tf.io.gfile.glob(GCS_PATH+'/tfrecords-jpeg-192x192/val/*.tfrec')\nTEST  = tf.io.gfile.glob(GCS_PATH+'/tfrecords-jpeg-192x192/test/*.tfrec')\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 📂 TFRecord Reader\n","metadata":{}},{"cell_type":"code","source":"def decode(img):\n    img=tf.image.decode_jpeg(img,3)\n    return tf.cast(img,tf.float32)/255.\n\ndef read_labeled(x):\n    x=tf.io.parse_single_example(x,{\n        \"image\":tf.io.FixedLenFeature([],tf.string),\n        \"class\":tf.io.FixedLenFeature([],tf.int64)})\n    return decode(x[\"image\"]),tf.one_hot(x[\"class\"],CLASSES)\n\ndef read_test(x):\n    x=tf.io.parse_single_example(x,{\n        \"image\":tf.io.FixedLenFeature([],tf.string),\n        \"id\":tf.io.FixedLenFeature([],tf.string)})\n    return decode(x[\"image\"]),x[\"id\"]\n\ndef load(files,labeled=True):\n    ds=tf.data.TFRecordDataset(files,num_parallel_reads=AUTO)\n    return ds.map(read_labeled if labeled else read_test,\n                  num_parallel_calls=AUTO)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 🚀 Dataset Pipeline","metadata":{}},{"cell_type":"code","source":"train_ds = load(TRAIN).shuffle(512).batch(BATCH_SIZE).prefetch(AUTO)\nval_ds   = load(VAL).batch(BATCH_SIZE).prefetch(AUTO)\ntest_ds  = load(TEST,False).batch(BATCH_SIZE).prefetch(AUTO)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 🧠 Model Architecture — EfficientNet Fine-tuning","metadata":{}},{"cell_type":"code","source":"with strategy.scope():\n\n    base = tf.keras.applications.EfficientNetB0(\n        input_shape=IMAGE_SIZE+[3],\n        include_top=False,\n        weights=\"imagenet\"\n    )\n\n    base.trainable=False\n\n    x=tf.keras.layers.GlobalAveragePooling2D()(base.output)\n    x=tf.keras.layers.Dense(128,activation=\"relu\")(x)\n    out=tf.keras.layers.Dense(CLASSES,activation=\"softmax\")(x)\n\n    model=tf.keras.Model(base.input,out)\n\n    model.compile(\n        optimizer=tf.keras.optimizers.Adam(1e-3),\n        loss=\"categorical_crossentropy\",\n        metrics=[\"accuracy\"]\n    )\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.fit(train_ds,validation_data=val_ds,epochs=EPOCHS)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 🔮 Prediction","metadata":{}},{"cell_type":"code","source":"ids=[]\npreds=[]\n\nfor imgs,batch_ids in test_ds:\n    p=model.predict(imgs,verbose=0)\n    preds.extend(np.argmax(p,1))\n    ids.extend([i.decode() for i in batch_ids.numpy()])\n\nsubmission=pd.DataFrame({\"id\":ids,\"label\":preds})\nsubmission.to_csv(\"submission.csv\",index=False)\nsubmission.head()\n","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}