{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","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"},{"sourceId":9587591,"sourceType":"datasetVersion","datasetId":5847039}],"dockerImageVersionId":30775,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-10-09T15:10:52.193826Z","iopub.execute_input":"2024-10-09T15:10:52.195060Z","iopub.status.idle":"2024-10-09T15:10:52.201772Z","shell.execute_reply.started":"2024-10-09T15:10:52.195016Z","shell.execute_reply":"2024-10-09T15:10:52.200710Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport re\nimport numpy as np\nimport pandas as pd\nimport tensorflow as tf\nimport matplotlib.pyplot as plt\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score\nfrom sklearn.preprocessing import LabelEncoder\n\nfrom pathlib import Path\nfrom typing import Dict,Optional, List, Tuple\n\nplt.style.use('ggplot')","metadata":{"execution":{"iopub.status.busy":"2024-10-09T15:10:55.611599Z","iopub.execute_input":"2024-10-09T15:10:55.612031Z","iopub.status.idle":"2024-10-09T15:10:55.620542Z","shell.execute_reply.started":"2024-10-09T15:10:55.611991Z","shell.execute_reply":"2024-10-09T15:10:55.619550Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images_folder = Path('/kaggle/input/extracted')\ninput_folder = Path('/kaggle/input/cifar-10')\n\nIMG_HEIGHT = 32\nIMG_WIDTH = 32\nN_CLASSES = 10\nBATCH_SIZE = 64\nEPOCHS = 4","metadata":{"execution":{"iopub.status.busy":"2024-10-09T15:50:34.843523Z","iopub.execute_input":"2024-10-09T15:50:34.843947Z","iopub.status.idle":"2024-10-09T15:50:34.849046Z","shell.execute_reply.started":"2024-10-09T15:50:34.843910Z","shell.execute_reply":"2024-10-09T15:50:34.848049Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load labels\nlabels_dat = pd.read_csv(input_folder/'trainLabels.csv',index_col=['id']).iloc[:,0]\n\n# build encoder from labels\nlabel_encoder = LabelEncoder().fit(labels_dat)\nclasses = label_encoder.classes_\nprint('Classes in CIFAR10')\nprint(classes)","metadata":{"execution":{"iopub.status.busy":"2024-10-09T15:50:36.681450Z","iopub.execute_input":"2024-10-09T15:50:36.682205Z","iopub.status.idle":"2024-10-09T15:50:36.708332Z","shell.execute_reply.started":"2024-10-09T15:50:36.682162Z","shell.execute_reply":"2024-10-09T15:50:36.707275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_data_from_npz(filepath:Path) -> Tuple[np.ndarray]:\n    npz_out = np.load(filepath)\n    return npz_out['images'],npz_out['ids']","metadata":{"execution":{"iopub.status.busy":"2024-10-09T15:50:41.804756Z","iopub.execute_input":"2024-10-09T15:50:41.805125Z","iopub.status.idle":"2024-10-09T15:50:41.810079Z","shell.execute_reply.started":"2024-10-09T15:50:41.805090Z","shell.execute_reply":"2024-10-09T15:50:41.809002Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load images \nimages, ids = load_data_from_npz(images_folder/'train.npz')\n\n# get corresponding labels\nlabels = label_encoder.transform(labels_dat.loc[ids])","metadata":{"execution":{"iopub.status.busy":"2024-10-09T15:50:53.378298Z","iopub.execute_input":"2024-10-09T15:50:53.378925Z","iopub.status.idle":"2024-10-09T15:50:55.990805Z","shell.execute_reply.started":"2024-10-09T15:50:53.378879Z","shell.execute_reply":"2024-10-09T15:50:55.989616Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Preprocessing\ndef preprocess_images(images:np.ndarray) -> np.ndarray:\n    images = images.astype(np.float32)\n    return tf.keras.applications.resnet50.preprocess_input(images)\n\nX = preprocess_images(images)","metadata":{"execution":{"iopub.status.busy":"2024-10-09T15:51:01.231547Z","iopub.execute_input":"2024-10-09T15:51:01.232456Z","iopub.status.idle":"2024-10-09T15:51:01.566495Z","shell.execute_reply.started":"2024-10-09T15:51:01.232410Z","shell.execute_reply":"2024-10-09T15:51:01.565703Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def classifier_module(inputs):\n    '''\n    Defines the final dense layers followed by the softmax layer for classification\n    '''\n    x = tf.keras.layers.GlobalAveragePooling2D()(inputs)\n    x = tf.keras.layers.Dense(1024, activation=\"relu\")(x)\n    x = tf.keras.layers.Dense(512, activation=\"relu\")(x)\n    x = tf.keras.layers.Dense(N_CLASSES, activation=\"softmax\", name=\"classification\")(x)\n    return x\n\ndef construct_model() -> tf.keras.Model:\n    '''\n    Builds a resnet50 based classification model with the specified hyperparameters\n        \n    Returns\n    -----------\n    model: tf.keras.Model\n        A compliled keras model\n    '''\n    \n    inputs = tf.keras.Input(shape=(IMG_WIDTH,IMG_HEIGHT,3))\n    resize = tf.keras.layers.UpSampling2D(size=(7,7))(inputs)\n    \n    resnet_features = tf.keras.applications.resnet.ResNet50(\n        input_shape=(224,224,3),\n        include_top=False,\n        weights='imagenet'\n    )(resize)\n    \n    classification_output = classifier_module(resnet_features)\n    \n    model = tf.keras.Model(inputs=inputs,outputs=classification_output)\n    \n    # compile\n    model.compile(\n        optimizer=tf.keras.optimizers.SGD(),\n        loss = 'sparse_categorical_crossentropy',\n        metrics=['accuracy']\n    )\n    \n    return model","metadata":{"execution":{"iopub.status.busy":"2024-10-09T15:51:06.342935Z","iopub.execute_input":"2024-10-09T15:51:06.343721Z","iopub.status.idle":"2024-10-09T15:51:06.354174Z","shell.execute_reply.started":"2024-10-09T15:51:06.343675Z","shell.execute_reply":"2024-10-09T15:51:06.353093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# build model\ntf.keras.backend.clear_session()        \nmodel = construct_model()\nprint(model.summary())","metadata":{"execution":{"iopub.status.busy":"2024-10-09T15:51:12.915988Z","iopub.execute_input":"2024-10-09T15:51:12.916377Z","iopub.status.idle":"2024-10-09T15:51:15.427747Z","shell.execute_reply.started":"2024-10-09T15:51:12.916337Z","shell.execute_reply":"2024-10-09T15:51:15.426808Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#further divide into train and validation splits for early stopping\n# stratified on the labels\nX_train,X_val,y_train,y_val = train_test_split(\n    X,labels,test_size=0.1,random_state=1,\n    stratify = labels\n)\n\n# train model\nhistory = model.fit(\n    X_train,\n    y_train,\n    batch_size=BATCH_SIZE,\n    epochs=EPOCHS,\n    validation_data=(X_val, y_val),\n    verbose=True\n)","metadata":{"execution":{"iopub.status.busy":"2024-10-09T15:51:21.224382Z","iopub.execute_input":"2024-10-09T15:51:21.225455Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# save model\nmodel.save_weights(f'cifar10_resnet_{EPOCHS}-epochs.h5')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Test prediction","metadata":{}},{"cell_type":"code","source":"# load the test set images\ntest_images, test_ids = load_data_from_npz(images_folder/'test.npz')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time \nfrom tqdm import tqdm\n\n# get prediction probabilities\n# using for loop to prevent out-of-memory issues when using predict\nTEST_BATCH_SIZE=1000\nbatch_vectors= []\n\nfor i in tqdm(range(0,test_images.shape[0],TEST_BATCH_SIZE)):\n    #print(f\" Processing Batch {i//TEST_BATCH_SIZE + 1}\")\n    batch_X = preprocess_images(test_images[i:i+TEST_BATCH_SIZE,...])\n    batch_vectors.append(\n        model.predict(batch_X, verbose=False,batch_size=TEST_BATCH_SIZE)\n    )\n    \ntest_pred_probs = np.concatenate(batch_vectors)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# get prediction labels \ntest_preds = test_pred_probs.argmax(axis=1)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# creating submission file\nsubmission = pd.DataFrame({\n    'id': test_ids,\n    'label':label_encoder.inverse_transform(test_preds)\n})\nsubmission.to_csv('submission.csv',index=False)","metadata":{},"execution_count":null,"outputs":[]}]}