{"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":"code","source":"import numpy as np, tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\n\nEPOCHS, BATCH, PEAK_LR, WD = 200, 128, 1e-3, 5e-4\n\n# --- train data (official CIFAR-10 == competition train set) ---\n(x_train, y_train), (x_test, y_test) = keras.datasets.cifar10.load_data()\nx_train = x_train.astype(\"float32\") / 255.0\nx_test  = x_test.astype(\"float32\")  / 255.0\ny_train_oh = keras.utils.to_categorical(y_train, 10)   # one-hot (needed for label smoothing)\ny_test_oh  = keras.utils.to_categorical(y_test, 10)\n\n# --- augmentation: reflect-pad+crop, flip (basic) + Cutout (advanced, required) ---\ndef augment(image, label):\n    image = tf.pad(image, [[4,4],[4,4],[0,0]], mode=\"REFLECT\")\n    image = tf.image.random_crop(image, [32,32,3])\n    image = tf.image.random_flip_left_right(image)\n    size = 16\n    cy = tf.random.uniform([], 0, 32, tf.int32); cx = tf.random.uniform([], 0, 32, tf.int32)\n    y1 = tf.clip_by_value(cy-size//2,0,32); y2 = tf.clip_by_value(cy+size//2,0,32)\n    x1 = tf.clip_by_value(cx-size//2,0,32); x2 = tf.clip_by_value(cx+size//2,0,32)\n    yy = tf.range(32)[:,None]; xx = tf.range(32)[None,:]\n    mask = tf.logical_not((yy>=y1)&(yy<y2)&(xx>=x1)&(xx<x2))\n    image = image * tf.cast(mask, image.dtype)[:,:,None]\n    return image, label\n\ntrain_ds = (tf.data.Dataset.from_tensor_slices((x_train, y_train_oh))\n            .shuffle(50000).map(augment, tf.data.AUTOTUNE)\n            .batch(BATCH).prefetch(tf.data.AUTOTUNE))\n\n# --- my custom pre-activation residual network ---\ndef preact_block(x, filters, stride=1):\n    y = layers.BatchNormalization()(x); y = layers.Activation(\"relu\")(y)\n    shortcut = x\n    if stride != 1 or x.shape[-1] != filters:\n        shortcut = layers.Conv2D(filters, 1, strides=stride, use_bias=False)(y)\n    y = layers.Conv2D(filters, 3, strides=stride, padding=\"same\", use_bias=False)(y)\n    y = layers.BatchNormalization()(y); y = layers.Activation(\"relu\")(y)\n    y = layers.Conv2D(filters, 3, padding=\"same\", use_bias=False)(y)\n    return layers.Add()([shortcut, y])\n\ninputs = keras.Input((32,32,3))\nx = layers.Conv2D(64, 3, padding=\"same\", use_bias=False)(inputs)\nfor filters, n_blocks, stride in [(64,2,1),(128,2,2),(256,2,2),(512,2,2)]:\n    for i in range(n_blocks):\n        x = preact_block(x, filters, stride=stride if i==0 else 1)\nx = layers.BatchNormalization()(x); x = layers.Activation(\"relu\")(x)\nx = layers.GlobalAveragePooling2D()(x)\nx = layers.Dropout(0.2)(x)\noutputs = layers.Dense(10, activation=\"softmax\")(x)\nmodel = keras.Model(inputs, outputs)\n\n# --- cosine annealing with warmup + AdamW ---\nsteps = int(np.ceil(50000/BATCH)); warmup = 5*steps\nschedule = keras.optimizers.schedules.CosineDecay(\n    initial_learning_rate=1e-5, warmup_target=PEAK_LR, warmup_steps=warmup,\n    decay_steps=EPOCHS*steps - warmup, alpha=0.0)\nmodel.compile(optimizer=keras.optimizers.AdamW(learning_rate=schedule, weight_decay=WD),\n              loss=keras.losses.CategoricalCrossentropy(label_smoothing=0.1),\n              metrics=[\"accuracy\"])\nmodel.summary()\n\nmodel.fit(train_ds, validation_data=(x_test, y_test_oh), epochs=EPOCHS, verbose=2)\nprint(\"Estimated Kaggle score:\", model.evaluate(x_test, y_test_oh, verbose=0)[1])\nmodel.save(\"cifar10_challenge.keras\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-10-01T18:23:58.465655Z","iopub.execute_input":"2026-10-01T18:23:58.465933Z","iopub.status.idle":"2026-10-01T20:59:28.174364Z","shell.execute_reply.started":"2026-10-01T18:23:58.465911Z","shell.execute_reply":"2026-10-01T20:59:28.173609Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install py7zr -q\nimport py7zr, glob\npath_to_7z = glob.glob('/kaggle/input/**/test.7z', recursive=True)[0]\nwith py7zr.SevenZipFile(path_to_7z, mode='r') as z:\n    z.extractall(path='/tmp')\nprint(len(glob.glob('/tmp/test/*.png')))   # expect 300000","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-01T20:59:28.17553Z","iopub.execute_input":"2026-10-01T20:59:28.176027Z","iopub.status.idle":"2026-10-01T21:02:58.552972Z","shell.execute_reply.started":"2026-10-01T20:59:28.175979Z","shell.execute_reply":"2026-10-01T21:02:58.551988Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np, pandas as pd, tensorflow as tf\n\nclass_names = ['airplane','automobile','bird','cat','deer','dog','frog','horse','ship','truck']\nfiles = tf.constant([f'/tmp/test/{i}.png' for i in range(1, 300001)])\n\ndef build_ds(flip):\n    def load(path):\n        img = tf.cast(tf.io.decode_png(tf.io.read_file(path), channels=3), tf.float32)/255.0\n        return tf.image.flip_left_right(img) if flip else img\n    return (tf.data.Dataset.from_tensor_slices(files)\n            .map(load, tf.data.AUTOTUNE).batch(512).prefetch(tf.data.AUTOTUNE))\n\nprobs  = model.predict(build_ds(False), verbose=1)      # original\nprobs += model.predict(build_ds(True),  verbose=1)      # + horizontal flip (TTA)\npred_labels = [class_names[k] for k in probs.argmax(1)]\n\nsubmission = pd.DataFrame({'id': range(1, 300001), 'label': pred_labels})\nsubmission.to_csv('submission.csv', index=False)\nprint(submission.head()); print(submission.shape)   # (300000, 2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-01T21:02:58.555172Z","iopub.execute_input":"2026-10-01T21:02:58.555504Z","iopub.status.idle":"2026-10-01T21:05:32.155757Z","shell.execute_reply.started":"2026-10-01T21:02:58.555476Z","shell.execute_reply":"2026-10-01T21:05:32.155006Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nprint(\"exists:\", os.path.exists('submission.csv'))\n!kaggle competitions submit -c cifar-10 -f submission.csv -m \"Custom pre-act ResNet, AdamW, cosine+warmup, Cutout, TTA\"\n!kaggle competitions submissions -c cifar-10","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-01T21:05:32.156943Z","iopub.execute_input":"2026-10-01T21:05:32.157234Z","iopub.status.idle":"2026-10-01T21:05:35.583729Z","shell.execute_reply.started":"2026-10-01T21:05:32.157209Z","shell.execute_reply":"2026-10-01T21:05:35.582951Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!kaggle competitions submissions -c cifar-10","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-01T21:05:35.585263Z","iopub.execute_input":"2026-10-01T21:05:35.585739Z","iopub.status.idle":"2026-10-01T21:05:36.389861Z","shell.execute_reply.started":"2026-10-01T21:05:35.585708Z","shell.execute_reply":"2026-10-01T21:05:36.389095Z"}},"outputs":[],"execution_count":null}]}