{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":70497,"databundleVersionId":7713244,"sourceType":"competition"},{"sourceId":4292212,"sourceType":"datasetVersion","datasetId":2529046}],"dockerImageVersionId":30648,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Import required dependencies","metadata":{}},{"cell_type":"code","source":"!pip install scikit-learn\n!pip install scikit-learn-extra","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:01:15.053643Z","iopub.execute_input":"2024-05-28T15:01:15.054045Z","iopub.status.idle":"2024-05-28T15:01:43.665035Z","shell.execute_reply.started":"2024-05-28T15:01:15.054010Z","shell.execute_reply":"2024-05-28T15:01:43.663992Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport tensorflow as tf\nfrom sklearn.cluster import KMeans\nfrom sklearn_extra.cluster import KMedoids\nfrom sklearn.model_selection import train_test_split\nfrom tensorflow.keras import Input, Model\nfrom tensorflow.keras.applications import InceptionV3\nfrom tensorflow.keras.layers import GlobalAveragePooling2D, Dense\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array\nfrom keras_tuner.tuners import RandomSearch","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:01:43.667042Z","iopub.execute_input":"2024-05-28T15:01:43.667360Z","iopub.status.idle":"2024-05-28T15:02:04.553385Z","shell.execute_reply.started":"2024-05-28T15:01:43.667333Z","shell.execute_reply":"2024-05-28T15:02:04.552372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Preprocessing","metadata":{}},{"cell_type":"code","source":"# Set random seed for reproducibility\nSEED = 42\nnp.random.seed(SEED)\ntf.random.set_seed(SEED)","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:02:04.554569Z","iopub.execute_input":"2024-05-28T15:02:04.555112Z","iopub.status.idle":"2024-05-28T15:02:04.560107Z","shell.execute_reply.started":"2024-05-28T15:02:04.555085Z","shell.execute_reply":"2024-05-28T15:02:04.558931Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Rescaling and centering the image","metadata":{}},{"cell_type":"code","source":"IMG_SIZE = 224","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:02:04.562423Z","iopub.execute_input":"2024-05-28T15:02:04.562922Z","iopub.status.idle":"2024-05-28T15:02:04.577578Z","shell.execute_reply.started":"2024-05-28T15:02:04.562895Z","shell.execute_reply":"2024-05-28T15:02:04.576773Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Data generators\ndatagen = ImageDataGenerator(\n    samplewise_center=True,\n    rescale=1/255,\n    rotation_range=30,            \n    width_shift_range=0.3,        \n    height_shift_range=0.3,       \n    shear_range=0.3,              \n    zoom_range=[0.8, 1.5],        \n    horizontal_flip=True,\n    vertical_flip=True,           \n    fill_mode='reflect'\n)","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:02:04.578791Z","iopub.execute_input":"2024-05-28T15:02:04.579055Z","iopub.status.idle":"2024-05-28T15:02:04.587049Z","shell.execute_reply.started":"2024-05-28T15:02:04.579033Z","shell.execute_reply":"2024-05-28T15:02:04.586323Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create data generator","metadata":{}},{"cell_type":"code","source":"train_it = datagen.flow_from_directory(\n    '../input/csc532-fruits-categorical-classification-2024/csc532_2024_train/train', \n    target_size=(IMG_SIZE, IMG_SIZE), \n    color_mode='rgb', \n    class_mode=\"categorical\"\n)","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:02:04.588554Z","iopub.execute_input":"2024-05-28T15:02:04.588830Z","iopub.status.idle":"2024-05-28T15:02:09.733937Z","shell.execute_reply.started":"2024-05-28T15:02:04.588808Z","shell.execute_reply":"2024-05-28T15:02:09.733126Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"valid_it = datagen.flow_from_directory(\n    '../input/csc532-fruits-categorical-classification-2024/csc532_2024_test/test', \n    target_size=(IMG_SIZE, IMG_SIZE), \n    color_mode='rgb', \n    class_mode=\"categorical\"\n)","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:02:09.735156Z","iopub.execute_input":"2024-05-28T15:02:09.735506Z","iopub.status.idle":"2024-05-28T15:02:10.145800Z","shell.execute_reply.started":"2024-05-28T15:02:09.735472Z","shell.execute_reply":"2024-05-28T15:02:10.145059Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Modeling","metadata":{}},{"cell_type":"code","source":"# Define your build_model function for KerasTuner\ndef build_model(hp):\n    IMG_SIZE = 224  # Assuming IMG_SIZE is defined elsewhere\n\n    # Define your model architecture here\n    base_model = InceptionV3(\n        weights='imagenet',\n        input_shape=(IMG_SIZE, IMG_SIZE, 3),\n        include_top=False\n    )\n    base_model.trainable = False\n\n    inputs = Input(shape=(IMG_SIZE, IMG_SIZE, 3))\n    x = base_model(inputs, training=False)\n    x = GlobalAveragePooling2D()(x)\n\n    hp_units = hp.Int('units', min_value=32, max_value=512, step=32)\n    outputs = Dense(hp_units, activation='relu')(x)\n    outputs = Dense(len(train_it.class_indices), activation='softmax')(outputs)\n\n    model = Model(inputs, outputs)\n\n    model.compile(\n        loss='categorical_crossentropy',\n        optimizer=Adam(hp.Choice('learning_rate', values=[1e-2, 1e-3, 1e-4])),\n        metrics=['accuracy']\n    )\n\n    return model","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:02:10.146833Z","iopub.execute_input":"2024-05-28T15:02:10.147136Z","iopub.status.idle":"2024-05-28T15:02:10.156300Z","shell.execute_reply.started":"2024-05-28T15:02:10.147110Z","shell.execute_reply":"2024-05-28T15:02:10.155411Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set random seed for Kerastuner\nrandom_tuner_seed = 50\n\ntuner = RandomSearch(\n    build_model,\n    objective='val_accuracy',\n    max_trials=1,\n    executions_per_trial=1,\n    directory='kerastuner_dir',\n    project_name='inceptionv3_hyperparameter_tuning',\n    seed=random_tuner_seed\n)\n\ntuner.search(train_it,\n             epochs=10,\n             validation_data=valid_it)\n\nbest_model = tuner.get_best_models(num_models=1)[0]\nbest_model.save('dlai5_inceptionV3_hyper_tuned')","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:05:09.359327Z","iopub.execute_input":"2024-05-28T15:05:09.359944Z","iopub.status.idle":"2024-05-28T15:43:57.575083Z","shell.execute_reply.started":"2024-05-28T15:05:09.359912Z","shell.execute_reply":"2024-05-28T15:43:57.574216Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prediction","metadata":{}},{"cell_type":"code","source":"# Load the trained model\nmodel = best_model","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:44:22.788293Z","iopub.execute_input":"2024-05-28T15:44:22.788668Z","iopub.status.idle":"2024-05-28T15:44:22.792930Z","shell.execute_reply.started":"2024-05-28T15:44:22.788629Z","shell.execute_reply":"2024-05-28T15:44:22.791934Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the directory containing the validation images\nvalidation_dir = '../input/csc532-fruits-categorical-classification-2024/csc532_2024_validation/validation'","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:44:24.243428Z","iopub.execute_input":"2024-05-28T15:44:24.244265Z","iopub.status.idle":"2024-05-28T15:44:24.248303Z","shell.execute_reply.started":"2024-05-28T15:44:24.244222Z","shell.execute_reply":"2024-05-28T15:44:24.247281Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get the list of image files in the validation directory\nfiles = [f for f in os.listdir(validation_dir) if os.path.isfile(os.path.join(validation_dir, f))]","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:44:25.130862Z","iopub.execute_input":"2024-05-28T15:44:25.131209Z","iopub.status.idle":"2024-05-28T15:44:25.167924Z","shell.execute_reply.started":"2024-05-28T15:44:25.131183Z","shell.execute_reply":"2024-05-28T15:44:25.167033Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Initialize result dictionary\nresult_dict = {'ID': [], 'Code': []}","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:44:26.866931Z","iopub.execute_input":"2024-05-28T15:44:26.867765Z","iopub.status.idle":"2024-05-28T15:44:26.872349Z","shell.execute_reply.started":"2024-05-28T15:44:26.867722Z","shell.execute_reply":"2024-05-28T15:44:26.871248Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Now, you can use the loaded model for predictions\nfor file in files:\n    # Load and preprocess the image\n    image = load_img(os.path.join(validation_dir, file), target_size=(IMG_SIZE, IMG_SIZE))\n    image = img_to_array(image)\n    image = image.reshape(1, IMG_SIZE, IMG_SIZE, 3)\n    image = image / 255.0\n\n    # Make prediction using the model\n    pred = np.argmax(model.predict(image)) + 1\n    result_dict['ID'].append(file)\n    result_dict['Code'].append(str(pred))  # Convert prediction to string for comma-delimited list","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:44:28.200195Z","iopub.execute_input":"2024-05-28T15:44:28.200541Z","iopub.status.idle":"2024-05-28T15:44:49.431274Z","shell.execute_reply.started":"2024-05-28T15:44:28.200515Z","shell.execute_reply":"2024-05-28T15:44:49.430347Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Convert result_dict to a DataFrame\ndf = pd.DataFrame.from_dict(result_dict)\n\n# Save the DataFrame to a CSV file\ndf.to_csv('submission.csv', index=False, header=True)","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:45:02.994827Z","iopub.execute_input":"2024-05-28T15:45:02.995565Z","iopub.status.idle":"2024-05-28T15:45:03.057262Z","shell.execute_reply.started":"2024-05-28T15:45:02.995530Z","shell.execute_reply":"2024-05-28T15:45:03.056153Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load images for clustering\nimages = []\nfor file in files:\n    image = load_img(os.path.join(validation_dir, file), target_size=(IMG_SIZE, IMG_SIZE))\n    image = img_to_array(image)\n    # Ensure that the input image has 3 dimensions\n    if image.ndim == 2:\n        image = np.expand_dims(image, axis=-1)\n    images.append(image.flatten())  # Flatten the image into a 1D array","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:45:03.949329Z","iopub.execute_input":"2024-05-28T15:45:03.950217Z","iopub.status.idle":"2024-05-28T15:45:07.788777Z","shell.execute_reply.started":"2024-05-28T15:45:03.950182Z","shell.execute_reply":"2024-05-28T15:45:07.787744Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Convert to numpy array\nimages = np.array(images)","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:45:09.880010Z","iopub.execute_input":"2024-05-28T15:45:09.880927Z","iopub.status.idle":"2024-05-28T15:45:09.912749Z","shell.execute_reply.started":"2024-05-28T15:45:09.880885Z","shell.execute_reply":"2024-05-28T15:45:09.911586Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.models import Sequential\n\n# Perform clustering for k = 2\nk = 2\nkmeans_2 = KMeans(n_clusters=k)\ncluster_labels_2 = kmeans_2.fit_predict(images)\n\n# Perform clustering for k = 3\nk = 3\nkmeans_3 = KMeans(n_clusters=k)\ncluster_labels_3 = kmeans_3.fit_predict(images)\n\n# Perform clustering for k = 6\nk = 6\nkmeans_6 = KMeans(n_clusters=k)\ncluster_labels_6 = kmeans_6.fit_predict(images)\n\n# Train models for each cluster for k = 2\ntrained_models_2 = {}\nfor i in range(2):\n    cluster_data = images[np.where(cluster_labels_2 == i)[0]]\n    \n    # Reshape the cluster data back to the original image dimensions\n    cluster_data = cluster_data.reshape(-1, IMG_SIZE, IMG_SIZE, 3)\n    \n    # Split the cluster data into train and test sets\n    X_train, X_test = train_test_split(cluster_data, test_size=0.2, random_state=42)\n    \n    # Define your model\n    model = Sequential([\n        GlobalAveragePooling2D(input_shape=(IMG_SIZE, IMG_SIZE, 3)),\n        Dense(128, activation='relu'),\n        Dense(64, activation='relu'),\n        Dense(len(np.unique(cluster_labels_2)), activation='softmax')  # Assuming the number of output classes equals the number of clusters\n    ])\n    \n    # Compile the model\n    model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])\n    \n    # Train the model\n    model.fit(X_train, np.full((X_train.shape[0],), i), epochs=10, validation_data=(X_test, np.full((X_test.shape[0],), i)))\n    \n    # Save the trained model\n    trained_models_2[i] = model\n\n# Train models for each cluster for k = 3\ntrained_models_3 = {}\nfor i in range(3):\n    cluster_data = images[np.where(cluster_labels_3 == i)[0]]\n    \n    # Reshape the cluster data back to the original image dimensions\n    cluster_data = cluster_data.reshape(-1, IMG_SIZE, IMG_SIZE, 3)\n    \n    # Split the cluster data into train and test sets\n    X_train, X_test = train_test_split(cluster_data, test_size=0.2, random_state=42)\n    \n    # Define your model\n    model = Sequential([\n        GlobalAveragePooling2D(input_shape=(IMG_SIZE, IMG_SIZE, 3)),\n        Dense(128, activation='relu'),\n        Dense(64, activation='relu'),\n        Dense(len(np.unique(cluster_labels_3)), activation='softmax')  # Assuming the number of output classes equals the number of clusters\n    ])\n    \n    # Compile the model\n    model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])\n    \n    # Train the model\n    model.fit(X_train, np.full((X_train.shape[0],), i), epochs=10, validation_data=(X_test, np.full((X_test.shape[0],), i)))\n    \n    # Save the trained model\n    trained_models_3[i] = model\n\n# Train models for each cluster for k = 6\ntrained_models_6 = {}\nfor i in range(6):\n    cluster_data = images[np.where(cluster_labels_6 == i)[0]]\n    \n    # Reshape the cluster data back to the original image dimensions\n    cluster_data = cluster_data.reshape(-1, IMG_SIZE, IMG_SIZE, 3)\n    \n    # Split the cluster data into train and test sets\n    X_train, X_test = train_test_split(cluster_data, test_size=0.2, random_state=42)\n    \n    # Define your model\n    model = Sequential([\n        GlobalAveragePooling2D(input_shape=(IMG_SIZE, IMG_SIZE, 3)),\n        Dense(128, activation='relu'),\n        Dense(64, activation='relu'),\n        Dense(len(np.unique(cluster_labels_6)), activation='softmax')  # Assuming the number of output classes equals the number of clusters\n    ])\n    \n    # Compile the model\n    model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])\n    \n    # Train the model\n    model.fit(X_train, np.full((X_train.shape[0],), i), epochs=10, validation_data=(X_test, np.full((X_test.shape[0],), i)))\n    \n    # Save the trained model\n    trained_models_6[i] = model\n","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:45:10.729083Z","iopub.execute_input":"2024-05-28T15:45:10.729912Z","iopub.status.idle":"2024-05-28T15:45:48.206893Z","shell.execute_reply.started":"2024-05-28T15:45:10.729866Z","shell.execute_reply":"2024-05-28T15:45:48.206010Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load the unseen data\nunseen_data_dir = \"/kaggle/input/fruit-classification10-class/MY_data/predict\"\nunseen_files = [f for f in os.listdir(unseen_data_dir) if os.path.isfile(os.path.join(unseen_data_dir, f))]\n\n# Initialize a dictionary to store predictions for each k value\nunseen_predictions_k2 = {}\nunseen_predictions_k3 = {}\nunseen_predictions_k6 = {}\n\n# Preprocess and predict labels for unseen data for each k value\nfor file in unseen_files:\n    # Load and preprocess the image\n    image = load_img(os.path.join(unseen_data_dir, file), target_size=(IMG_SIZE, IMG_SIZE))\n    image = img_to_array(image)\n    image = image.reshape(1, IMG_SIZE, IMG_SIZE, 3)\n    image = image / 255.0\n\n    # Cluster assignment for the unseen data point\n    cluster_index_k2 = kmeans_2.predict(image.flatten().reshape(1, -1))[0]\n    cluster_index_k3 = kmeans_3.predict(image.flatten().reshape(1, -1))[0]\n    cluster_index_k6 = kmeans_6.predict(image.flatten().reshape(1, -1))[0]\n\n    # Use the corresponding trained model to predict labels for the data point\n    model_k2 = trained_models_2[cluster_index_k2]\n    model_k3 = trained_models_3[cluster_index_k3]\n    model_k6 = trained_models_6[cluster_index_k6]\n\n    prediction_k2 = np.argmax(model_k2.predict(image)) + 1\n    prediction_k3 = np.argmax(model_k3.predict(image)) + 1\n    prediction_k6 = np.argmax(model_k6.predict(image)) + 1\n    \n    # Store the predictions for each k value\n    unseen_predictions_k2[file] = prediction_k2\n    unseen_predictions_k3[file] = prediction_k3\n    unseen_predictions_k6[file] = prediction_k6\n\n# Print or process the predictions as needed\nprint(\"Predictions for k=2:\", unseen_predictions_k2)\nprint(\"Predictions for k=3:\", unseen_predictions_k3)\nprint(\"Predictions for k=6:\", unseen_predictions_k6)","metadata":{"execution":{"iopub.status.busy":"2024-05-28T15:46:17.708728Z","iopub.execute_input":"2024-05-28T15:46:17.709140Z","iopub.status.idle":"2024-05-28T15:46:29.770762Z","shell.execute_reply.started":"2024-05-28T15:46:17.709111Z","shell.execute_reply":"2024-05-28T15:46:29.769864Z"},"trusted":true},"execution_count":null,"outputs":[]}]}