{"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":[{"sourceId":3649,"databundleVersionId":46718,"sourceType":"competition"}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"### Runtime & environment","metadata":{}},{"cell_type":"code","source":"!pip -q install py7zr","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-09-19T13:15:30.451828Z","iopub.execute_input":"2025-09-19T13:15:30.452407Z","iopub.status.idle":"2025-09-19T13:15:33.662871Z","shell.execute_reply.started":"2025-09-19T13:15:30.452383Z","shell.execute_reply":"2025-09-19T13:15:33.662020Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Imports, config, seeds, class names","metadata":{}},{"cell_type":"code","source":"import os, math, glob, numpy as np, tensorflow as tf, pandas as pd\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\n\n# Reproducibility & performance\nSEED = 1337\ntf.keras.utils.set_random_seed(SEED)\nAUTO = tf.data.AUTOTUNE\ntf.config.optimizer.set_jit(False) \n\n# Hyperparameters\nBATCH_TRAIN = 64\nBATCH_TEST  = 64\nEPOCHS      = 100\nLR          = 1e-2\nMOMENTUM    = 0.9\nWEIGHT_DECAY = 1e-6  # L2 via kernel_regularizer\nNUM_CLASSES = 10\nCLASS_NAMES = ['airplane','automobile','bird','cat','deer','dog','frog','horse','ship','truck']\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T13:15:33.664802Z","iopub.execute_input":"2025-09-19T13:15:33.665137Z","iopub.status.idle":"2025-09-19T13:15:33.694960Z","shell.execute_reply.started":"2025-09-19T13:15:33.665094Z","shell.execute_reply":"2025-09-19T13:15:33.694403Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Loads official CIFAR-10 (train/test) via Keras","metadata":{}},{"cell_type":"code","source":"(x_train, y_train), (x_test, y_test) = keras.datasets.cifar10.load_data()\ny_train = keras.utils.to_categorical(y_train, NUM_CLASSES)\ny_test  = keras.utils.to_categorical(y_test,  NUM_CLASSES)\n\nprint(x_train.shape, y_train.shape, x_test.shape, y_test.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T13:15:33.695614Z","iopub.execute_input":"2025-09-19T13:15:33.695828Z","iopub.status.idle":"2025-09-19T13:15:35.930640Z","shell.execute_reply.started":"2025-09-19T13:15:33.695812Z","shell.execute_reply":"2025-09-19T13:15:35.929784Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Augmentations & tf.data pipelines","metadata":{}},{"cell_type":"code","source":"train_aug = keras.Sequential([\n    layers.RandomFlip(\"horizontal\"),\n    layers.RandomTranslation(0.05, 0.05, fill_mode=\"reflect\"),\n    layers.RandomZoom(0.05, 0.05, fill_mode=\"reflect\"),\n    layers.RandomContrast(0.1),\n    layers.RandomBrightness(0.1),\n])\n\ndef preprocess(x, y=None):\n    x = tf.cast(x, tf.float32) / 255.0\n    return (x, y) if y is not None else x\n\ndef make_ds(x, y, train=False, batch=100):\n    ds = tf.data.Dataset.from_tensor_slices((x, y))\n    if train:\n        ds = ds.shuffle(10000, seed=SEED, reshuffle_each_iteration=True)\n        ds = ds.map(lambda a,b: (train_aug(a), b), num_parallel_calls=AUTO)\n    ds = ds.map(lambda a,b: (preprocess(a), b), num_parallel_calls=AUTO)\n    ds = ds.batch(batch).prefetch(AUTO)\n    return ds\n\ntrain_ds = make_ds(x_train, y_train, train=True,  batch=BATCH_TRAIN)\ntest_ds  = make_ds(x_test,  y_test,  train=False, batch=BATCH_TEST)  # used as validation proxy for Kaggle\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T13:15:35.932565Z","iopub.execute_input":"2025-09-19T13:15:35.932770Z","iopub.status.idle":"2025-09-19T13:15:37.053840Z","shell.execute_reply.started":"2025-09-19T13:15:35.932753Z","shell.execute_reply":"2025-09-19T13:15:37.053275Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Cutout","metadata":{}},{"cell_type":"code","source":"USE_CUTOUT = False  # set True for a small boost\n\ndef cutout(img, length=8):\n    H = tf.shape(img)[0]; W = tf.shape(img)[1]\n    y = tf.random.uniform([], 0, H, dtype=tf.int32)\n    x = tf.random.uniform([], 0, W, dtype=tf.int32)\n    y1 = tf.clip_by_value(y - length//2, 0, H); y2 = tf.clip_by_value(y + length//2, 0, H)\n    x1 = tf.clip_by_value(x - length//2, 0, W); x2 = tf.clip_by_value(x + length//2, 0, W)\n    mask = tf.ones([y2-y1, x2-x1, 3], dtype=img.dtype)\n    paddings = [[y1, H - y2], [x1, W - x2], [0, 0]]\n    mask = tf.pad(mask, paddings, constant_values=0)\n    return img * (1 - mask)\n\nif USE_CUTOUT:\n    def _train_map(a, b):\n        a = cutout(a, length=8)\n        return a, b\n    train_ds = train_ds.map(_train_map, num_parallel_calls=AUTO).prefetch(AUTO)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T13:15:37.054525Z","iopub.execute_input":"2025-09-19T13:15:37.054726Z","iopub.status.idle":"2025-09-19T13:15:37.060603Z","shell.execute_reply.started":"2025-09-19T13:15:37.054710Z","shell.execute_reply":"2025-09-19T13:15:37.059782Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Advanced CNN","metadata":{}},{"cell_type":"code","source":"L2 = keras.regularizers.l2(WEIGHT_DECAY)\n\ndef conv_bn_relu(x, filters, k=3, bn=False):\n    x = layers.Conv2D(filters, k, padding=\"same\", use_bias=not bn,\n                      kernel_regularizer=L2)(x)\n    if bn:\n        x = layers.BatchNormalization()(x)\n    return layers.ReLU()(x)\n\ninputs = keras.Input(shape=(32, 32, 3))\nx = inputs\n\n# Block 1: 3 convs -> MaxPool\nx = conv_bn_relu(x, 64*2, bn=True)   # conv1 + BN\nx = conv_bn_relu(x, 64*2)            # conv2\nx = conv_bn_relu(x, 64*2)            # conv3\nx = layers.MaxPooling2D(2)(x)\n\n# Block 2: 3 convs -> MaxPool -> Dropout\nx = conv_bn_relu(x, 128*2, bn=True)  # conv4 + BN\nx = conv_bn_relu(x, 128*2)           # conv5\nx = conv_bn_relu(x, 128*2)           # conv6\nx = layers.MaxPooling2D(2)(x)\nx = layers.Dropout(0.2)(x)\n\n# Block 3: 3 convs -> MaxPool -> Dropout\nx = conv_bn_relu(x, 256*2, bn=True)  # conv7 + BN\nx = conv_bn_relu(x, 256*2)           # conv8\nx = conv_bn_relu(x, 256*2)           # conv9\nx = layers.MaxPooling2D(2)(x)\nx = layers.Dropout(0.2)(x)\n\n# Classifier: 4*4*512 = 8192 -> 8192 -> 4096 -> 10\nx = layers.Flatten()(x)\nx = layers.Dense(4096*2, activation=\"relu\", kernel_regularizer=L2)(x)\nx = layers.Dense(2048*2, activation=\"relu\", kernel_regularizer=L2)(x)\nx = layers.Dropout(0.2)(x)\noutputs = layers.Dense(NUM_CLASSES, activation=\"softmax\")(x)\n\nmodel = keras.Model(inputs, outputs)\nmodel.summary()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T13:15:37.061403Z","iopub.execute_input":"2025-09-19T13:15:37.061640Z","iopub.status.idle":"2025-09-19T13:15:37.217339Z","shell.execute_reply.started":"2025-09-19T13:15:37.061617Z","shell.execute_reply":"2025-09-19T13:15:37.216769Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Optimizer & compile (SGD + momentum)","metadata":{}},{"cell_type":"code","source":"opt = keras.optimizers.SGD(learning_rate=LR, momentum=MOMENTUM, nesterov=False)\n\nmodel.compile(\n    optimizer=opt,\n    loss=keras.losses.CategoricalCrossentropy(label_smoothing=0.0),\n    metrics=[\"accuracy\"]\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T13:15:37.217948Z","iopub.execute_input":"2025-09-19T13:15:37.218198Z","iopub.status.idle":"2025-09-19T13:15:37.229485Z","shell.execute_reply.started":"2025-09-19T13:15:37.218175Z","shell.execute_reply":"2025-09-19T13:15:37.228795Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Callbacks","metadata":{}},{"cell_type":"code","source":"ckpt = keras.callbacks.ModelCheckpoint(\n    filepath=\"adv_best.weights.h5\",\n    monitor=\"val_accuracy\",\n    save_best_only=True,\n    save_weights_only=True,\n)\nplateau = keras.callbacks.ReduceLROnPlateau(\n    monitor=\"val_loss\", factor=0.1, patience=10, min_lr=1e-5, verbose=1\n)\nes = keras.callbacks.EarlyStopping(\n    monitor=\"val_accuracy\", patience=20, restore_best_weights=True\n)\nlog = keras.callbacks.CSVLogger(\"adv_training_log.csv\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T13:15:37.230250Z","iopub.execute_input":"2025-09-19T13:15:37.230524Z","iopub.status.idle":"2025-09-19T13:15:37.234427Z","shell.execute_reply.started":"2025-09-19T13:15:37.230507Z","shell.execute_reply":"2025-09-19T13:15:37.233812Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Train","metadata":{}},{"cell_type":"code","source":"history = model.fit(\n    train_ds,\n    validation_data=test_ds,\n    epochs=EPOCHS,\n    callbacks=[ckpt, plateau, es, log]\n)\nprint(\"Final val_acc (official test):\", round(float(history.history[\"val_accuracy\"][-1]), 4))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T13:15:37.235162Z","iopub.execute_input":"2025-09-19T13:15:37.235411Z","iopub.status.idle":"2025-09-19T14:56:19.961036Z","shell.execute_reply.started":"2025-09-19T13:15:37.235388Z","shell.execute_reply":"2025-09-19T14:56:19.960404Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Evaluate on official test (your Kaggle score estimate)","metadata":{}},{"cell_type":"code","source":"loss, acc = model.evaluate(test_ds, verbose=0)\nprint(\"Official CIFAR-10 test accuracy (Kaggle-score estimate):\", round(float(acc), 4))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T14:56:19.963143Z","iopub.execute_input":"2025-09-19T14:56:19.963372Z","iopub.status.idle":"2025-09-19T14:56:24.743018Z","shell.execute_reply.started":"2025-09-19T14:56:19.963355Z","shell.execute_reply":"2025-09-19T14:56:24.742348Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### locate & extract test.7z","metadata":{}},{"cell_type":"code","source":"import py7zr, os, glob\n\ninput_dir = \"/kaggle/input/cifar-10\"\ntest_7z = os.path.join(input_dir, \"test.7z\")\n\nif os.path.exists(test_7z):\n    with py7zr.SevenZipFile(test_7z, mode='r') as z:\n        z.extractall(path=\".\")\n    print(\"Extracted test images:\", len(glob.glob(\"test/*.png\")))\nelse:\n    print(\"test.7z not found at\", test_7z)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T15:04:52.780848Z","iopub.execute_input":"2025-09-19T15:04:52.781105Z","iopub.status.idle":"2025-09-19T15:06:56.524264Z","shell.execute_reply.started":"2025-09-19T15:04:52.781087Z","shell.execute_reply":"2025-09-19T15:06:56.523485Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Build submission.csv","metadata":{}},{"cell_type":"code","source":"from PIL import Image\n\ndef load_png(fp):\n    im = Image.open(fp).convert(\"RGB\")\n    # Should already be 32x32; resize defensively just in case\n    im = im.resize((32,32), resample=Image.BILINEAR)\n    arr = np.asarray(im).astype(np.float32) / 255.0\n    return arr\n\ntest_files = sorted(glob.glob(\"test/*.png\"), key=lambda p: int(os.path.splitext(os.path.basename(p))[0]))\n\nBATCH = 1024\npred_labels = []\nfor i in range(0, len(test_files), BATCH):\n    batch_files = test_files[i:i+BATCH]\n    batch = np.stack([load_png(f) for f in batch_files], axis=0)\n    probs = model.predict(batch, verbose=0)\n    idx  = np.argmax(probs, axis=1)\n    pred_labels.extend([CLASS_NAMES[j] for j in idx])\n\nids = [int(os.path.splitext(os.path.basename(f))[0]) for f in test_files]\nsub = pd.DataFrame({\"id\": ids, \"label\": pred_labels})\nsub.to_csv(\"submission.csv\", index=False)\nsub.head()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T15:07:39.087388Z","iopub.execute_input":"2025-09-19T15:07:39.087962Z","iopub.status.idle":"2025-09-19T15:11:24.677064Z","shell.execute_reply.started":"2025-09-19T15:07:39.087938Z","shell.execute_reply":"2025-09-19T15:11:24.676435Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### quick sanity checks on submission","metadata":{}},{"cell_type":"code","source":"# Check format and label set\nassert set(sub.columns)=={\"id\",\"label\"}\nassert set(sub[\"label\"].unique()).issubset(set(CLASSES))\nassert sub[\"id\"].min()==1 and sub[\"id\"].max()==300000 and len(sub)==300000\nprint(\"Submission looks well-formed:\", sub.shape, \"rows\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-19T15:11:57.370050Z","iopub.execute_input":"2025-09-19T15:11:57.370345Z","iopub.status.idle":"2025-09-19T15:11:57.408869Z","shell.execute_reply.started":"2025-09-19T15:11:57.370326Z","shell.execute_reply":"2025-09-19T15:11:57.408281Z"}},"outputs":[],"execution_count":null}]}