{"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":"tpu1vmV38","dataSources":[{"sourceId":70497,"databundleVersionId":7713244,"sourceType":"competition"}],"dockerImageVersionId":30647,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install tensorflow &> /dev/null\nprint(\"tensorflow installed\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-02-16T08:20:00.097420Z","iopub.execute_input":"2024-02-16T08:20:00.097765Z","iopub.status.idle":"2024-02-16T08:20:00.396090Z","shell.execute_reply.started":"2024-02-16T08:20:00.097736Z","shell.execute_reply":"2024-02-16T08:20:00.394923Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport matplotlib.image as mpimg\n\nfrom zipfile import ZipFile\nfrom os import listdir, walk\nfrom os.path import isfile, join\nfrom tensorflow.keras import Input, Model\nfrom tensorflow.keras.applications import ResNet101V2, VGG19, Xception, InceptionV3\nfrom tensorflow.keras.applications.imagenet_utils import preprocess_input\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array\nfrom tensorflow.keras.layers import GlobalAveragePooling2D, Dense\nfrom tensorflow.keras.optimizers import Adam","metadata":{"execution":{"iopub.status.busy":"2024-02-16T08:20:00.397803Z","iopub.execute_input":"2024-02-16T08:20:00.398079Z","iopub.status.idle":"2024-02-16T08:20:00.404142Z","shell.execute_reply.started":"2024-02-16T08:20:00.398052Z","shell.execute_reply":"2024-02-16T08:20:00.403443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**ImageDataGenerator:** Here, you're creating an instance of the ImageDataGenerator class from the Keras library. This class is used for data augmentation and preprocessing of images during training of deep learning models.\n\n**samplewise_center=True**: This parameter centers each sample (image) around zero by subtracting the mean pixel value across all channels.\n\n**rescale=1/255.**: This parameter scales the pixel values of the images by dividing each pixel value by 255. This operation is commonly performed to normalize the pixel values to the range [0, 1], which can help in training neural networks more effectively by ensuring that the input values are within a similar range.","metadata":{}},{"cell_type":"code","source":"IMG_SIZE = 224\ndatagen = ImageDataGenerator(\n        samplewise_center=True,\n        rescale=1/255.)","metadata":{"execution":{"iopub.status.busy":"2024-02-16T08:20:00.404989Z","iopub.execute_input":"2024-02-16T08:20:00.405224Z","iopub.status.idle":"2024-02-16T08:20:00.416526Z","shell.execute_reply.started":"2024-02-16T08:20:00.405192Z","shell.execute_reply":"2024-02-16T08:20:00.415819Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The **flow_from_directory()** method will search for images inside this directory and its subdirectories to generate training data.\n\n**IMG_SIZE**: is a variable (previously set to 224), indicating that all images will be resized to a square shape of 224x224 pixels. \n\n**color_mode='rgb'**: This parameter specifies the color mode of the input images. 'rgb' indicates that the images are in RGB (Red, Green, Blue) color space.\n\n**class_mode=\"categorical\":** This parameter specifies the type of label arrays that are returned by the data generator. 'categorical' indicates that the labels are represented as one-hot encoded vectors.","metadata":{}},{"cell_type":"code","source":"train_it = datagen.flow_from_directory('../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\")","metadata":{"execution":{"iopub.status.busy":"2024-02-16T08:20:00.418266Z","iopub.execute_input":"2024-02-16T08:20:00.418599Z","iopub.status.idle":"2024-02-16T08:20:00.864930Z","shell.execute_reply.started":"2024-02-16T08:20:00.418571Z","shell.execute_reply":"2024-02-16T08:20:00.863952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"valid_it = datagen.flow_from_directory('../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\")","metadata":{"execution":{"iopub.status.busy":"2024-02-16T08:20:00.865874Z","iopub.execute_input":"2024-02-16T08:20:00.866146Z","iopub.status.idle":"2024-02-16T08:20:00.997405Z","shell.execute_reply.started":"2024-02-16T08:20:00.866121Z","shell.execute_reply":"2024-02-16T08:20:00.996602Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**InceptionV3:** This initializes the InceptionV3 model architecture. InceptionV3 is a deep convolutional neural network architecture that is commonly used for image classification tasks.\n\n**weights='imagenet':** This parameter specifies that the model should be initialized with pre-trained weights from the ImageNet dataset.\n\n**input_shape=(IMG_SIZE, IMG_SIZE, 3):** This parameter defines the shape of the input data that the model expects. In this case, it specifies that the input images should be of size IMG_SIZE x IMG_SIZE pixels with 3 channels (RGB).\n\n**include_top=False:** This parameter specifies whether to include the fully connected layers at the top of the network. Setting it to False means that only the convolutional base of the InceptionV3 model will be used, and the fully connected layers will be omitted. \n\n**base_model.trainable = False:** This line freezes the layers of the base model, preventing them from being updated during training. Freezing the layers of the pre-trained model is typically done to prevent the pre-trained weights from being altered while training the custom classifier on top.","metadata":{}},{"cell_type":"code","source":"base_model = InceptionV3(\n    weights='imagenet',\n    input_shape=(IMG_SIZE, IMG_SIZE, 3),\n    include_top=False)\n\nbase_model.trainable = False","metadata":{"execution":{"iopub.status.busy":"2024-02-16T08:20:00.998395Z","iopub.execute_input":"2024-02-16T08:20:00.998664Z","iopub.status.idle":"2024-02-16T08:20:03.679906Z","shell.execute_reply.started":"2024-02-16T08:20:00.998636Z","shell.execute_reply":"2024-02-16T08:20:03.678994Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Here, **you're passing the input through the pre-trained InceptionV3 base model.** This line applies the pre-trained convolutional layers of InceptionV3 to the input data. The training=False argument ensures that the base model runs in inference mode, meaning that the weights of the base model are not updated during training.\n\n**global average pooling layer** on top of the output of the pre-trained base model. Global average pooling reduces each feature map in the input to a single value by taking the average of all values in the feature map. \n\n**Dense(fully connected layer):** The number of units in this layer is set to the number of classes in your dataset, which is determined by len(train_it.class_indices). The softmax activation function is commonly used in multi-class classification tasks to output probabilities for each class.\n\n","metadata":{}},{"cell_type":"code","source":"inputs = Input(shape=(IMG_SIZE, IMG_SIZE, 3))\n\nx = base_model(inputs, training=False)\nx = GlobalAveragePooling2D()(x)\n\noutputs = Dense(len(train_it.class_indices), activation = 'softmax')(x)\n\nmodel = Model(inputs, outputs)\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2024-02-16T08:20:03.680936Z","iopub.execute_input":"2024-02-16T08:20:03.681218Z","iopub.status.idle":"2024-02-16T08:20:04.364626Z","shell.execute_reply.started":"2024-02-16T08:20:03.681190Z","shell.execute_reply":"2024-02-16T08:20:04.363934Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**epochs** i.e., the number of times the entire training dataset will be passed forward and backward through the neural network. \n\nThe history object returned by the fit() method contains information about the training process, such as the loss and accuracy values over each epoch. This information can be used for visualization and analysis.","metadata":{}},{"cell_type":"code","source":"model.compile(loss = 'categorical_crossentropy' , optimizer='adam', metrics = [\"accuracy\"])","metadata":{"execution":{"iopub.status.busy":"2024-02-16T08:20:04.365526Z","iopub.execute_input":"2024-02-16T08:20:04.365784Z","iopub.status.idle":"2024-02-16T08:20:04.385051Z","shell.execute_reply.started":"2024-02-16T08:20:04.365759Z","shell.execute_reply":"2024-02-16T08:20:04.384396Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"epochs = 10\n\nhistory = model.fit(\n    train_it,\n    epochs=epochs,\n    validation_data=valid_it,\n)","metadata":{"execution":{"iopub.status.busy":"2024-02-16T08:20:04.385872Z","iopub.execute_input":"2024-02-16T08:20:04.386099Z","iopub.status.idle":"2024-02-16T08:39:14.900566Z","shell.execute_reply.started":"2024-02-16T08:20:04.386067Z","shell.execute_reply":"2024-02-16T08:39:14.899577Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.evaluate(valid_it, steps=valid_it.samples/valid_it.batch_size)","metadata":{"execution":{"iopub.status.busy":"2024-02-16T08:39:14.903370Z","iopub.execute_input":"2024-02-16T08:39:14.903709Z","iopub.status.idle":"2024-02-16T08:39:35.477590Z","shell.execute_reply.started":"2024-02-16T08:39:14.903646Z","shell.execute_reply":"2024-02-16T08:39:35.476497Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save('dlai5_inceptionV3_fine_tuned')","metadata":{"execution":{"iopub.status.busy":"2024-02-16T08:39:35.479010Z","iopub.execute_input":"2024-02-16T08:39:35.479374Z","iopub.status.idle":"2024-02-16T08:39:59.687044Z","shell.execute_reply.started":"2024-02-16T08:39:35.479339Z","shell.execute_reply":"2024-02-16T08:39:59.685930Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"zf = ZipFile(\"model_inceptionV3_fine_tuned.zip\", \"w\")\nfor dirname, subdirs, files in walk(\"dlai5_inceptionV3_fine_tuned\"):\n    zf.write(dirname)\n    for filename in files:\n        zf.write(os.path.join(dirname, filename))\nzf.close()","metadata":{"execution":{"iopub.status.busy":"2024-02-16T08:39:59.693918Z","iopub.execute_input":"2024-02-16T08:39:59.694214Z","iopub.status.idle":"2024-02-16T08:40:00.012523Z","shell.execute_reply.started":"2024-02-16T08:39:59.694184Z","shell.execute_reply":"2024-02-16T08:40:00.011400Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"files = [f for f in listdir('../input/csc532-fruits-categorical-classification-2024/csc532_2024_validation/validation') if isfile(join('../input/csc532-fruits-categorical-classification-2024/csc532_2024_validation/validation', f))]","metadata":{"execution":{"iopub.status.busy":"2024-02-16T08:40:00.013793Z","iopub.execute_input":"2024-02-16T08:40:00.014082Z","iopub.status.idle":"2024-02-16T08:40:00.082385Z","shell.execute_reply.started":"2024-02-16T08:40:00.014054Z","shell.execute_reply":"2024-02-16T08:40:00.081400Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**result_dict:** This dictionary is initialized to store the results. It has two keys: 'ID' and 'Code'. 'ID' will contain the filenames, and 'Code' will contain the predicted codes.\n\nFor each filename, it loads the corresponding image, resizes it to the target size (IMG_SIZE), converts it to a NumPy array, reshapes it to match the expected input shape of the model, and normalizes the pixel values to the range [0, 1].\n\nIt uses the trained model (model) to make predictions on the preprocessed image. model.predict(image) generates the model's prediction probabilities for each class. np.argmax() is then used to find the index of the class with the highest probability, and 1 is added to convert the 0-indexed class labels to 1-indexed labels.","metadata":{}},{"cell_type":"code","source":"result_dict = {\n    'ID': [],\n    'Code': [],\n}\n\nfor file in files:\n  image = load_img(f'../input/csc532-fruits-categorical-classification-2024/csc532_2024_validation/validation/{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\n\n  pred = np.argmax(model.predict(image)) + 1\n  result_dict['ID'].append(file)\n  result_dict['Code'].append(pred)","metadata":{"execution":{"iopub.status.busy":"2024-02-16T08:40:00.083492Z","iopub.execute_input":"2024-02-16T08:40:00.083754Z","iopub.status.idle":"2024-02-16T08:40:21.443339Z","shell.execute_reply.started":"2024-02-16T08:40:00.083728Z","shell.execute_reply":"2024-02-16T08:40:21.442372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.DataFrame.from_dict(result_dict)\ndf.to_csv('result_inceptionV3_fine_tuned.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-02-16T08:40:21.444883Z","iopub.execute_input":"2024-02-16T08:40:21.445220Z","iopub.status.idle":"2024-02-16T08:40:21.454195Z","shell.execute_reply.started":"2024-02-16T08:40:21.445185Z","shell.execute_reply":"2024-02-16T08:40:21.453409Z"},"trusted":true},"execution_count":null,"outputs":[]}]}