YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
South Ontario Birds Family Classification Model
Overview
This model is a deep learning classifier trained to identify bird families commonly found in South Ontario, Canada. The goal is to contribute to citizen science efforts by providing a tool for automated bird identification based on images.
Dataset
The model was trained on a subset of the iNaturalist 2021 Birds dataset, specifically filtered to include only bird observations located within the geographical boundaries of South Ontario (latitude between 42.5 and 45, longitude between -81 and -75). Original dataset on Kaggle: iNaturalist 2021 Birds
Model Architecture
The model uses a ResNet50 architecture pre-trained on ImageNet. Transfer learning was applied by modifying the final classification layer to predict one of the 37 bird families present in the filtered South Ontario dataset. A dropout layer was added before the final linear layer to help with regularization.
Training Details
The model was trained using the following key hyperparameters, determined through hyperparameter tuning (random search):
- Learning Rate: 0.0001
- Batch Size: 16
- Number of Epochs: 25
- Dropout Rate: 0.6
The training process used the Adam optimizer and Cross-Entropy Loss.
Evaluation
The model was evaluated on a separate test set.
- Accuracy on Test Set: The final accuracy achieved on the test set was approximately 47.04% (based on the last evaluation output).
- Other metrics like Precision, Recall, and F1-Score were also calculated and a confusion matrix was generated during evaluation.
Limitations
- The model's accuracy is moderate (around 47%), indicating that it may struggle with fine-grained classification between similar bird families.
- The dataset is limited to South Ontario, so performance on birds from other regions may vary.
- The model classifies by family, not by individual species.
- The dataset size for some bird families is relatively small, which could impact the model's ability to generalize well to those specific families.
How to Use the Model for Inference
To use the trained model for predicting the bird family of a new image, follow these steps:
Load the Model and Label Map: You will need the
south_ontario_bird_model.pthstate dictionary file and thelabel_map.jsonfile.import torch import torch.nn as nn import torchvision.models as models import torchvision.transforms as transforms from PIL import Image import json # Define the model architecture (must match the trained model) def GetCleanModel(dropoutNum): model_tuned = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V1) num_ftrs_tuned = model_tuned.fc.in_features model_tuned.fc = torch.nn.Sequential( nn.Dropout(p=dropoutNum), torch.nn.Linear(num_ftrs_tuned, 37) # 37 classes for bird families ) return model_tuned # Load the saved model state dictionary model_save_path = 'south_ontario_bird_model.pth' # Path to your saved model file loaded_model = GetCleanModel(dropoutNum = 0.6) # Create a new model instance with the same architecture and dropout loaded_model.load_state_dict(torch.load(model_save_path)) loaded_model.eval() # Set the model to evaluation mode # Load the label map label_map_save_path = 'label_map.json' # Path to your saved label map file with open(label_map_save_path, 'r') as f: reverse_label_map = json.load(f) # Convert keys back to integers if they were saved as strings reverse_label_map = {int(k): v for k, v in reverse_label_map.items()} # Set device device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") loaded_model.to(device) print("Model and label map loaded successfully.")Preprocess the New Image: Apply the same transformations used for the validation/test sets.
# Define the same transformations used for validation/testing inference_transforms = transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) # Example: Load and preprocess a new image new_image_path = 'path/to/your/new_bird_image.jpg' # Replace with the actual path to your new image try: new_image = Image.open(new_image_path).convert('RGB') # Ensure image is RGB input_tensor = inference_transforms(new_image).unsqueeze(0) # Add batch dimension input_tensor = input_tensor.to(device) print("Image preprocessed successfully.") except FileNotFoundError: print(f"Error: New image not found at {new_image_path}") except Exception as e: print(f"An error occurred during image preprocessing: {e}")Make a Prediction: Pass the preprocessed image tensor through the loaded model.
# Make a prediction if 'input_tensor' in locals(): # Check if input_tensor was created successfully with torch.no_grad(): output = loaded_model(input_tensor) _, predicted_class_index = torch.max(output, 1); # Convert the predicted class index back to the bird family name predicted_bird_family = reverse_label_map[predicted_class_index.item()] print(f"The predicted bird family for the new image is: {predicted_bird_family}")