{"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":"none","dataSources":[{"sourceId":3649,"databundleVersionId":46718,"sourceType":"competition"}],"dockerImageVersionId":31040,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras import layers, models, optimizers\nimport matplotlib.pyplot as plt\n\ndef simple_augmentation(image, label):\n    image = tf.cast(image, tf.float32)\n    # Only horizontal flip - keep it simple\n    image = tf.image.random_flip_left_right(image)\n    return image, label\n\n# 创建数据集管道\ndef create_dataset(images, labels, batch_size, is_training=True, validation_split=0.15):\n    dataset = tf.data.Dataset.from_tensor_slices((images, labels))\n\n    if is_training:\n        # 拆分训练数据以进行验证\n        dataset_size = len(images)\n        val_size = int(dataset_size * validation_split)\n        train_size = dataset_size - val_size\n\n        dataset = dataset.shuffle(10000, seed=42)\n        train_dataset = dataset.take(train_size)\n        val_dataset = dataset.skip(train_size)\n\n        # 仅对训练数据应用最小增强\n        train_dataset = train_dataset.cache()\n        train_dataset = train_dataset.shuffle(5000, reshuffle_each_iteration=True)\n        train_dataset = train_dataset.map(simple_augmentation, num_parallel_calls=tf.data.AUTOTUNE)\n        train_dataset = train_dataset.batch(batch_size)\n        train_dataset = train_dataset.prefetch(tf.data.AUTOTUNE)\n\n        # 无增强的验证数据集\n        val_dataset = val_dataset.batch(batch_size)\n        val_dataset = val_dataset.prefetch(tf.data.AUTOTUNE)\n\n        return train_dataset, val_dataset\n    else:\n        dataset = dataset.batch(batch_size)\n        dataset = dataset.prefetch(tf.data.AUTOTUNE)\n        return dataset\n\n# 创建参数高效但有效的模型\ndef create_simple_effective_model():\n    inputs = layers.Input(shape=(32, 32, 3))\n\n    x = layers.Conv2D(24, (3, 3), padding='same', activation='relu')(inputs)\n    x = layers.BatchNormalization()(x)\n    x = layers.Conv2D(24, (3, 3), padding='same', activation='relu')(x)\n    x = layers.MaxPooling2D((2, 2))(x)\n    x = layers.Dropout(0.05)(x)\n\n    x = layers.Conv2D(48, (3, 3), padding='same', activation='relu')(x)\n    x = layers.BatchNormalization()(x)\n    x = layers.Conv2D(48, (3, 3), padding='same', activation='relu')(x)\n    x = layers.MaxPooling2D((2, 2))(x)\n    x = layers.Dropout(0.05)(x)\n\n    x = layers.Conv2D(68, (3, 3), padding='same', activation='relu')(x)  # 72->68\n    x = layers.BatchNormalization()(x)\n    x = layers.Conv2D(68, (3, 3), padding='same', activation='relu')(x)  # 72->68\n    x = layers.Dropout(0.05)(x)\n\n    # 全局平均池化\n    x = layers.GlobalAveragePooling2D()(x)\n\n    # Slightly smaller dense layer\n    x = layers.Dense(120, activation='relu')(x)  # 128->120\n    x = layers.Dropout(0.15)(x)\n\n    outputs = layers.Dense(10)(x)\n\n    model = models.Model(inputs, outputs, name='competitive_model')\n    return model\n\ndef cosine_decay_schedule(epoch, total_epochs=100):\n    import math\n    return 0.001 * 0.5 * (1 + math.cos(math.pi * epoch / total_epochs))\n\n# 建立模型\nmodel = create_simple_effective_model()\nmodel.build(input_shape=(None, 32, 32, 3))\n\noptimizer = optimizers.Adam(learning_rate=0.001)\nmodel.compile(\n    optimizer=optimizer,\n    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),\n    metrics=[\n        tf.keras.metrics.SparseCategoricalCrossentropy(from_logits=True, name='ce'),\n        tf.keras.metrics.SparseCategoricalAccuracy(name='accuracy')\n    ]\n)\n\n# 显示模型\nmodel.summary()\n\n# 计算总参数\ntotal_params = model.count_params()\nprint(f\"Total Parameters: {total_params:,}\")\nprint(f\"Parameter budget used: {total_params/122000*100:.1f}%\")\n\ncallbacks = [\n    tf.keras.callbacks.LearningRateScheduler(cosine_decay_schedule),\n    tf.keras.callbacks.EarlyStopping(\n        monitor='val_accuracy',  # 监控准确性\n        patience=10,\n        restore_best_weights=True,\n        mode='max',\n        verbose=1\n    ),\n    tf.keras.callbacks.ModelCheckpoint(\n        'best_model.h5',\n        monitor='val_accuracy',\n        save_best_only=True,\n        mode='max',\n        verbose=1\n    )\n]\n\n# 加载和预处理 CIFAR-10 数据集\n(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.cifar10.load_data()\n\ntrain_images = train_images.astype('float32') / 255.0\ntest_images = test_images.astype('float32') / 255.0\n\n# 创建具有较大验证拆分的数据集\nbatch_size = 32  \ntrain_dataset, val_dataset = create_dataset(train_images, train_labels, batch_size, is_training=True)\ntest_dataset = create_dataset(test_images, test_labels, batch_size, is_training=False)\n\n# 使用更少的 epoch 训练模型\nhistory = model.fit(\n    train_dataset,\n    epochs=100,  # epoch\n    validation_data=val_dataset,\n    callbacks=callbacks,\n    verbose=1\n)\n\n# 在测试集上评估\ntest_results = model.evaluate(test_dataset, verbose=0)\nprint(f\"\\nTest Results:\")\nprint(f\"Test Loss: {test_results[0]:.4f}\")\nprint(f\"Test Cross-Entropy: {test_results[1]:.4f}\")\nprint(f\"Test Accuracy: {test_results[2]:.4f}\")\n\n# 绘制训练历史和详细的 CE 信息\nplt.figure(figsize=(15, 5))\n\nplt.subplot(1, 3, 1)\nplt.plot(history.history['ce'], label='Train CE', alpha=0.8)\nplt.plot(history.history['val_ce'], label='Val CE', alpha=0.8)\n\n# 查找并注释最低验证 CE\nmin_val_ce = min(history.history['val_ce'])\nmin_val_ce_epoch = history.history['val_ce'].index(min_val_ce)\nplt.annotate(f'Lowest Val CE: {min_val_ce:.4f}\\nEpoch: {min_val_ce_epoch + 1}',\n             xy=(min_val_ce_epoch, min_val_ce),\n             xytext=(min_val_ce_epoch + 5, min_val_ce + 0.1),\n             arrowprops=dict(arrowstyle='->', color='red', alpha=0.7),\n             bbox=dict(boxstyle=\"round,pad=0.3\", facecolor='yellow', alpha=0.7),\n             fontsize=10)\n\n#标记点\nplt.plot(min_val_ce_epoch, min_val_ce, 'ro', markersize=8, alpha=0.8)\n\nplt.title(f'Cross Entropy (Best Val CE: {min_val_ce:.4f})')\nplt.xlabel('Epoch')\nplt.ylabel('Cross Entropy')\nplt.legend()\nplt.grid(True, alpha=0.3)\n\nplt.subplot(1, 3, 2)\nplt.plot(history.history['accuracy'], label='Train Acc', alpha=0.8)\nplt.plot(history.history['val_accuracy'], label='Val Acc', alpha=0.8)\n\n# 查找并注释最高的验证准确性\nmax_val_acc = max(history.history['val_accuracy'])\nmax_val_acc_epoch = history.history['val_accuracy'].index(max_val_acc)\nplt.annotate(f'Best Val Acc: {max_val_acc:.4f}\\nEpoch: {max_val_acc_epoch + 1}',\n             xy=(max_val_acc_epoch, max_val_acc),\n             xytext=(max_val_acc_epoch + 5, max_val_acc - 0.05),\n             arrowprops=dict(arrowstyle='->', color='green', alpha=0.7),\n             bbox=dict(boxstyle=\"round,pad=0.3\", facecolor='lightgreen', alpha=0.7),\n             fontsize=10)\n\nplt.plot(max_val_acc_epoch, max_val_acc, 'go', markersize=8, alpha=0.8)\n\nplt.title(f'Accuracy (Best Val Acc: {max_val_acc:.4f})')\nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\nplt.legend()\nplt.grid(True, alpha=0.3)\n\nplt.subplot(1, 3, 3)\nplt.plot(history.history['loss'], label='Train Loss', alpha=0.8)\nplt.plot(history.history['val_loss'], label='Val Loss', alpha=0.8)\n\n# 查找并注释最低的验证损失\nmin_val_loss = min(history.history['val_loss'])\nmin_val_loss_epoch = history.history['val_loss'].index(min_val_loss)\nplt.annotate(f'Lowest Val Loss: {min_val_loss:.4f}\\nEpoch: {min_val_loss_epoch + 1}',\n             xy=(min_val_loss_epoch, min_val_loss),\n             xytext=(min_val_loss_epoch + 5, min_val_loss + 0.1),\n             arrowprops=dict(arrowstyle='->', color='blue', alpha=0.7),\n             bbox=dict(boxstyle=\"round,pad=0.3\", facecolor='lightblue', alpha=0.7),\n             fontsize=10)\n\nplt.plot(min_val_loss_epoch, min_val_loss, 'bo', markersize=8, alpha=0.8)\n\nplt.title(f'Loss (Best Val Loss: {min_val_loss:.4f})')\nplt.xlabel('Epoch')\nplt.ylabel('Loss')\nplt.legend()\nplt.grid(True, alpha=0.3)\n\nplt.tight_layout()\nplt.show()\n\n# Print\nprint(f\"\\n COMPETITION SUMMARY:\")\nprint(f\" Parameters: {total_params:,} / 122,000 ({total_params/122000*100:.1f}%)\")\nprint(f\" Best Validation CE: {min_val_ce:.4f} (Epoch {min_val_ce_epoch + 1})\")\nprint(f\" Best Validation Accuracy: {max_val_acc:.4f} (Epoch {max_val_acc_epoch + 1})\")\nprint(f\" Best Validation Loss: {min_val_loss:.4f} (Epoch {min_val_loss_epoch + 1})\")\nprint(f\" Final Test CE: {test_results[1]:.4f}\")\nprint(f\" Final Test Accuracy: {test_results[2]:.4f}\")","metadata":{"_uuid":"eab50dc8-f6c2-4e2f-b501-712af1a23e25","_cell_guid":"445ba1ef-86f7-4de3-bacf-97d152382378","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-06-24T02:09:21.066793Z","iopub.execute_input":"2025-06-24T02:09:21.067023Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"Model: \"competitive_model\"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}