Load required libraries

library(imager) library(dplyr) library(caret) library(nnet)

Define paths to each folder containing fruit images

base_path <- “/Users/RSanghavi/Misclaneous/AU/sem3/project/data” folders <- c(“Apple”, “Banana”, “Mango”, “Orange”)

Function to load images from a specified folder

load_images <- function(folder) { folder_path <- file.path(base_path, folder) # Construct full path to the folder images <- list.files(folder_path, pattern = “\.jpg\(|\\.png\)”, full.names = TRUE) # List all images

# Standard dimensions for resizing standard_width <- 64 standard_height <- 64

image_list <- lapply(images, function(img_path) { img <- load.image(img_path) # Load the image

# Convert to grayscale if the image has 3 channels (RGB)
if (spectrum(img) == 3) {
  img <- grayscale(img)
}

# Resize the image to standard dimensions (64x64)
img <- resize(img, standard_width, standard_height)

# Flatten the image into a single vector for further processing
as.vector(img)

})

# Combine image vectors into a matrix and add corresponding labels image_data <- do.call(rbind, image_list) labels <- rep(folder, length(images)) # Create a label for each image return(data.frame(image_data, label = labels, stringsAsFactors = FALSE)) # Return as data frame }

Load images from all specified fruit folders

apple_data <- load_images(“Apple”) banana_data <- load_images(“Banana”) mango_data <- load_images(“Mango”) orange_data <- load_images(“Orange”)

Convert image data to numeric and normalize by dividing by 255

apple_data_numeric <- as.data.frame(lapply(apple_data[, 1:4096], as.numeric)) / 255 banana_data_numeric <- as.data.frame(lapply(banana_data[, 1:16384], as.numeric)) / 255 mango_data_numeric <- as.data.frame(lapply(mango_data[, 1:4096], as.numeric)) / 255 orange_data_numeric <- as.data.frame(lapply(orange_data[, 1:16384], as.numeric)) / 255

Function to resize images to a specified size

resize_images <- function(image_data, new_size = 64) { resized_data <- lapply(1:nrow(image_data), function(i) { # Convert the numeric data of each image to a matrix img_matrix <- matrix(as.numeric(image_data[i, 1:(128*128)]), nrow = 128, ncol = 128) img <- as.cimg(img_matrix) # Convert to image object # Resize the image to the new dimensions (64x64) img_resized <- resize(img, size_x = new_size, size_y = new_size) # Convert back to a vector and return as.vector(as.matrix(img_resized)) })

# Combine resized images into a data frame resized_data <- do.call(rbind, resized_data) return(as.data.frame(resized_data)) # Return as data frame }

Resize banana and orange data to 64x64 dimensions

banana_data_resized <- resize_images(banana_data_numeric) orange_data_resized <- resize_images(orange_data_numeric)

Ensure apple and berries data only contain the first 4096 columns for consistency

apple_data_numeric <- apple_data_numeric[, 1:4096] mango_data_numeric <- mango_data_numeric[, 1:4096]

Rename the columns for consistency across datasets

colnames(apple_data_numeric) <- paste0(“X”, 1:4096) colnames(banana_data_resized) <- paste0(“X”, 1:4096) colnames(mango_data_numeric) <- paste0(“X”, 1:4096) colnames(orange_data_resized) <- paste0(“X”, 1:4096)

Combine all datasets into one data frame

combined_data <- rbind(apple_data_numeric, banana_data_resized, mango_data_numeric, orange_data_resized)

Check the dimensions of the combined data

dim(combined_data) # Should reflect total number of images and 4096 features

Add labels to the combined dataset

combined_data$label <- factor(c(rep(“Apple”, nrow(apple_data_numeric)), rep(“Banana”, nrow(banana_data_resized)), rep(“Mango”, nrow(mango_data_numeric)), rep(“Orange”, nrow(orange_data_resized))))

Set seed for reproducibility of the random sample

set.seed(123)

Split the combined data into training and test sets (70% training, 30% testing)

train_indices <- sample(1:nrow(combined_data), size = 0.7 * nrow(combined_data)) train_data <- combined_data[train_indices, ] # Training data test_data <- combined_data[-train_indices, ] # Test data

Convert any character columns in training data to factors

train_data <- as.data.frame(lapply(train_data, function(x) if(is.character(x)) factor(x) else x))

Ensure numeric predictors are in the correct format (excluding label)

train_data[, -which(names(train_data) == “label”)] <- lapply(train_data[, -which(names(train_data) == “label”)], as.numeric)

Ensure the label is a factor

train_data\(label <- as.factor(train_data\)label)

Perform Principal Component Analysis (PCA) on training data

pca_result <- prcomp(train_data[, -which(names(train_data) == “label”)], center = TRUE, scale. = TRUE)

Calculate cumulative variance explained by principal components

pca_variance <- cumsum(pca_result\(sdev^2) / sum(pca_result\)sdev^2)

Plot cumulative explained variance against the number of components

plot(pca_variance, xlab = “Number of Components”, ylab = “Cumulative Explained Variance”, type = “b”, main = “Cumulative Explained Variance by Principal Components”)

Create a new dataframe with the first 20 principal components for the training data

train_data_pca <- data.frame(pca_result\(x[, 1:20]) # Use the first 20 principal components train_data_pca\)label <- train_data$label # Add back the label

Apply the same PCA transformation to the test data

test_data_pca <- predict(pca_result, newdata = test_data[, -which(names(test_data) == “label”)]) test_data_pca <- data.frame(test_data_pca[, 1:20]) # Use the same number of components as training data test_data_pca\(label <- test_data\)label # Add back the label for evaluation

Fit a multinomial logistic regression model on the PCA-transformed training data

model <- multinom(label ~ ., data = train_data_pca)

Check the model summary to review coefficients

summary(model)

Make predictions on the test data

predicted_probabilities <- predict(model, newdata = test_data_pca, type = “prob”)

Convert predicted probabilities to class labels

predicted_classes <- apply(predicted_probabilities, 1, function(x) { levels(train_data_pca$label)[which.max(x)] })

Convert predicted classes to a factor

predicted_classes <- factor(predicted_classes, levels = levels(test_data$label))

Convert actual labels to a factor (if they are not already)

actual_labels <- factor(test_data\(label, levels = levels(test_data\)label))

Create confusion matrix for evaluation

confusion_matrix <- table(actual_labels, predicted_classes)

Use confusionMatrix function from caret package to get detailed results

confusion_results <- confusionMatrix(predicted_classes, actual_labels) print(confusion_results)

Calculate overall accuracy of the model

accuracy <- sum(diag(confusion_matrix)) / sum(confusion_matrix) print(paste(“Accuracy:”, accuracy))

Initialize vectors to store precision, recall, and F1 scores for each class

precision <- numeric(nrow(confusion_matrix)) recall <- numeric(nrow(confusion_matrix)) f1_score <- numeric(nrow(confusion_matrix))

Calculate precision, recall, and F1 score for each class based on the confusion matrix

for (i in 1:nrow(confusion_matrix)) { TP <- confusion_matrix[i, i] # True Positives FP <- sum(confusion_matrix[, i]) - TP # False Positives FN <- sum(confusion_matrix[i, ]) - TP # False Negatives

precision[i] <- TP / (TP + FP) # Calculate precision recall[i] <- TP / (TP + FN) # Calculate recall

# Calculate F1 Score f1_score[i] <- 2 * (precision[i] * recall[i]) / (precision[i] + recall[i]) }

Display precision, recall, and F1 Score metrics for each class

for (i in 1:nrow(confusion_matrix)) { cat(“:”, rownames(confusion_matrix)[i], “”) cat(“Precision:”, precision[i], “”) cat(“Recall:”, recall[i], “”) cat(“F1 Score:”, f1_score[i], “”) }

Calculate and display the overall F1 Score (Macro F1)

macro_f1 <- mean(f1_score, na.rm = TRUE) cat(“F1 Score:”, macro_f1, “”)

CLUSTERING

Load the required libraries for data visualization and clustering

library(ggplot2) library(dplyr) library(cluster)

Step 1: Visualize PCA results

ggplot(train_data_pca, aes(x = PC1, y = PC2, color = label)) + geom_point(alpha = 0.7) + # Scatter plot of the first two principal components labs(title = “PCA of Fruit Images”, x = “Principal Component 1”, y = “Principal Component 2”) + theme_minimal() # Apply a minimal theme for better aesthetics

Step 2: Determine optimal number of clusters using the Elbow Method

set.seed(123) # Set seed for reproducibility wss <- numeric(10) # Initialize a vector to store total within-cluster sum of squares

Calculate WSS for k values from 1 to 10

for (k in 1:10) { kmeans_result <- kmeans(train_data_pca[, -which(names(train_data_pca) == “label”)], centers = k, nstart = 10) wss[k] <- kmeans_result$tot.withinss # Store WSS for each k }

Plot the Elbow curve to visualize WSS against the number of clusters

plot(1:10, wss, type = “b”, pch = 19, xlab = “Number of Clusters”, ylab = “Total Within-Cluster Sum of Squares”, main = “Elbow Method for Optimal k”)

Step 3: Conduct Silhouette Analysis to assess clustering quality

sil_width <- numeric(10) # Initialize a vector to store average silhouette widths

Calculate average silhouette width for k values from 2 to 10

for (k in 2:10) { kmeans_result <- kmeans(train_data_pca[, -which(names(train_data_pca) == “label”)], centers = k, nstart = 10) sil <- silhouette(kmeans_result$cluster, dist(train_data_pca[, -which(names(train_data_pca) == “label”)])) # Compute silhouette values sil_width[k] <- mean(sil[, 3]) # Calculate mean silhouette width }

Plot silhouette scores to visualize clustering quality

plot(2:10, sil_width[2:10], type = “b”, pch = 19, xlab = “Number of Clusters”, ylab = “Average Silhouette Width”, main = “Silhouette Analysis”)

Step 4: Apply K-means Clustering with the identified optimal number of clusters

optimal_k <- 4 # Set optimal k value; replace with the identified elbow point set.seed(123) # Set seed for reproducibility kmeans_result <- kmeans(train_data_pca[, -which(names(train_data_pca) == “label”)], centers = optimal_k, nstart = 10)

Add the cluster assignments to the PCA data

train_data_pca\(cluster <- factor(kmeans_result\)cluster)

Create a data frame of cluster centers for visualization

centers <- as.data.frame(kmeans_result\(centers) colnames(centers) <- c("PC1", "PC2") # Rename columns for clarity centers\)cluster <- factor(1:nrow(centers)) # Add cluster identifiers

Define descriptive names for the identified clusters

cluster_names <- c(“Apple”, “Banana”, “Mango”, “Orange”) # Customize with actual names as necessary

Add a column for descriptive cluster names to the PCA data

train_data_pca\(cluster_name <- factor(cluster_names[as.numeric(train_data_pca\)cluster)])

Visualize the clusters with ellipses and centroids highlighted

ggplot(train_data_pca, aes(x = PC1, y = PC2, color = cluster_name)) + geom_point(alpha = 0.5, size = 3) + # Plot points for the clusters stat_ellipse(aes(color = cluster_name), alpha = 0.4, linewidth = 1.5, linetype = “solid”) + # Add ellipses around clusters geom_point(data = centers, aes(x = PC1, y = PC2), color = “black”, shape = 3, size = 2, stroke = 2) + # Mark centroids with a different shape labs(title = paste(“K-means Clustering (k =”, optimal_k, “)”), x = “Principal Component 1”, y = “Principal Component 2”) + theme_minimal() + # Apply a minimal theme for aesthetics scale_color_manual(values = c(“red”, “yellow”, “green”, “orange”), # Define custom colors for the clusters name = “Fruit Type”) + # Set legend title theme(legend.position = “right”) # Position the legend to the right

Neural Network Model Training

Perform PCA on training data

pca_model <- prcomp(train_data[, -which(names(train_data) == “label”)], center = TRUE, scale. = TRUE)

Create a PCA dataset for training

train_data_pca <- data.frame(pca_model\(x[, 1:2], label = train_data\)label) # Include label if needed

Apply the PCA transformation to the test data

test_data_pca <- data.frame(predict(pca_model, newdata = test_data[, -which(names(test_data) == “label”)])) test_data_pca <- cbind(test_data_pca, label = test_data$label) # Include the label if needed

Train a neural network model with 5 neurons in the hidden layer

nn_model_5 <- nnet(label ~ ., data = train_data_pca, size = 5, maxit = 200)

Generate predictions using the trained model

predictions_5 <- predict(nn_model_5, newdata = test_data_pca[, -which(names(test_data_pca) == “label”)], type = “class”)

Compute the confusion matrix to evaluate the model’s performance

confusion_matrix_5 <- confusionMatrix(factor(predictions_5, levels = levels(test_data_pca\(label)), test_data_pca\)label)

Calculate overall accuracy from the confusion matrix

accuracy_5 <- sum(diag(confusion_matrix_5\(table)) / sum(confusion_matrix_5\)table) cat(“Accuracy for 5 neurons:”, accuracy_5, “”)

Extract the confusion matrix table for further analysis

confusion_matrix_5_table <- confusion_matrix_5$table

Initialize vectors to store precision, recall, and F1 score for each class

precision_5 <- numeric(nrow(confusion_matrix_5_table)) recall_5 <- numeric(nrow(confusion_matrix_5_table)) f1_score_5 <- numeric(nrow(confusion_matrix_5_table))

Calculate precision, recall, and F1 score for each class based on the confusion matrix

for (i in 1:nrow(confusion_matrix_5_table)) { TP <- confusion_matrix_5_table[i, i] # True Positives for class i FP <- sum(confusion_matrix_5_table[, i]) - TP # False Positives for class i FN <- sum(confusion_matrix_5_table[i, ]) - TP # False Negatives for class i

precision_5[i] <- ifelse((TP + FP) == 0, 0, TP / (TP + FP)) # Calculate precision recall_5[i] <- ifelse((TP + FN) == 0, 0, TP / (TP + FN)) # Calculate recall f1_score_5[i] <- ifelse((precision_5[i] + recall_5[i]) == 0, 0, 2 * (precision_5[i] * recall_5[i]) / (precision_5[i] + recall_5[i])) # Calculate F1 score }

Display calculated metrics (precision, recall, F1 score) for each class

for (i in 1:nrow(confusion_matrix_5_table)) { cat(“:”, rownames(confusion_matrix_5_table)[i], “”) cat(“Precision:”, precision_5[i], “”) cat(“Recall:”, recall_5[i], “”) cat(“F1 Score:”, f1_score_5[i], “”) }

Model Training with 10 Neurons in the Hidden Layer

nn_model_10 <- nnet(label ~ ., data = train_data_pca, size = 10, maxit = 200)

Generate predictions for the 10-neuron model

predictions_10 <- predict(nn_model_10, newdata = test_data_pca[, -which(names(test_data_pca) == “label”)], type = “class”)

Compute the confusion matrix for the 10-neuron model

confusion_matrix_10 <- confusionMatrix(factor(predictions_10, levels = levels(test_data_pca\(label)), test_data_pca\)label)

Calculate overall accuracy for the 10-neuron model

accuracy_10 <- sum(diag(confusion_matrix_10\(table)) / sum(confusion_matrix_10\)table) cat(“Accuracy for 10 neurons:”, accuracy_10, “”)

Extract the confusion matrix table for further analysis

confusion_matrix_10_table <- confusion_matrix_10$table

Initialize vectors to store precision, recall, and F1 score for each class

precision_10 <- numeric(nrow(confusion_matrix_10_table)) recall_10 <- numeric(nrow(confusion_matrix_10_table)) f1_score_10 <- numeric(nrow(confusion_matrix_10_table))

Calculate precision, recall, and F1 score for each class based on the confusion matrix

for (i in 1:nrow(confusion_matrix_10_table)) { TP <- confusion_matrix_10_table[i, i] # True Positives for class i FP <- sum(confusion_matrix_10_table[, i]) - TP # False Positives for class i FN <- sum(confusion_matrix_10_table[i, ]) - TP # False Negatives for class i

precision_10[i] <- ifelse((TP + FP) == 0, 0, TP / (TP + FP)) # Calculate precision recall_10[i] <- ifelse((TP + FN) == 0, 0, TP / (TP + FN)) # Calculate recall f1_score_10[i] <- ifelse((precision_10[i] + recall_10[i]) == 0, 0, 2 * (precision_10[i] * recall_10[i]) / (precision_10[i] + recall_10[i])) # Calculate F1 score }

Display calculated metrics (precision, recall, F1 score) for each class

for (i in 1:nrow(confusion_matrix_10_table)) { cat(“:”, rownames(confusion_matrix_10_table)[i], “”) cat(“Precision:”, precision_10[i], “”) cat(“Recall:”, recall_10[i], “”) cat(“F1 Score:”, f1_score_10[i], “”) }

Model Training with 20 Neurons in the Hidden Layer

nn_model_20 <- nnet(label ~ ., data = train_data_pca, size = 20, maxit = 200)

Generate predictions for the 20-neuron model

predictions_20 <- predict(nn_model_20, newdata = test_data_pca[, -which(names(test_data_pca) == “label”)], type = “class”)

Compute the confusion matrix for the 20-neuron model

confusion_matrix_20 <- confusionMatrix(factor(predictions_20, levels = levels(test_data_pca\(label)), test_data_pca\)label)

Calculate overall accuracy for the 20-neuron model

accuracy_20 <- sum(diag(confusion_matrix_20\(table)) / sum(confusion_matrix_20\)table) cat(“Accuracy for 20 neurons:”, accuracy_20, “”)

Extract the confusion matrix table for further analysis

confusion_matrix_20_table <- confusion_matrix_20$table

Initialize vectors to store precision, recall, and F1 score for each class

precision_20 <- numeric(nrow(confusion_matrix_20_table)) recall_20 <- numeric(nrow(confusion_matrix_20_table)) f1_score_20 <- numeric(nrow(confusion_matrix_20_table))

Calculate precision, recall, and F1 score for each class based on the confusion matrix

for (i in 1:nrow(confusion_matrix_20_table)) { TP <- confusion_matrix_20_table[i, i] # True Positives for class i FP <- sum(confusion_matrix_20_table[, i]) - TP # False Positives for class i FN <- sum(confusion_matrix_20_table[i, ]) - TP # False Negatives for class i

precision_20[i] <- ifelse((TP + FP) == 0, 0, TP / (TP + FP)) # Calculate precision recall_20[i] <- ifelse((TP + FN) == 0, 0, TP / (TP + FN)) # Calculate recall f1_score_20[i] <- ifelse((precision_20[i] + recall_20[i]) == 0, 0, 2 * (precision_20[i] * recall_20[i]) / (precision_20[i] + recall_20[i])) # Calculate F1 score }

Display calculated metrics (precision, recall, F1 score) for each class

for (i in 1:nrow(confusion_matrix_20_table)) { cat(“:”, rownames(confusion_matrix_20_table)[i], “”) cat(“Precision:”, precision_20[i], “”) cat(“Recall:”, recall_20[i], “”) cat(“F1 Score:”, f1_score_20[i], “”) }