{"metadata":{"kernelspec":{"name":"ir","display_name":"R","language":"R"},"language_info":{"name":"R","codemirror_mode":"r","pygments_lexer":"r","mimetype":"text/x-r-source","file_extension":".r","version":"4.4.0"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":3004,"databundleVersionId":861823,"sourceType":"competition"},{"sourceId":10998243,"sourceType":"datasetVersion","datasetId":6846461}],"dockerImageVersionId":30749,"isInternetEnabled":false,"language":"r","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"In this example we are going to be following An Introduction to Statistical Learning R's code for a Convolutional Neural Network (CNN) on the CIFAR100 data, which consists of tens of thousands of 32x32 color images. We begin by downloading the necessary packages and getting the data.","metadata":{}},{"cell_type":"code","source":"# Load in packages\nlibrary(pacman)\np_load(tidyverse, tensorflow, keras, qs)\n\n # Load CIFAR100\ncifar100 <- qread(\"/kaggle/input/cifar100/cifar100.qs\")\n","metadata":{"_uuid":"051d70d956493feee0c6d64651c6a088724dca2a","_execution_state":"idle","trusted":true,"execution":{"iopub.status.busy":"2025-03-13T05:33:41.543285Z","iopub.execute_input":"2025-03-13T05:33:41.579334Z","iopub.status.idle":"2025-03-13T05:33:47.922705Z","shell.execute_reply":"2025-03-13T05:33:47.920464Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Next we assign CIFAR100 into training and test and we normalize the pixel values to the range [0,1] by dividing by 255, the maximum pixel value. After this, we produce a 100 column binary matrix, which is a matrix with a column per class and a 1 value in the column corresponding to the class an observation belongs to. This is all just prep work for the CNN.","metadata":{}},{"cell_type":"code","source":" # Assign data to test and train\nx_train <- cifar100$train$x\ng_train <- cifar100$train$y\nx_test <- cifar100$test$x\ng_test <- cifar100$test$y\n\n # Normalize our pixel values\nx_train <- x_train / 255\nx_test <- x_test / 255\n\n\n #Produce 100 column binary matrix\ny_train <- to_categorical(g_train, 100)\n#dim(y_train)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T05:34:03.442957Z","iopub.execute_input":"2025-03-13T05:34:03.444680Z","iopub.status.idle":"2025-03-13T05:34:05.179931Z","shell.execute_reply":"2025-03-13T05:34:05.178158Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Before starting the CNN, we can view some random training images using the jpeg package.","metadata":{}},{"cell_type":"code","source":"p_load(jpeg)\npar(mar = c(0, 0, 0, 0), mfrow = c(5, 5))\nindex <- sample(seq(50000), 25)\nfor (i in index) plot(as.raster(x_train[i,,, ]))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T02:35:09.795751Z","iopub.execute_input":"2025-03-13T02:35:09.796705Z","iopub.status.idle":"2025-03-13T02:35:10.340249Z","shell.execute_reply":"2025-03-13T02:35:10.338468Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"    In the code block below we define our CNN and there you may notice many familiar concepts mentioned in the Wikipedia, I will also highlight them. The keras_model_sequential() function simply initializes a neural network that will have a linear stack of layers. \n\n    The layer_conv_2d function creates a convolution layer. Notice there are many arguments in this function. The filters argument in this function defines how many convolution filters there are, the kernal_size function defines the size matrix of each filter, the activation argument defines which activation function will be used, and input_shape is just the dimensions of the input that the layer should expect. Notice there is also a padding argument, although it was set to \"same\", I will touch on what this for the first time here. Padding refers to how many extra values should be added around the input image before applying convolutional filters. This simply helps defend against information loss at the edges since interior matrices are overrpresented in the typical convolution process without any padding.\n\n    The layer_max_pooling_2d function creates a pooling layer that uses max pooling. The pool_size argument in this function defines the size of each matrix that will be pooled. \n\n    After the convolutional and pooling layers, we begin with the fully connected layers. The functions layer_flatten() and layer_dropout() are intuitive and directly related to their explanations in the Wikipedia. The layer_dense() functions help produce probabilities for each class given the input from all previous layers so that the model can form a decision of an observations class. The units argument defines how many neurons are in the layer.","metadata":{}},{"cell_type":"code","source":"model <- keras_model_sequential() %>%\n layer_conv_2d(filters = 32, #convolution layer\n               kernel_size = c(3, 3), \n               padding = \"same\", activation = \"relu\",\n               input_shape = c(32, 32, 3)) %>% \nlayer_max_pooling_2d(pool_size = c(2, 2)) %>% #pooling layer\n layer_conv_2d(filters = 64, #convolution layer\n               kernel_size = c(3, 3),\n               padding = \"same\", \n               activation = \"relu\") %>%\n layer_max_pooling_2d(pool_size = c(2, 2)) %>% #pooling layer\n   layer_conv_2d(filters = 128, #convolution layer\n                 kernel_size = c(3, 3),\n                 padding = \"same\", \n                 activation = \"relu\") %>%\n layer_max_pooling_2d(pool_size = c(2, 2)) %>% #pooling layer\n layer_conv_2d(filters = 256,  #convolution layer\n               kernel_size = c(3, 3),\n               padding = \"same\", \n               activation = \"relu\") %>%\n layer_max_pooling_2d(pool_size = c(2, 2)) %>% #pooling layer\n layer_flatten() %>% #start fully connected layers\n layer_dropout(rate = 0.5) %>%\n layer_dense(units = 512, activation = \"relu\") %>%\nlayer_dense(units = 100, activation = \"softmax\")\n\nsummary(model) ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T05:34:05.681759Z","iopub.execute_input":"2025-03-13T05:34:05.683195Z","iopub.status.idle":"2025-03-13T05:34:05.840566Z","shell.execute_reply":"2025-03-13T05:34:05.838692Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Lastly, we fit the model on the test data and acheive 46% accuracy on it. While at first, this might not seem too impressive, it is important to consider that guessing randomly would result in 1% accuracy since there are 100 classes. This is also a simple demonstration model.","metadata":{}},{"cell_type":"code","source":"\n #use categorical crossentropy loss function and accuracy\n#model %>% compile(loss = \"categorical_crossentropy\", #this is the loss function\n#optimizer = optimizer_rmsprop(), metrics = c(\"accuracy\"))\n\n#fit the model on test data\n#history <- model %>% fit(x_train, y_train, epochs = 30,\n#batch_size = 128, validation_split = 0.2)\n\n#model %>% predict(x_test) %>% k_argmax() %>% accuracy(g_test)\n\n\n#predicted_labels <- model %>% predict(x_test) %>% k_argmax()\n#true_labels <- k_argmax(g_test)\n\n#accuracy <- mean(predicted_labels == true_labels)\n#print(accuracy)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T04:51:45.897629Z","iopub.execute_input":"2025-03-13T04:51:45.899619Z","iopub.status.idle":"2025-03-13T04:51:46.185531Z","shell.execute_reply":"2025-03-13T04:51:46.183618Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Compile the model with categorical crossentropy and accuracy as metrics\nmodel %>% compile(\n  loss = \"categorical_crossentropy\",  # Loss function\n  optimizer = optimizer_rmsprop(),    # Optimizer\n  metrics = c(\"accuracy\")             # Metrics\n)\n\n# Fit the model on the training data\nhistory <- model %>% fit(\n  x_train, y_train,                  # Training data and labels\n  epochs = 30,                       # Number of epochs\n  batch_size = 128,                  # Batch size\n  validation_split = 0.2             # Use 20% of the data for validation\n)\n\n# Evaluate the model on the test data\nresults <- model %>% evaluate(x_test, g_test)\n\n# Print test accuracy\ncat(\"Test Accuracy:\", results[[2]], \"\\n\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-13T05:34:23.279133Z","iopub.execute_input":"2025-03-13T05:34:23.280611Z"}},"outputs":[],"execution_count":null}]}