{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":71608,"databundleVersionId":7895811,"sourceType":"competition"}],"dockerImageVersionId":30665,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"EPOCHS = 25\nBATCH_SIZE = 32","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:35:35.673981Z","iopub.execute_input":"2024-03-16T07:35:35.674462Z","iopub.status.idle":"2024-03-16T07:35:48.958165Z","shell.execute_reply.started":"2024-03-16T07:35:35.674433Z","shell.execute_reply":"2024-03-16T07:35:48.957333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#reading ground truth\n\ndf = pd.read_csv('/kaggle/input/aiml-general-championship/KCDH2024_Training_GroundTruth.csv')\nprint(df.head())\nprint(len(df))\nprint(df.columns)","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:35:48.960168Z","iopub.execute_input":"2024-03-16T07:35:48.961191Z","iopub.status.idle":"2024-03-16T07:35:49.003786Z","shell.execute_reply.started":"2024-03-16T07:35:48.961125Z","shell.execute_reply":"2024-03-16T07:35:49.002894Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label_names = ['MEL', 'NV', 'BCC', 'AKIEC', 'BKL', 'DF', 'VASC']\nlabel_names = sorted(label_names) #sorting\nprint(label_names)","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:35:52.491554Z","iopub.execute_input":"2024-03-16T07:35:52.49201Z","iopub.status.idle":"2024-03-16T07:35:52.497866Z","shell.execute_reply.started":"2024-03-16T07:35:52.491977Z","shell.execute_reply":"2024-03-16T07:35:52.496999Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#adding a jpg extension to file names in csv file\ndf['image'] = df['image'].apply(lambda x: x+ '.jpg')\nprint(df.head())","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:35:53.732144Z","iopub.execute_input":"2024-03-16T07:35:53.73304Z","iopub.status.idle":"2024-03-16T07:35:53.749952Z","shell.execute_reply.started":"2024-03-16T07:35:53.733002Z","shell.execute_reply":"2024-03-16T07:35:53.748932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = df[:9600]\nlen(df)","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:35:54.530284Z","iopub.execute_input":"2024-03-16T07:35:54.530698Z","iopub.status.idle":"2024-03-16T07:35:54.54125Z","shell.execute_reply.started":"2024-03-16T07:35:54.53067Z","shell.execute_reply":"2024-03-16T07:35:54.540335Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import shutil\n\ndata_dir = '/kaggle/working/lesions'\n\n# Empty directory to prevent FileExistsError if the function is run several times\nif os.path.exists(data_dir):\n  shutil.rmtree(data_dir)\n\n# Create the empty dir for each skin lesion\nfor label in label_names:\n    os.makedirs(os.path.join(data_dir, label)) # e.g. /kaggle/working/lesions/MEL","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:35:55.184867Z","iopub.execute_input":"2024-03-16T07:35:55.185708Z","iopub.status.idle":"2024-03-16T07:35:55.192499Z","shell.execute_reply.started":"2024-03-16T07:35:55.185666Z","shell.execute_reply":"2024-03-16T07:35:55.191442Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from shutil import copyfile\nfrom tqdm import tqdm\n\n# Iterate over dataframe and move images to correct folders\nfor index, row in tqdm(df.iterrows(), total=df.shape[0], desc=f'Copying HAM10000 dataset images..'):\n    # Get the image pathname\n    image_name = row['image']  # e.g. ISIC_0024306.jpg\n    \n    # Find which labels are hot for this image (i.e. equal to 1)\n    # This returns a list of indices, should just be one\n    hot_label = row[row == 1].index.tolist()[0]  # e.g. MEL\n    \n#     print(image_name, hot_labels)  # ISIC_0024306.jpg NV\n\n    # Copy the image to the right label directory\n    src_path = os.path.join('/kaggle/input/aiml-general-championship/KCDH2024_Training_Input_10K/KCDH2024_Training_Input_10K', image_name)\n    dst_path = os.path.join(data_dir, hot_label, image_name)\n    \n#     print(src_path)\n#     print(dst_path)\n    \n    copyfile(src_path, dst_path)\n\n#     if index > 10:\n#         break","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:35:55.924216Z","iopub.execute_input":"2024-03-16T07:35:55.924655Z","iopub.status.idle":"2024-03-16T07:37:33.858Z","shell.execute_reply.started":"2024-03-16T07:35:55.924613Z","shell.execute_reply":"2024-03-16T07:37:33.857065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tot = 0\nfor label in label_names:\n    cnt_label = len(os.listdir(os.path.join(data_dir, label)))\n    print(f\"There are {cnt_label} images with label {label}.\")\n    tot += cnt_label\nprint(f\"\\nThere are {tot} total images across all labels.\")","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:37:35.331428Z","iopub.execute_input":"2024-03-16T07:37:35.332321Z","iopub.status.idle":"2024-03-16T07:37:35.344837Z","shell.execute_reply.started":"2024-03-16T07:37:35.332277Z","shell.execute_reply":"2024-03-16T07:37:35.343946Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Calculating Class weights","metadata":{}},{"cell_type":"code","source":"# Start weights at zero\nnum_classes = len(label_names)\nweights = [0] * num_classes  # e.g. [0, 0, 0, .. 0]\n\ntot = 0\nfor idx, label in enumerate(label_names):\n    cnt_label = len(os.listdir(os.path.join(data_dir, label)))\n    weights[idx] = cnt_label  # really a count right now\n    tot += cnt_label\n\n# Calculate class frequencies (we'll use this later to initialize our bias terms)\nclass_frequencies = weights\nclass_frequencies = [ w / tot for w in weights ]  \n\n# Now we have the total counts across all classes, and the \n# weights array is actually counts at the moment.\n# Less frequent classes have higher weights, inversely proportional\nweights = [1.0 / cnt if cnt != 0 else 0 for cnt in weights]\n\n\nif tot != 0:\n    weights = [tot * w / num_classes for w in weights]\nelse:\n    # Handle the case where tot is zero (e.g., by setting weights to a default value)\n    weights = [1.0 / num_classes] * num_classes\n\n\n# Now assign to a class_weight dictionary that Keras expects\nclass_weight = {}\nfor i in range(num_classes):\n    class_weight[i] = weights[i]\n    print(f\"Weight for class {i}: \" + '{:.2f}'.format(weights[i]))","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:37:37.943801Z","iopub.execute_input":"2024-03-16T07:37:37.944513Z","iopub.status.idle":"2024-03-16T07:37:37.960084Z","shell.execute_reply.started":"2024-03-16T07:37:37.944479Z","shell.execute_reply":"2024-03-16T07:37:37.959222Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# The image resizing is determined by what model of EfficientNet we want to use\nIMG_SIZE = 224  # EfficientNetB0, 5.3M parameters","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:37:38.986332Z","iopub.execute_input":"2024-03-16T07:37:38.987313Z","iopub.status.idle":"2024-03-16T07:37:38.991466Z","shell.execute_reply.started":"2024-03-16T07:37:38.987277Z","shell.execute_reply":"2024-03-16T07:37:38.990619Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Now that images are in correct disk folder structure, we can create \n# a tf data dataset easily.  Can return the Train and val/test datasets all at once.\ntrain_ds, val_and_test_ds = tf.keras.utils.image_dataset_from_directory(\n    data_dir,\n    labels=\"inferred\",\n    label_mode=\"categorical\",   # will use categorical_crossentropy loss later\n    class_names=label_names,\n    batch_size=BATCH_SIZE,\n    image_size=(IMG_SIZE, IMG_SIZE),\n    shuffle=True,\n    seed=7,\n    validation_split=0.1,       # Set aside 10% for val & test\n    subset=\"both\",              # Returns a tuple\n    crop_to_aspect_ratio=True,\n)","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:37:39.84038Z","iopub.execute_input":"2024-03-16T07:37:39.84132Z","iopub.status.idle":"2024-03-16T07:37:43.156737Z","shell.execute_reply.started":"2024-03-16T07:37:39.84128Z","shell.execute_reply":"2024-03-16T07:37:43.155874Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"val_and_test_ds_size = len(list(val_and_test_ds))\n\n# Calculate the number of samples for each split\nval_size = int(val_and_test_ds_size * 0.5)\ntest_size = val_and_test_ds_size - val_size\n\n# Split the dataset\nval_ds = val_and_test_ds.take(val_size)\ntest_ds = val_and_test_ds.skip(val_size)","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:37:43.158265Z","iopub.execute_input":"2024-03-16T07:37:43.158558Z","iopub.status.idle":"2024-03-16T07:37:45.208163Z","shell.execute_reply.started":"2024-03-16T07:37:43.158532Z","shell.execute_reply":"2024-03-16T07:37:45.207404Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Visualizing data\n","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nn_rows = 3\nn_cols = 5\n\nplt.figure(figsize=(n_cols * 2.0, n_rows * 2.0))\n\n# Get a batch to work with\nfor images_batch, labels_batch in train_ds.take(1):\n    pass\n\nfor row in range(n_rows):\n    for col in range(n_cols):\n        index = n_cols * row + col\n        plt.subplot(n_rows, n_cols, index + 1)\n        \n        # Grab one image and convert it to NumPy type values\n        img = images_batch[index, :, :, :].numpy()\n        plt.imshow(img) #, cmap=\"binary\", interpolation=\"nearest\")\n        \n        # For the labels, we need to turn a length-8 one-hot EagerTensor\n        # into the string label\n        label_row = labels_batch[index, :]\n       \n        # Find the class label number with argmax and convert to NumPy type\n        class_label = tf.argmax(label_row).numpy()\n        \n        # Look up the list\n        class_label = label_names[class_label]\n        \n        # Use it on the plot\n        plt.title(class_label)\nplt.subplots_adjust(wspace=0.2, hspace=0.5)\nplt.show()       ","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:37:48.093521Z","iopub.execute_input":"2024-03-16T07:37:48.094127Z","iopub.status.idle":"2024-03-16T07:37:51.048091Z","shell.execute_reply.started":"2024-03-16T07:37:48.094089Z","shell.execute_reply":"2024-03-16T07:37:51.046968Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# A mole is gonna look valid in any rotation or flipping, since there isn't a \n# left-to-right \"direction\" to how cells grow.  Thus we can do lots of augmentation.\nimage_augmentation = tf.keras.models.Sequential([\n    tf.keras.layers.RandomRotation(factor=0.15),\n    tf.keras.layers.RandomTranslation(height_factor=0.1, width_factor=0.1),\n    tf.keras.layers.RandomFlip(mode=\"horizontal_and_vertical\", seed=7)\n    ])","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:37:51.049668Z","iopub.execute_input":"2024-03-16T07:37:51.049963Z","iopub.status.idle":"2024-03-16T07:37:51.066235Z","shell.execute_reply.started":"2024-03-16T07:37:51.049939Z","shell.execute_reply":"2024-03-16T07:37:51.065223Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Cache dataset for performance and prefetch so CPU can do work while GPU \n# training on current batch.  Train is already shuffled earlier.\ntrain_ds = train_ds.cache().prefetch(buffer_size=tf.data.AUTOTUNE)\nval_ds = val_ds.cache().prefetch(buffer_size=tf.data.AUTOTUNE)\ntest_ds = test_ds.cache().prefetch(buffer_size=tf.data.AUTOTUNE)","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:37:54.881357Z","iopub.execute_input":"2024-03-16T07:37:54.88223Z","iopub.status.idle":"2024-03-16T07:37:54.898968Z","shell.execute_reply.started":"2024-03-16T07:37:54.882164Z","shell.execute_reply":"2024-03-16T07:37:54.898141Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.applications import EfficientNetB0","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:37:56.491701Z","iopub.execute_input":"2024-03-16T07:37:56.492483Z","iopub.status.idle":"2024-03-16T07:37:56.499512Z","shell.execute_reply.started":"2024-03-16T07:37:56.492453Z","shell.execute_reply":"2024-03-16T07:37:56.498761Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Going to start by \n# 1. retraining the classifier (head) \n# 2. then we'll fine-tune all weights next\n\nMETRICS = [\n    tf.keras.metrics.CategoricalCrossentropy(name='categorical_crossentropy'),\n    tf.keras.metrics.TruePositives(name='tp'),\n    tf.keras.metrics.TrueNegatives(name='tn'),\n    tf.keras.metrics.FalsePositives(name='fp'),\n    tf.keras.metrics.FalseNegatives(name='fn'),\n    tf.keras.metrics.Precision(name='precision'),\n    tf.keras.metrics.Recall(name='recall'),\n    tf.keras.metrics.F1Score(name='f1'),\n    tf.keras.metrics.CategoricalAccuracy(name='categorical_accuracy'),  # not trustworthy since imbalanced!\n]\n\ndef build_model(num_classes, metrics=METRICS, output_bias=None):\n    \n    # Can set initial output biases to something other than zero for faster convergence\n    if output_bias is not None:\n        output_bias = tf.keras.initializers.Constant(output_bias)\n    \n    # Inputs and augmentation\n    inputs = tf.keras.layers.Input(shape=(IMG_SIZE, IMG_SIZE, 3))\n    aug_inputs = image_augmentation(inputs)\n    \n    # Base model\n    model = EfficientNetB0(include_top=False, input_tensor=aug_inputs, weights=\"imagenet\")\n\n    # Freeze the pretrained weights\n    model.trainable = False\n\n    # Rebuild top like in original paper\n    x = tf.keras.layers.GlobalAveragePooling2D(name=\"avg_pool\")(model.output)\n    x = tf.keras.layers.BatchNormalization()(x)\n    x = tf.keras.layers.Dropout(0.2, name=\"top_dropout\")(x)\n    outputs = tf.keras.layers.Dense(num_classes, \n                                    activation=\"softmax\",\n                                    # bias otherwise defaults to zeros\n                                    bias_initializer=output_bias,\n                                    name=\"pred\")(x)\n\n    # Compile Model\n    model = tf.keras.Model(inputs, outputs, name=\"EfficientNet\")\n    \n    # Using a large learning rate for this part since most weights are fixed\n    optimizer = tf.keras.optimizers.Adam(learning_rate=1e-2)\n    \n    model.compile(\n        optimizer=optimizer, loss=\"categorical_crossentropy\", metrics=metrics,\n    )\n    \n    return model","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:37:59.833549Z","iopub.execute_input":"2024-03-16T07:37:59.834361Z","iopub.status.idle":"2024-03-16T07:37:59.873584Z","shell.execute_reply.started":"2024-03-16T07:37:59.834329Z","shell.execute_reply":"2024-03-16T07:37:59.872843Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = build_model(num_classes)\n# model.summary()","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:38:02.086837Z","iopub.execute_input":"2024-03-16T07:38:02.087506Z","iopub.status.idle":"2024-03-16T07:38:03.847925Z","shell.execute_reply.started":"2024-03-16T07:38:02.087476Z","shell.execute_reply":"2024-03-16T07:38:03.846934Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get a batch to work with\nfor image_batch, label_batch in train_ds.take(1):\n    pass\n\nresults = model.evaluate(image_batch, label_batch, batch_size=BATCH_SIZE, verbose=0)\nprint(\"Loss: {:0.4f}\".format(results[0]))","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:38:05.154437Z","iopub.execute_input":"2024-03-16T07:38:05.154807Z","iopub.status.idle":"2024-03-16T07:38:14.055087Z","shell.execute_reply.started":"2024-03-16T07:38:05.154778Z","shell.execute_reply":"2024-03-16T07:38:14.054079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# We calculated the class frequencies earlier when doing the class_weights\nclass_frequencies = np.array(class_frequencies)\n\n# Making priors that match the data distribution for faster convergence\nclass_log_odds = np.log(class_frequencies / (1 - class_frequencies))\n\nprint(class_log_odds)","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:38:15.318073Z","iopub.execute_input":"2024-03-16T07:38:15.318713Z","iopub.status.idle":"2024-03-16T07:38:15.324315Z","shell.execute_reply.started":"2024-03-16T07:38:15.318682Z","shell.execute_reply":"2024-03-16T07:38:15.323404Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = build_model(num_classes, output_bias=class_log_odds)\n# model.summary()","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:38:16.391999Z","iopub.execute_input":"2024-03-16T07:38:16.39238Z","iopub.status.idle":"2024-03-16T07:38:17.472381Z","shell.execute_reply.started":"2024-03-16T07:38:16.39235Z","shell.execute_reply":"2024-03-16T07:38:17.471596Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Now see the loss on that same batch with better initialized bias terms\nresults = model.evaluate(image_batch, label_batch, batch_size=BATCH_SIZE, verbose=0)\nprint(\"Loss: {:0.4f}\".format(results[0]))","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:38:17.473888Z","iopub.execute_input":"2024-03-16T07:38:17.474186Z","iopub.status.idle":"2024-03-16T07:38:20.514436Z","shell.execute_reply.started":"2024-03-16T07:38:17.474146Z","shell.execute_reply":"2024-03-16T07:38:20.51344Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(train_ds, \n                    epochs=EPOCHS, \n                    validation_data=val_ds,\n                    class_weight=class_weight,  # use our class weights here\n                   )","metadata":{"execution":{"iopub.status.busy":"2024-03-16T07:38:40.094673Z","iopub.execute_input":"2024-03-16T07:38:40.095023Z","iopub.status.idle":"2024-03-16T08:14:42.261123Z","shell.execute_reply.started":"2024-03-16T07:38:40.094996Z","shell.execute_reply":"2024-03-16T08:14:42.26013Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":" # **FINE TUNNING**","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\ndef plot_history(history):\n    # Plot the loss and accuracy curves for training and validation \n    fig, ax = plt.subplots(2,1)\n    ax[0].plot(history.history['loss'], color='b', label=\"Training loss\")\n    ax[0].plot(history.history['val_loss'], color='r', label=\"validation loss\",axes =ax[0])\n    legend = ax[0].legend(loc='best', shadow=True)\n\n    ax[1].plot(history.history['categorical_accuracy'], color='b', label=\"Training accuracy\")\n    ax[1].plot(history.history['val_categorical_accuracy'], color='r',label=\"Validation accuracy\")\n    legend = ax[1].legend(loc='best', shadow=True)","metadata":{"execution":{"iopub.status.busy":"2024-03-16T08:16:15.3725Z","iopub.execute_input":"2024-03-16T08:16:15.373408Z","iopub.status.idle":"2024-03-16T08:16:15.380575Z","shell.execute_reply.started":"2024-03-16T08:16:15.373371Z","shell.execute_reply":"2024-03-16T08:16:15.379559Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def unfreeze_model(model, metrics=METRICS):\n    \n#     We unfreeze the top 20 layers while leaving BatchNorm layers frozen\n    # Unfreeze all the layers, but leave BatchNorm layers frozen\n#     for layer in model.layers[-20:]:\n    for layer in model.layers:\n        if not isinstance(layer, tf.keras.layers.BatchNormalization):\n            layer.trainable = True\n\n    # Use a much smaller learning rate now to start\n    optimizer = tf.keras.optimizers.Adam(learning_rate=1e-5)\n    \n    # Recompile to 'freeze' which layers are frozen (not trainable)\n    model.compile(\n        optimizer=optimizer, loss=\"categorical_crossentropy\", metrics=metrics\n    )\n\nunfreeze_model(model)","metadata":{"execution":{"iopub.status.busy":"2024-03-16T08:16:53.490778Z","iopub.execute_input":"2024-03-16T08:16:53.491544Z","iopub.status.idle":"2024-03-16T08:16:53.502794Z","shell.execute_reply.started":"2024-03-16T08:16:53.491512Z","shell.execute_reply":"2024-03-16T08:16:53.50195Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(train_ds, \n                    epochs=EPOCHS, \n                    validation_data=val_ds,\n                    class_weight=class_weight,  # use our class weights here\n                   )","metadata":{"execution":{"iopub.status.busy":"2024-03-16T08:21:10.736939Z","iopub.execute_input":"2024-03-16T08:21:10.737307Z","iopub.status.idle":"2024-03-16T10:05:48.419196Z","shell.execute_reply.started":"2024-03-16T08:21:10.737276Z","shell.execute_reply":"2024-03-16T10:05:48.418393Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# This is a (1732, 8) NumPy array of raw probabilities\ntest_predictions_baseline = model.predict(test_ds, batch_size=BATCH_SIZE)\n\n# Convert raw probabilities into actual class predictions\npredicted_classes = np.argmax(test_predictions_baseline, axis=1)  # (1732,)","metadata":{"execution":{"iopub.status.busy":"2024-03-16T13:13:21.269144Z","iopub.execute_input":"2024-03-16T13:13:21.269442Z","iopub.status.idle":"2024-03-16T13:13:21.611181Z","shell.execute_reply.started":"2024-03-16T13:13:21.269415Z","shell.execute_reply":"2024-03-16T13:13:21.609952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\n\n# Assuming your PyTorch model is named 'model' and PATH is the file path where you want to save the model\ntorch.save(model, '/kaggle/working/model.h5')\n","metadata":{"execution":{"iopub.status.busy":"2024-03-16T10:58:06.499359Z","iopub.execute_input":"2024-03-16T10:58:06.499719Z","iopub.status.idle":"2024-03-16T10:58:06.611012Z","shell.execute_reply.started":"2024-03-16T10:58:06.499688Z","shell.execute_reply":"2024-03-16T10:58:06.609634Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(predicted_classes.shape)\nprint(predicted_classes[:10])","metadata":{"execution":{"iopub.status.busy":"2024-03-16T10:37:22.612686Z","iopub.execute_input":"2024-03-16T10:37:22.61362Z","iopub.status.idle":"2024-03-16T10:37:22.618808Z","shell.execute_reply.started":"2024-03-16T10:37:22.613583Z","shell.execute_reply":"2024-03-16T10:37:22.617816Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Need to get the true labels from the test_ds dataset\n\n# Initialize an empty list to store the labels\ntrue_labels = []\n\n# Iterate over the dataset batches\nfor _, tmp_labels in test_ds:\n    # The \"_\" ignores the features, and \"labels\" are what we want to collect\n    \n    # Convert the labels to numpy arrays and append to the list\n    true_labels.append(tmp_labels.numpy())\n\n# True labels is a list of batches, need to \n# concatenate all the labels into a single numpy array\ntrue_labels = np.concatenate(true_labels)\n\n# Convert 1-hot labels to class labels\ntrue_labels = np.argmax(true_labels, axis=1)  # (1732,)","metadata":{"execution":{"iopub.status.busy":"2024-03-16T10:12:30.565346Z","iopub.execute_input":"2024-03-16T10:12:30.566158Z","iopub.status.idle":"2024-03-16T10:12:30.579818Z","shell.execute_reply.started":"2024-03-16T10:12:30.566125Z","shell.execute_reply":"2024-03-16T10:12:30.578843Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(true_labels.shape)\nprint(true_labels[:10])","metadata":{"execution":{"iopub.status.busy":"2024-03-16T10:12:31.884137Z","iopub.execute_input":"2024-03-16T10:12:31.884958Z","iopub.status.idle":"2024-03-16T10:12:31.889672Z","shell.execute_reply.started":"2024-03-16T10:12:31.884928Z","shell.execute_reply":"2024-03-16T10:12:31.888746Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\n\n# Assuming predicted_classes and true_labels are numpy arrays\npredicted_classes = np.array(predicted_classes)\ntrue_labels = np.array(true_labels)\n\n# Calculate accuracy\naccuracy = np.mean(predicted_classes == true_labels)\nprint(accuracy)","metadata":{"execution":{"iopub.status.busy":"2024-03-16T10:12:33.891822Z","iopub.execute_input":"2024-03-16T10:12:33.892517Z","iopub.status.idle":"2024-03-16T10:12:33.897914Z","shell.execute_reply.started":"2024-03-16T10:12:33.892486Z","shell.execute_reply":"2024-03-16T10:12:33.896959Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\ncount = 0\n\n# Iterate over elements and update count\nfor true_label, predicted_class in zip(true_labels, predicted_classes):\n    if true_label == predicted_class:\n        count += 1\n\nprint(\"Total number of common values:\", count)","metadata":{"execution":{"iopub.status.busy":"2024-03-16T10:12:35.966896Z","iopub.execute_input":"2024-03-16T10:12:35.967574Z","iopub.status.idle":"2024-03-16T10:12:35.973278Z","shell.execute_reply.started":"2024-03-16T10:12:35.967537Z","shell.execute_reply":"2024-03-16T10:12:35.972368Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"final_dir = '/kaggle/input/aiml-general-championship/KCDH2024_Test_Input'","metadata":{"execution":{"iopub.status.busy":"2024-03-16T10:12:38.575126Z","iopub.execute_input":"2024-03-16T10:12:38.575484Z","iopub.status.idle":"2024-03-16T10:12:38.579691Z","shell.execute_reply.started":"2024-03-16T10:12:38.575458Z","shell.execute_reply":"2024-03-16T10:12:38.578761Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"conf_ds = tf.keras.utils.image_dataset_from_directory(\n    final_dir,\n    labels=\"inferred\",\n    label_mode=\"categorical\",   # will use categorical_crossentropy loss later\n    batch_size=BATCH_SIZE,\n    image_size=(IMG_SIZE, IMG_SIZE),\n    seed=7,\n    crop_to_aspect_ratio=True,\n)","metadata":{"execution":{"iopub.status.busy":"2024-03-16T10:12:41.830294Z","iopub.execute_input":"2024-03-16T10:12:41.831157Z","iopub.status.idle":"2024-03-16T10:12:43.421537Z","shell.execute_reply.started":"2024-03-16T10:12:41.831124Z","shell.execute_reply":"2024-03-16T10:12:43.420757Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# This is a (1732, 8) NumPy array of raw probabilities\nfinal_predictions = model.predict(conf_ds, batch_size=BATCH_SIZE)\n\n# Convert raw probabilities into actual class predictions\nanswer_to_gc = np.argmax(final_predictions, axis=1)  # (1732,)","metadata":{"execution":{"iopub.status.busy":"2024-03-16T10:12:43.608001Z","iopub.execute_input":"2024-03-16T10:12:43.608571Z","iopub.status.idle":"2024-03-16T10:12:55.411011Z","shell.execute_reply.started":"2024-03-16T10:12:43.608534Z","shell.execute_reply":"2024-03-16T10:12:55.410224Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(answer_to_gc.shape)\nprint(answer_to_gc)","metadata":{"execution":{"iopub.status.busy":"2024-03-16T10:12:57.793262Z","iopub.execute_input":"2024-03-16T10:12:57.794092Z","iopub.status.idle":"2024-03-16T10:12:57.798903Z","shell.execute_reply.started":"2024-03-16T10:12:57.79406Z","shell.execute_reply":"2024-03-16T10:12:57.797838Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"execution":{"iopub.status.busy":"2024-03-16T05:31:10.382812Z","iopub.execute_input":"2024-03-16T05:31:10.383247Z","iopub.status.idle":"2024-03-16T05:31:10.389957Z","shell.execute_reply.started":"2024-03-16T05:31:10.383213Z","shell.execute_reply":"2024-03-16T05:31:10.388965Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Initialize an empty dictionary to store frequencies\nfrequency_dict = {}\n\n# Count frequencies of each number\nfor num in answer_to_gc:\n    if num in frequency_dict:\n        frequency_dict[num] += 1\n    else:\n        frequency_dict[num] = 1\n\n# Print frequencies\nfor num, freq in frequency_dict.items():\n    print(f\"Number {num} occurs {freq} times.\")","metadata":{"execution":{"iopub.status.busy":"2024-03-16T10:13:01.94657Z","iopub.execute_input":"2024-03-16T10:13:01.946924Z","iopub.status.idle":"2024-03-16T10:13:01.954119Z","shell.execute_reply.started":"2024-03-16T10:13:01.946895Z","shell.execute_reply":"2024-03-16T10:13:01.95322Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# List all files in the directory\nfinal_dir_in = '/kaggle/input/aiml-general-championship/KCDH2024_Test_Input/KCDH2024_Test_Input'\nimage_files = os.listdir(final_dir_in)\n\n# Create a DataFrame with a column containing the image file names\ndf = pd.DataFrame({'image_file': image_files})\n\n# If you want to sort the DataFrame by image file names\ndf.sort_values(by='image_file', inplace=True)\n\n# If you want to reset the index after sorting\ndf.reset_index(drop=True, inplace=True)\n\n# Remove \".jpg\" extension from image names\ndf['image_file'] = df['image_file'].str.replace('.jpg', '')\n\n\n\nprint(df.head())","metadata":{"execution":{"iopub.status.busy":"2024-03-16T10:13:04.732769Z","iopub.execute_input":"2024-03-16T10:13:04.733414Z","iopub.status.idle":"2024-03-16T10:13:04.755152Z","shell.execute_reply.started":"2024-03-16T10:13:04.73338Z","shell.execute_reply":"2024-03-16T10:13:04.754337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# Create a DataFrame from the array\nanswer_to_gc_df = pd.DataFrame({'answer_to_gc': answer_to_gc})\n\n# Concatenate the two DataFrames along columns\ndf = pd.concat([df, answer_to_gc_df], axis=1)\n\nprint(df.head())","metadata":{"execution":{"iopub.status.busy":"2024-03-16T10:13:06.976636Z","iopub.execute_input":"2024-03-16T10:13:06.97749Z","iopub.status.idle":"2024-03-16T10:13:06.990683Z","shell.execute_reply.started":"2024-03-16T10:13:06.977447Z","shell.execute_reply":"2024-03-16T10:13:06.989811Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Generaating csv file to upload\n\ndf.to_csv('output.csv', index=False)\n\nprint(\"CSV file generated successfully.\")","metadata":{"execution":{"iopub.status.busy":"2024-03-16T10:13:10.129019Z","iopub.execute_input":"2024-03-16T10:13:10.129884Z","iopub.status.idle":"2024-03-16T10:13:10.142281Z","shell.execute_reply.started":"2024-03-16T10:13:10.12985Z","shell.execute_reply":"2024-03-16T10:13:10.141385Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}