{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[],"dockerImageVersionId":28755,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## ResNet-style ConvNet trained from scratch\nAll network weights are randomly initialized. No pretrained weights were used.","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\n\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\n\nprint(\"TensorFlow version:\", tf.__version__)\nprint(\"GPU available:\", tf.config.list_physical_devices('GPU'))","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-09-22T19:26:05.413463Z","iopub.execute_input":"2026-09-22T19:26:05.413889Z","iopub.status.idle":"2026-09-22T19:26:05.419238Z","shell.execute_reply.started":"2026-09-22T19:26:05.413859Z","shell.execute_reply":"2026-09-22T19:26:05.418438Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load the official CIFAR-10 dataset\n(x_train, y_train), (x_test, y_test) = tf.keras.datasets.cifar10.load_data()\n\nprint(\"Training images:\", x_train.shape)\nprint(\"Training labels:\", y_train.shape)\nprint(\"Test images:\", x_test.shape)\nprint(\"Test labels:\", y_test.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-22T19:26:05.420413Z","iopub.execute_input":"2026-09-22T19:26:05.420672Z","iopub.status.idle":"2026-09-22T19:59:51.416825Z","shell.execute_reply.started":"2026-09-22T19:26:05.420639Z","shell.execute_reply":"2026-09-22T19:59:51.416142Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Normalize pixel values from [0, 255] to [0, 1]\nx_train = x_train.astype(\"float32\") / 255.0\nx_test = x_test.astype(\"float32\") / 255.0\n\n# Data augmentation used only during training\ndata_augmentation = tf.keras.Sequential([\n    layers.RandomFlip(\"horizontal\"),\n    layers.RandomTranslation(height_factor=0.1, width_factor=0.1),\n], name=\"data_augmentation\")\n\nprint(\"Training pixel range:\", x_train.min(), \"to\", x_train.max())\nprint(\"Test pixel range:\", x_test.min(), \"to\", x_test.max())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-22T19:59:51.418231Z","iopub.execute_input":"2026-09-22T19:59:51.418533Z","iopub.status.idle":"2026-09-22T19:59:52.431944Z","shell.execute_reply.started":"2026-09-22T19:59:51.418509Z","shell.execute_reply":"2026-09-22T19:59:52.431281Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Residual block\ndef residual_block(x, filters, stride=1):\n    shortcut = x\n\n    x = layers.Conv2D(\n        filters, 3,\n        strides=stride,\n        padding=\"same\",\n        use_bias=False,\n        kernel_initializer=\"he_normal\"\n    )(x)\n\n    x = layers.BatchNormalization()(x)\n    x = layers.ReLU()(x)\n\n    x = layers.Conv2D(\n        filters, 3,\n        strides=1,\n        padding=\"same\",\n        use_bias=False,\n        kernel_initializer=\"he_normal\"\n    )(x)\n\n    x = layers.BatchNormalization()(x)\n\n    # Match dimensions if needed\n    if stride != 1 or shortcut.shape[-1] != filters:\n        shortcut = layers.Conv2D(\n            filters, 1,\n            strides=stride,\n            padding=\"same\",\n            use_bias=False,\n            kernel_initializer=\"he_normal\"\n        )(shortcut)\n\n        shortcut = layers.BatchNormalization()(shortcut)\n\n    x = layers.Add()([x, shortcut])\n    x = layers.ReLU()(x)\n\n    return x\n\n\n# Build CIFAR-10 ResNet-style model\ninputs = keras.Input(shape=(32, 32, 3))\n\nx = data_augmentation(inputs)\n\nx = layers.Conv2D(\n    64, 3,\n    padding=\"same\",\n    use_bias=False,\n    kernel_initializer=\"he_normal\"\n)(x)\n\nx = layers.BatchNormalization()(x)\nx = layers.ReLU()(x)\n\n# Stage 1\nx = residual_block(x, 64)\nx = residual_block(x, 64)\n\n# Stage 2\nx = residual_block(x, 128, stride=2)\nx = residual_block(x, 128)\n\n# Stage 3\nx = residual_block(x, 256, stride=2)\nx = residual_block(x, 256)\n\n# Classification head\nx = layers.GlobalAveragePooling2D()(x)\nx = layers.Dropout(0.3)(x)\n\noutputs = layers.Dense(\n    10,\n    activation=\"softmax\",\n    kernel_initializer=\"he_normal\"\n)(x)\n\nmodel = keras.Model(inputs, outputs)\n\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-22T19:59:52.433892Z","iopub.execute_input":"2026-09-22T19:59:52.434146Z","iopub.status.idle":"2026-09-22T19:59:54.215817Z","shell.execute_reply.started":"2026-09-22T19:59:52.434125Z","shell.execute_reply":"2026-09-22T19:59:54.215045Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Compile the model\noptimizer = tf.keras.optimizers.AdamW(\n    learning_rate=1e-3,\n    weight_decay=1e-4\n)\n\nmodel.compile(\n    optimizer=optimizer,\n    loss=\"sparse_categorical_crossentropy\",\n    metrics=[\"accuracy\"]\n)\n\nprint(\"Model compiled successfully.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-22T19:59:54.216847Z","iopub.execute_input":"2026-09-22T19:59:54.217163Z","iopub.status.idle":"2026-09-22T19:59:54.230589Z","shell.execute_reply.started":"2026-09-22T19:59:54.21714Z","shell.execute_reply":"2026-09-22T19:59:54.229906Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Training callbacks\n\ncallbacks = [\n    tf.keras.callbacks.ReduceLROnPlateau(\n        monitor=\"val_accuracy\",\n        factor=0.5,\n        patience=5,\n        min_lr=1e-6,\n        verbose=1\n    ),\n\n    tf.keras.callbacks.EarlyStopping(\n        monitor=\"val_accuracy\",\n        patience=15,\n        restore_best_weights=True,\n        verbose=1\n    ),\n\n    tf.keras.callbacks.ModelCheckpoint(\n        \"best_cifar10_model.keras\",\n        monitor=\"val_accuracy\",\n        save_best_only=True,\n        verbose=1\n    )\n]\n\nprint(\"Callbacks ready.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-22T19:59:54.231458Z","iopub.execute_input":"2026-09-22T19:59:54.231758Z","iopub.status.idle":"2026-09-22T19:59:54.237843Z","shell.execute_reply.started":"2026-09-22T19:59:54.231694Z","shell.execute_reply":"2026-09-22T19:59:54.23724Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model.fit(\n    x_train,\n    y_train,\n    batch_size=128,\n    epochs=50,\n    validation_split=0.1,\n    callbacks=callbacks,\n    verbose=1\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-22T19:59:54.238626Z","iopub.execute_input":"2026-09-22T19:59:54.239034Z","iopub.status.idle":"2026-09-22T20:40:58.638567Z","shell.execute_reply.started":"2026-09-22T19:59:54.239012Z","shell.execute_reply":"2026-09-22T20:40:58.63797Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_loss, test_accuracy = model.evaluate(\n    x_test,\n    y_test,\n    verbose=1\n)\n\nprint(f\"Test loss: {test_loss:.4f}\")\nprint(f\"Test accuracy: {test_accuracy:.4f}\")\nprint(f\"Test accuracy (%): {test_accuracy * 100:.2f}%\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-22T20:40:58.63961Z","iopub.execute_input":"2026-09-22T20:40:58.640502Z","iopub.status.idle":"2026-09-22T20:41:02.325224Z","shell.execute_reply.started":"2026-09-22T20:40:58.640472Z","shell.execute_reply":"2026-09-22T20:41:02.324607Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\nfor root, dirs, files in os.walk(\"/kaggle/input\"):\n    for file in files:\n        if \"test.7z\" in file or \"sampleSubmission.csv\" in file:\n            print(os.path.join(root, file))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-22T20:41:02.326078Z","iopub.execute_input":"2026-09-22T20:41:02.326371Z","iopub.status.idle":"2026-09-22T20:41:02.337637Z","shell.execute_reply.started":"2026-09-22T20:41:02.326341Z","shell.execute_reply":"2026-09-22T20:41:02.336854Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sample_path = \"/kaggle/input/competitions/cifar-10/sampleSubmission.csv\"\n\nsample_submission = pd.read_csv(sample_path)\n\nprint(sample_submission.head())\nprint(\"Rows:\", len(sample_submission))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-22T20:41:02.339813Z","iopub.execute_input":"2026-09-22T20:41:02.340417Z","iopub.status.idle":"2026-09-22T20:41:02.425824Z","shell.execute_reply.started":"2026-09-22T20:41:02.340394Z","shell.execute_reply":"2026-09-22T20:41:02.425142Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"try:\n    import libarchive\n    print(\"libarchive is ready.\")\nexcept ImportError:\n    print(\"libarchive is not installed.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-22T20:43:06.304892Z","iopub.execute_input":"2026-09-22T20:43:06.305308Z","iopub.status.idle":"2026-09-22T20:43:06.310539Z","shell.execute_reply.started":"2026-09-22T20:43:06.305278Z","shell.execute_reply":"2026-09-22T20:43:06.309767Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install -q libarchive-c","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-22T20:45:50.449978Z","iopub.execute_input":"2026-09-22T20:45:50.450628Z","iopub.status.idle":"2026-09-22T20:45:55.45913Z","shell.execute_reply.started":"2026-09-22T20:45:50.450596Z","shell.execute_reply":"2026-09-22T20:45:55.458343Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import libarchive\nprint(\"libarchive is ready.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-22T20:48:45.05241Z","iopub.execute_input":"2026-09-22T20:48:45.052809Z","iopub.status.idle":"2026-09-22T20:48:45.111842Z","shell.execute_reply.started":"2026-09-22T20:48:45.052772Z","shell.execute_reply":"2026-09-22T20:48:45.111038Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import io\nfrom PIL import Image\n\narchive_path = \"/kaggle/input/competitions/cifar-10/test.7z\"\n\nclass_names = [\n    \"airplane\", \"automobile\", \"bird\", \"cat\", \"deer\",\n    \"dog\", \"frog\", \"horse\", \"ship\", \"truck\"\n]\n\nbatch_size = 512\n\nbatch_images = []\nbatch_ids = []\n\nall_ids = []\nall_predictions = []\n\nprocessed = 0\n\nwith libarchive.file_reader(archive_path) as archive:\n    for entry in archive:\n\n        # Only process PNG images\n        if not entry.pathname.lower().endswith(\".png\"):\n            continue\n\n        # Read image directly from the .7z archive\n        image_bytes = b\"\".join(entry.get_blocks())\n\n        image = Image.open(io.BytesIO(image_bytes)).convert(\"RGB\")\n        image_array = np.asarray(image, dtype=np.float32) / 255.0\n\n        # Example: test/123.png -> ID = 123\n        image_id = int(\n            os.path.splitext(\n                os.path.basename(entry.pathname)\n            )[0]\n        )\n\n        batch_images.append(image_array)\n        batch_ids.append(image_id)\n\n        # Predict one batch at a time\n        if len(batch_images) == batch_size:\n            batch_array = np.stack(batch_images)\n\n            probabilities = model(\n                batch_array,\n                training=False\n            ).numpy()\n\n            predictions = np.argmax(probabilities, axis=1)\n\n            all_ids.extend(batch_ids)\n            all_predictions.extend(predictions)\n\n            processed += len(batch_images)\n\n            if processed % 10000 == 0:\n                print(f\"Processed {processed:,} images\")\n\n            batch_images = []\n            batch_ids = []\n\n\n# Process the final batch\nif len(batch_images) > 0:\n    batch_array = np.stack(batch_images)\n\n    probabilities = model(\n        batch_array,\n        training=False\n    ).numpy()\n\n    predictions = np.argmax(probabilities, axis=1)\n\n    all_ids.extend(batch_ids)\n    all_predictions.extend(predictions)\n\n    processed += len(batch_images)\n\n\nprint(\"Total images processed:\", processed)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-22T20:50:00.532326Z","iopub.execute_input":"2026-09-22T20:50:00.532813Z","iopub.status.idle":"2026-09-22T20:52:57.176473Z","shell.execute_reply.started":"2026-09-22T20:50:00.53277Z","shell.execute_reply":"2026-09-22T20:52:57.175669Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predicted_labels = [class_names[i] for i in all_predictions]\n\npredictions_df = pd.DataFrame({\n    \"id\": all_ids,\n    \"label\": predicted_labels\n})\n\nprint(predictions_df.head())\nprint(\"Predictions:\", len(predictions_df))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-22T20:54:45.115334Z","iopub.execute_input":"2026-09-22T20:54:45.116183Z","iopub.status.idle":"2026-09-22T20:54:45.248086Z","shell.execute_reply.started":"2026-09-22T20:54:45.116151Z","shell.execute_reply":"2026-09-22T20:54:45.247238Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission = sample_submission[[\"id\"]].merge(\n    predictions_df,\n    on=\"id\",\n    how=\"left\"\n)\n\nprint(submission.head())\nprint(\"Rows:\", len(submission))\nprint(\"Missing predictions:\", submission[\"label\"].isna().sum())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-22T20:57:13.364876Z","iopub.execute_input":"2026-09-22T20:57:13.365142Z","iopub.status.idle":"2026-09-22T20:57:13.428079Z","shell.execute_reply.started":"2026-09-22T20:57:13.36512Z","shell.execute_reply":"2026-09-22T20:57:13.427384Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission_path = \"/kaggle/working/submission.csv\"\n\nsubmission.to_csv(submission_path, index=False)\n\nprint(\"Saved:\", submission_path)\nprint(\"Shape:\", submission.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-22T20:57:54.115177Z","iopub.execute_input":"2026-09-22T20:57:54.115934Z","iopub.status.idle":"2026-09-22T20:57:54.346099Z","shell.execute_reply.started":"2026-09-22T20:57:54.115903Z","shell.execute_reply":"2026-09-22T20:57:54.345315Z"}},"outputs":[],"execution_count":null}]}