{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":21154,"databundleVersionId":1243559,"sourceType":"competition"}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install --upgrade pip","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import tensorflow as tf\n# import numpy as np\n# import matplotlib.pyplot as plt\n# import re, math\n# from sklearn.metrics import classification_report\n# from tensorflow.keras.applications.efficientnet import EfficientNetB7, preprocess_input\n# # from tensorflow.python.keras.applications.efficientnet import EfficientNetB7\n\n\nimport tensorflow as tf\nfrom tensorflow.keras.applications.efficientnet import EfficientNetB7\nfrom tensorflow.keras.layers import Dense, GlobalAveragePooling2D\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.callbacks import EarlyStopping\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom sklearn.metrics import f1_score, precision_score, recall_score, confusion_matrix\n\n\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-05-31T13:42:01.78459Z","iopub.execute_input":"2025-05-31T13:42:01.784896Z","iopub.status.idle":"2025-05-31T13:42:02.000977Z","shell.execute_reply.started":"2025-05-31T13:42:01.784871Z","shell.execute_reply":"2025-05-31T13:42:01.995471Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.applications import DenseNet169\nfrom tensorflow.keras.applications.densenet import preprocess_input\nfrom tensorflow.keras.layers import Dense\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.callbacks import EarlyStopping\nimport numpy as np\nimport pandas as pd\nimport os\n\n# ========== 設定 ==========\ntry:\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)\n    print(\"✅ TPU initialized\")\nexcept ValueError:\n    strategy = tf.distribute.get_strategy()\n    print(\"✅ Using CPU/GPU\")\n\nIMAGE_SIZE = [384, 384]\nBATCH_SIZE = 32\nEPOCHS = 12\nNUM_CLASSES = 104\n\n# ========== 資料路徑 ==========\nGCS_PATH = '/kaggle/input/tpu-getting-started'\nTRAINING_FILENAMES = tf.io.gfile.glob(GCS_PATH + '/tfrecords-jpeg-512x512/train/*.tfrec')\nVALIDATION_FILENAMES = tf.io.gfile.glob(GCS_PATH + '/tfrecords-jpeg-512x512/val/*.tfrec')\nTEST_FILENAMES = tf.io.gfile.glob(GCS_PATH + '/tfrecords-jpeg-512x512/test/*.tfrec')\n\n# ========== 資料解析 ==========\ndef decode_image(image_data):\n    try:\n        image = tf.image.decode_jpeg(image_data, channels=3)\n        image = tf.image.resize(image, IMAGE_SIZE)\n        image = preprocess_input(image)\n    except:\n        image = tf.zeros([*IMAGE_SIZE, 3])\n    return image\n\ndef read_labeled_tfrecord(example):\n    LABELED_TFREC_FORMAT = {\n        \"image\": tf.io.FixedLenFeature([], tf.string),\n        \"class\": tf.io.FixedLenFeature([], tf.int64),\n    }\n    example = tf.io.parse_single_example(example, LABELED_TFREC_FORMAT)\n    return decode_image(example['image']), example['class']\n\ndef read_unlabeled_tfrecord(example):\n    UNLABELED_TFREC_FORMAT = {\n        \"image\": tf.io.FixedLenFeature([], tf.string),\n        \"id\": tf.io.FixedLenFeature([], tf.string),\n    }\n    example = tf.io.parse_single_example(example, UNLABELED_TFREC_FORMAT)\n    image = decode_image(example['image'])\n    return image, example['id']\n\ndef load_dataset(filenames, labeled=True, ordered=False):\n    ignore_order = tf.data.Options()\n    if not ordered:\n        ignore_order.experimental_deterministic = False\n\n    dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=tf.data.AUTOTUNE)\n    dataset = dataset.with_options(ignore_order)\n    dataset = dataset.map(read_labeled_tfrecord if labeled else read_unlabeled_tfrecord, num_parallel_calls=4)\n    return dataset\n\ndef get_dataset(filenames, labeled=True, batch_size=BATCH_SIZE):\n    dataset = load_dataset(filenames, labeled)\n    if labeled:\n        dataset = dataset.shuffle(2048)\n    dataset = dataset.batch(batch_size)\n    dataset = dataset.prefetch(tf.data.AUTOTUNE)\n    return dataset\n\n# ========== 建立資料集 ==========\ntrain_dataset = get_dataset(TRAINING_FILENAMES, labeled=True)\nval_dataset = get_dataset(VALIDATION_FILENAMES, labeled=True)\ntest_dataset = get_dataset(TEST_FILENAMES, labeled=False)\n\n# ========== 建立 DenseNet169 模型 ==========\nwith strategy.scope():\n    base_model = DenseNet169(\n        input_shape=(*IMAGE_SIZE, 3),\n        include_top=False,\n        weights='imagenet',\n        pooling='avg'\n    )\n\n    output = Dense(NUM_CLASSES, activation='softmax')(base_model.output)\n    model = Model(inputs=base_model.input, outputs=output)\n\n    model.compile(\n        optimizer=Adam(),\n        loss='sparse_categorical_crossentropy',\n        metrics=['sparse_categorical_accuracy']\n    )\n\nmodel.summary()\n\n# ========== 模型訓練 ==========\ntry:\n    history = model.fit(\n        train_dataset,\n        validation_data=val_dataset,\n        epochs=EPOCHS,\n        callbacks=[EarlyStopping(patience=3, restore_best_weights=True)]\n    )\nexcept Exception as e:\n    print(\"🚨 模型訓練錯誤：\", e)\n\n# ========== 預測與提交 ==========\nprint(\"Generating predictions...\")\n\nraw_test_dataset = load_dataset(TEST_FILENAMES, labeled=False, ordered=True)\nbatched_test_dataset = raw_test_dataset.batch(BATCH_SIZE, drop_remainder=False)\n\n# 🔍 印出一筆測試看看\nfor img, idnum in batched_test_dataset.take(1):\n    print(\"✅ 測試圖片形狀:\", img.shape, \"ID 數量:\", idnum.shape)\n\n# 預測\nall_predictions = []\nall_ids = []\n\nfor batch_images, batch_ids in batched_test_dataset:\n    preds = model(batch_images, training=False)\n    all_predictions.append(preds.numpy())\n    all_ids.append(batch_ids.numpy())\n\n# 合併預測與 ID\npredictions = np.concatenate(all_predictions, axis=0)\nimage_ids = np.concatenate(all_ids, axis=0)\npredicted_labels = np.argmax(predictions, axis=-1)\n\nsubmission = pd.DataFrame({\n    \"id\": image_ids.astype(\"U\"),\n    \"label\": predicted_labels\n})\nsubmission.to_csv(\"submission.csv\", index=False)\nprint(\"✅ submission.csv created\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T14:10:07.233563Z","iopub.execute_input":"2025-05-31T14:10:07.233834Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"score, acc = model.evaluate(X_test,y_test)\nprint('Validation score:', score,'   Validation accuracy:', acc)","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}