{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":17018,"databundleVersionId":799209,"sourceType":"competition"}],"dockerImageVersionId":31154,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\n#for dirname, _, filenames in os.walk('/kaggle/input'):\n#    for filename in filenames:\n#        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-11-01T19:12:13.190969Z","iopub.execute_input":"2025-11-01T19:12:13.191249Z","iopub.status.idle":"2025-11-01T19:12:13.640717Z","shell.execute_reply.started":"2025-11-01T19:12:13.191224Z","shell.execute_reply":"2025-11-01T19:12:13.639998Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Vehicle Image Classification Project\nThis project will classify images of vehicles. It will use FastAI to train a deep neural network to perform image classification to predict what kind of vehicle is in an image.\n\nThe data is from the Kaggle TAU Vehicle Type Recognition Competition: https://www.kaggle.com/competitions/vehicle/data.\n\n## Set Up\n\nChange the runtime to utilize the NVIDIA T4 GPU.\n\n#### Import the fastai library","metadata":{}},{"cell_type":"code","source":"from fastai.vision.all import *\nfrom fastcore.all import *","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-01T19:12:28.012216Z","iopub.execute_input":"2025-11-01T19:12:28.013026Z","iopub.status.idle":"2025-11-01T19:12:41.550171Z","shell.execute_reply.started":"2025-11-01T19:12:28.012998Z","shell.execute_reply":"2025-11-01T19:12:41.549356Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Vehicle Classifier\n\nLook at a few images.","metadata":{}},{"cell_type":"code","source":"file_names = get_image_files('/kaggle/input/vehicle/train/train/Limousine')\n\n# select an example image\nimg = PILImage.create(file_names[1]) # Change the number here to pick a different image\n\n# plot the image\nimg.to_thumb(192)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-01T19:12:57.800719Z","iopub.execute_input":"2025-11-01T19:12:57.801126Z","iopub.status.idle":"2025-11-01T19:12:58.121298Z","shell.execute_reply.started":"2025-11-01T19:12:57.801093Z","shell.execute_reply":"2025-11-01T19:12:58.120425Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The images look appropriate for the project.","metadata":{}},{"cell_type":"markdown","source":"## Data Processing\n\nThe training data is organized with images of vehicles in folders that name the type of vehicles that are in the images in that folder. \n\nProcess the images (input) and annotations (output) at the same time as part of setting up the neural network model that will be used for image classification. Resize the images so that they are the size required by the neural network.\n\nProcess the images. Load and transform the data.","metadata":{}},{"cell_type":"code","source":"# Step 1: Define the root path\npath = Path('/kaggle/input/vehicle')\n\n# Step 2: Create the DataBlock for training\nvehicles = DataBlock(\n    blocks = (ImageBlock, CategoryBlock),\n    get_items = get_image_files,\n    splitter = GrandparentSplitter(train_name='train', valid_name='train'),  # use part of training set for validation\n    get_y = parent_label,\n    item_tfms = Resize(450),\n    batch_tfms = [*aug_transforms(size=224, max_warp=0), Normalize.from_stats(*imagenet_stats)]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-01T19:13:04.116826Z","iopub.execute_input":"2025-11-01T19:13:04.117688Z","iopub.status.idle":"2025-11-01T19:13:04.423548Z","shell.execute_reply.started":"2025-11-01T19:13:04.117648Z","shell.execute_reply":"2025-11-01T19:13:04.422666Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Load the data.","metadata":{}},{"cell_type":"code","source":"dls = vehicles.dataloaders(path/'train')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-01T19:13:22.561312Z","iopub.execute_input":"2025-11-01T19:13:22.562100Z","iopub.status.idle":"2025-11-01T19:14:19.444017Z","shell.execute_reply.started":"2025-11-01T19:13:22.562064Z","shell.execute_reply":"2025-11-01T19:14:19.443191Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Exploratory Data Analysis\n\nOur exploratory data analysis consists of examining example images. We can use the show_batch() method to show a few images and their labels.","metadata":{}},{"cell_type":"code","source":"dls.show_batch()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-01T19:14:34.395692Z","iopub.execute_input":"2025-11-01T19:14:34.396526Z","iopub.status.idle":"2025-11-01T19:14:37.663500Z","shell.execute_reply.started":"2025-11-01T19:14:34.396497Z","shell.execute_reply":"2025-11-01T19:14:37.662637Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The labels seem appropriate for the images. The images are all of vehicles, which is what we expect.","metadata":{}},{"cell_type":"markdown","source":"## Modeling\n\nUse a deep neural network to build the classification model. Modify an existing deep neural network to solve the problem of recognizing different vehicle types.\n\nThe model will be based on the ResNet-34 deep neural network that was trained on the ImageNet dataset. The ImageNet data set consists of images of many types.\n\nUse transfer learning to train the network to classify images as different types of vehicles.\n\n#### Train and Test the Model\n\nTrain a model to classify the type of vehicle, starting from the resnet34 model that has already been trained to solve an image classification problem involing many types of images.\n\nCreate a vision_learner object by specifying 3 things: (1) the data block created above dls, (2) the name of the neural network we want to use as the basis for the model resnet34, and (3) the metric we want to use to evaluate the performance of the model error_rate.\n\nFine tune the weights of the model to perform our specific task by minimizing the error for a specified number of epochs.","metadata":{}},{"cell_type":"code","source":"learn = vision_learner(dls, resnet34, metrics=error_rate)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-01T19:14:48.765941Z","iopub.execute_input":"2025-11-01T19:14:48.766230Z","iopub.status.idle":"2025-11-01T19:14:49.957643Z","shell.execute_reply.started":"2025-11-01T19:14:48.766208Z","shell.execute_reply":"2025-11-01T19:14:49.956905Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"learn.fine_tune(epochs=1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-01T19:14:56.179732Z","iopub.execute_input":"2025-11-01T19:14:56.180013Z","iopub.status.idle":"2025-11-01T19:38:44.525821Z","shell.execute_reply.started":"2025-11-01T19:14:56.179990Z","shell.execute_reply":"2025-11-01T19:38:44.524891Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The error rate is small on the validation image set.","metadata":{}},{"cell_type":"markdown","source":"#### Assess Model Performance\n\n\nfast.ai has a ClassificationInterpretation function to help analyze the performance of the model.","metadata":{}},{"cell_type":"code","source":"interp = ClassificationInterpretation.from_learner(learn)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-01T19:41:14.874123Z","iopub.execute_input":"2025-11-01T19:41:14.874465Z","iopub.status.idle":"2025-11-01T19:47:27.233280Z","shell.execute_reply.started":"2025-11-01T19:41:14.874418Z","shell.execute_reply":"2025-11-01T19:47:27.232577Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Plot the confusion matrix, which shows the number of images in the validation set that were correctly and incorrectly classified by the model.","metadata":{}},{"cell_type":"code","source":"interp.plot_confusion_matrix(figsize=(6,6))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-01T19:48:24.951316Z","iopub.execute_input":"2025-11-01T19:48:24.952228Z","iopub.status.idle":"2025-11-01T19:54:54.899545Z","shell.execute_reply.started":"2025-11-01T19:48:24.952199Z","shell.execute_reply":"2025-11-01T19:54:54.898443Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The model looks strong on overall accuracy, since the diagonal values are high. It sometimes confuses similar vehicles, like cars and trucks or cars and taxis. Even in those instances, though, it gets more right than wrong.\n\nNext look at the top loss images. Showing the top loss images allows us to see where the model made the largest mistakes by having a high probability that the image was of one class when it was actually a different type of vehicle.","metadata":{}},{"cell_type":"code","source":"interp.plot_top_losses(9, figsize=(15,10))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-01T19:58:09.970993Z","iopub.execute_input":"2025-11-01T19:58:09.971782Z","iopub.status.idle":"2025-11-01T19:58:11.525690Z","shell.execute_reply.started":"2025-11-01T19:58:09.971740Z","shell.execute_reply":"2025-11-01T19:58:11.524491Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"markdown","source":"The top loss images are interesting. I think that some of the images that were reported to be classified incorrectly were actually classified correctly, such as the school bus that was predicted as a bus. ","metadata":{}},{"cell_type":"markdown","source":"## Deployment\n\nWe can use the model to predict the vehicle type for an example image and plot the class probabilities.","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-01T20:00:21.368935Z","iopub.execute_input":"2025-11-01T20:00:21.369889Z","iopub.status.idle":"2025-11-01T20:00:21.607684Z","shell.execute_reply.started":"2025-11-01T20:00:21.369854Z","shell.execute_reply":"2025-11-01T20:00:21.606738Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Import an example image.","metadata":{}},{"cell_type":"code","source":"import requests\nfrom PIL import Image\nfrom fastai.vision.all import PILImage\n\nimage_url = \"https://images.cdn.europe-west1.gcp.commercetools.com/078b97e9-ed31-4c81-baae-cdd44f3bf3c1/9d94369904b4aa91f108-N8UFjDvh-medium.png\"\n\nresponse = requests.get(image_url, stream=True)\nresponse.raise_for_status()\n\n# Open directly from the response stream\nimage = Image.open(response.raw).convert(\"RGB\")\n\nimage_path = \"flying_pigeon.jpg\"\nimage.save(image_path)\n\n# Optional: load into fastai\nfastai_img = PILImage.create(image_path)\nfastai_img.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-01T20:07:25.310055Z","iopub.execute_input":"2025-11-01T20:07:25.310365Z","iopub.status.idle":"2025-11-01T20:07:25.602903Z","shell.execute_reply.started":"2025-11-01T20:07:25.310343Z","shell.execute_reply":"2025-11-01T20:07:25.601946Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\n# Convert to numpy\nprobs_np = probs.detach().cpu().numpy()\n\n# Build a DataFrame with labels and probabilities\ndf = pd.DataFrame({\n    \"Class\": dls.vocab,\n    \"Probability\": probs_np\n})\n\nfig, axes = plt.subplots(1, 2, figsize=(10, 5))\n\n# Show the image\naxes[0].imshow(img)\naxes[0].axis('off')\naxes[0].set_title(f\"Prediction: {prediction}\")\n\n# Horizontal barplot\nsns.barplot(data=df, x=\"Probability\", y=\"Class\", ax=axes[1], orient=\"h\")\naxes[1].set_xlabel(\"Probability\")\naxes[1].set_ylabel(\"Class Label\")\naxes[1].set_title(\"Prediction Probabilities\")\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-01T20:12:40.862031Z","iopub.execute_input":"2025-11-01T20:12:40.862357Z","iopub.status.idle":"2025-11-01T20:12:41.249258Z","shell.execute_reply.started":"2025-11-01T20:12:40.862334Z","shell.execute_reply":"2025-11-01T20:12:41.248256Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The model correctly classified the bicycle.","metadata":{}},{"cell_type":"markdown","source":"## Evaluation\n\nThe model has a low error rate and a confusion matrix that showed that the model performed well overall.\n\nIf I were going to expand this project, I would clean the data set. Since some of the validation data seems to be misclassified in the data set, it's likely that some of the training data was also misclassified. I think that just cleaning the data set and training the model on the clean data set would decrease the model's error rate and improve its overall performance.","metadata":{}}]}