iamsubrata commited on
Commit
628e9ae
·
1 Parent(s): 9a730b6

Add application file, models, support files

Browse files
.DS_Store ADDED
Binary file (6.15 kB). View file
 
.vscode/settings.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "[python]": {
3
+ "editor.defaultFormatter": "ms-python.autopep8"
4
+ },
5
+ "python.formatting.provider": "none"
6
+ }
README.md CHANGED
@@ -1,13 +1,85 @@
 
1
  ---
2
- title: Birds 525 Species Detector
3
- emoji: 🐢
4
- colorFrom: green
5
- colorTo: gray
6
- sdk: streamlit
7
- sdk_version: 1.26.0
8
- app_file: app.py
9
- pinned: false
10
- license: other
11
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+ # Birds 525 Species Detector
2
  ---
3
+ ## 1. Load Data
4
+ [**BIRDS 525 SPECIES IMAGE CLASSIFICATION DATASET**](https://www.kaggle.com/datasets/gpiosenka/100-bird-species)
5
+ - **Dataset Size:** 525 bird species.
6
+ - **Images:** 84,635 training images, 2,625 test images (5 per species), and 2,625 validation images (5 per species).
7
+ - **Image Dimensions:** 224x224x3 JPG format.
8
+ - **Data Structure:** Convenient subdirectories for each species.
9
+ - **Additional File:** `birds.csv` contains file paths, class labels, and more.
10
+
11
+ **Dataset Quality:**
12
+ - Cleaned to remove duplicate and low-quality images.
13
+ - Each image features a single bird taking up at least 50% of pixels.
14
+ - Original images, no augmentation.
15
+
16
+ **File Naming:**
17
+ - Sequential numbering, e.g., "001.jpg," "002.jpg" for training.
18
+ - Test and validation images: "1.jpg" to "5.jpg."
19
+
20
+ **Note:** Training set not balanced but has ≥130 images per species.
21
+
22
+ ## 2. Data Preparation
23
+ **Augmentation Transforms:**
24
+ - Imported augmentation transforms to enhance dataset diversity.
25
+
26
+ **Item Transforms:**
27
+ - Images resized to a consistent width of 460 pixels.
28
+
29
+ **Batch Transforms:**
30
+ - Images resized to 224x224 pixels with a minimum scaling of 75%.
31
+ - Additional augmentations applied to batches for robustness.
32
+
33
+ These transformations ensure data consistency and introduce variability, preparing the dataset for model training.
34
+
35
+ ## 3. Create DataLoader
36
+ **DataBlock Configuration:**
37
+ - Utilized Fastai's DataBlock to define data processing.
38
+ - Blocks specified as (ImageBlock, CategoryBlock) for image and category data.
39
+ - `get_items` set to retrieve image files.
40
+ - Splitter configured using `GrandparentSplitter` to separate train and test sets based on directory names.
41
+ - `get_y` method defined to extract parent label as category.
42
+ - Item and batch transforms (`item_tfms` and `batch_tfms`) applied as configured.
43
+
44
+ **DataLoaders Creation:**
45
+ - Fastai DataLoaders created using the DataBlock and dataset path.
46
+ - Batch size set to 64 for efficient data loading.
47
+
48
+ These steps establish the DataLoaders required for training and validation, making the data ready for model ingestion.
49
+
50
+ ## 4. Create Learner (Model) & Find Learning Rate
51
+ **Pre-trained Model Configuration:**
52
+ - Imported pre-trained ResNet models (resnet34 and resnet50) from torchvision.
53
+ - Created a vision learner using the Fastai library with the ResNet-50 architecture.
54
+ - Enabled the use of pretrained weights and specified evaluation metrics, including accuracy and error rate.
55
+ - Enabled mixed-precision training using `to_fp16()` for enhanced training efficiency.
56
+
57
+ **Finding Learning Rate:**
58
+ - Utilized the `lr_find()` method to determine an optimal learning rate.
59
+ - Discovered a suitable learning rate range (`lr`) for model training, set as `slice(1e-4, 5e-3)`.
60
+
61
+ This section highlights the model configuration, including the choice of architecture, pretrained weights, and learning rate discovery, ensuring an effective setup for model training and evaluation.
62
+
63
+ ## 5. Train & Save Model
64
+ **Model Performance with Resnet50 (Freezed Layers)**
65
+
66
+ | Epoch | Train Loss | Valid Loss | Accuracy | Error Rate | Time |
67
+ |-------|------------|------------|----------|------------|--------|
68
+ | 0 | 1.2802 | 0.4474 | 0.8705 | 0.1295 | 13:50 |
69
+ | 1 | 0.7865 | 0.1838 | 0.9482 | 0.0518 | 11:06 |
70
+ | 2 | 0.4920 | 0.1074 | 0.9695 | 0.0305 | 11:17 |
71
+ | 3 | 0.3435 | 0.0671 | 0.9844 | 0.0156 | 10:44 |
72
+ | 4 | 0.2979 | 0.0590 | 0.9859 | 0.0141 | 11:12 |
73
+
74
+ **Model Training:**
75
+ - The model was trained for 5 epochs using a one-cycle learning rate policy with the specified learning rate range.
76
+ - The training results demonstrate the model's impressive performance, achieving high accuracy and low error rates.
77
+
78
+ **Model Preservation:**
79
+ - Saved the trained model with the name 'model1_freezed' for future use.
80
+ - This step ensures that the model's architecture and learned weights are preserved and can be easily loaded and deployed for various tasks.
81
+
82
+ This section provides an overview of the model's training performance, including training and validation losses, accuracy, and error rates. It also emphasizes the importance of preserving the trained model for future use.
83
+
84
+
85
 
 
app/.DS_Store ADDED
Binary file (6.15 kB). View file
 
app/app.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Import streamlit
2
+ import streamlit as st
3
+ from streamlit_option_menu import option_menu
4
+ from fastai.vision.all import *
5
+ from fastai.learner import load_learner
6
+ import pickle
7
+ from bird_species import model_info
8
+ from bird_species import capture_photo
9
+ from bird_species import upload_photo
10
+
11
+
12
+ def app():
13
+ #######################################################################################################################
14
+
15
+ # Set the page config
16
+ st.set_page_config(
17
+ page_title="Bird 525 Species Detector", # The title of the web page
18
+ page_icon="🕊️", # The icon of the web page, can be an emoji or a file path
19
+ initial_sidebar_state="collapsed"
20
+ )
21
+
22
+ #######################################################################################################################
23
+
24
+ st.markdown("<h1 style='text-align: center;'>🕊️Birds 525 Species Detector🕊️</h1>",
25
+ unsafe_allow_html=True)
26
+
27
+ #######################################################################################################################
28
+
29
+ # Options Menu at the top of the homepage
30
+ selected = option_menu(None, ["Upload", "Capture", "Model"],
31
+ icons=["cloud upload", "camera", "gear"],
32
+ menu_icon="cast", default_index=0, orientation="horizontal")
33
+
34
+ #######################################################################################################################
35
+
36
+ # Load model and model class labels (vocab)
37
+ model = load_learner(fname="models/birds_learner.pkl")
38
+
39
+ with open("models/birds_vocab.pkl", "rb") as f:
40
+ vocab = pickle.load(f)
41
+ # Sorting
42
+ vocab = sorted(vocab)
43
+
44
+ with open("models/freezed_model_summary.pkl", "rb") as f:
45
+ freezed_arch_summary = pickle.load(f)
46
+
47
+ with open("models/unfreezed_model_summary.pkl", "rb") as f:
48
+ unfreezed_arch_summary = pickle.load(f)
49
+
50
+ #######################################################################################################################
51
+
52
+ if selected == "Upload":
53
+ st.caption("""Our project utilizes FastAI Vision with the ResNet50 architecture to classify
54
+ 525 bird species. Our dataset comprises 84,635 training images, 2,625 test images and 2,625 validation
55
+ images, all standardized to 224x224x3 pixels. Initial training yields 96.6% accuracy, improved to 98% post
56
+ fine-tuning. Despite gender imbalances, it's a valuable resource for accurate bird species classification.""")
57
+
58
+ upload_photo(model=model, vocab=vocab, key="upload photo")
59
+
60
+ #######################################################################################################################
61
+
62
+ if selected == "Capture":
63
+ capture_photo(model=model, vocab=None, key="capture photo")
64
+
65
+ if selected == "Model":
66
+ model_info()
67
+ st.subheader("FastAi Model Summary (Freezed)")
68
+ st.code(freezed_arch_summary)
69
+ st.subheader("FastAi Model Summary (Unfreezed)")
70
+ st.code(unfreezed_arch_summary)
71
+
72
+
73
+ #######################################################################################################################
74
+ if __name__ == "__main__":
75
+ app()
app/bird_species.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Import streamlit
2
+ import streamlit as st
3
+ from streamlit_option_menu import option_menu
4
+ from PIL import Image
5
+ import pandas as pd
6
+ from fastai.vision.all import *
7
+ from fastai.learner import load_learner
8
+
9
+ #######################################################################################################################
10
+
11
+ def upload_photo(model=None, vocab=None, key=None):
12
+ options = st.multiselect("**Find & select multiple names, then perform Web Search, Download, Upload & Detect...**",
13
+ vocab,
14
+ vocab[100:108],
15
+ key="birds_detector 1")
16
+ st.text(f"Your selection: {options}")
17
+
18
+ uploaded_image = st.file_uploader(
19
+ "**Upload an image**", type=["jpg", "png", "jpeg"], key=key)
20
+ st.divider()
21
+
22
+ if uploaded_image:
23
+ image = Image.open(uploaded_image)
24
+ st.image(image, use_column_width=True)
25
+
26
+ if st.button("**Detect**", type="primary"):
27
+ output = model.predict(image)
28
+ st.markdown(f"""
29
+ <div style="text-align:center;">
30
+ <h1>{output[0]}</h1>
31
+ </div>""",
32
+ unsafe_allow_html=True)
33
+
34
+ st.image(
35
+ image, caption=f'{output[0]} {max(output[2]).item() * 100:.2f}%', use_column_width=True)
36
+
37
+ #######################################################################################################################
38
+
39
+ def capture_photo(model=None, vocab=None, key=None):
40
+ capture_toggle = st.toggle(
41
+ label="**`Enable Camera`**", key="birds_capture_photo")
42
+
43
+ if capture_toggle:
44
+ # Check if the cancel checkbox is not selected
45
+ img_file_buffer = st.camera_input(
46
+ label="Take a picture (`try to keep the subject at the center`)", key=key)
47
+
48
+ if img_file_buffer:
49
+ # To read image file buffer as a PIL Image:
50
+ image = Image.open(img_file_buffer)
51
+
52
+ st.image(image, use_column_width=True)
53
+
54
+ if st.button(label="Detect", key="pets_capture_detect"):
55
+
56
+ output = model.predict(image)
57
+ st.markdown(f"""<div style="text-align:center;">
58
+ <h1>{output[0]}</h1>
59
+ </div>""",
60
+ unsafe_allow_html=True)
61
+
62
+ st.image(
63
+ image, caption=f'{output[0]} {max(output[2]).item() * 100:.2f}%', use_column_width=True)
64
+
65
+ #######################################################################################################################
66
+
67
+ def model_info():
68
+ # Model performance on Freezed Layers
69
+ st.subheader("Model performance with Resnet50 (freezed layers)")
70
+ freezed_data = {
71
+ 'epoch': [0, 1, 2, 3, 4],
72
+ 'train_loss': [1.280186, 0.786523, 0.491951, 0.343532, 0.297919],
73
+ 'valid_loss': [0.447442, 0.183758, 0.107396, 0.067139, 0.058960],
74
+ 'accuracy': [0.870476, 0.948190, 0.969524, 0.984381, 0.985905],
75
+ 'error_rate': [0.129524, 0.051810, 0.030476, 0.015619, 0.014095],
76
+ 'time': ['13:50', '11:06', '11:17', '10:44', '11:12']
77
+ }
78
+
79
+ df = pd.DataFrame(freezed_data)
80
+ st.table(df)
81
+
82
+ # Model performance on Unfreezed Layers
83
+ st.subheader("Model performance with Resnet50 (unfreezed layers)")
84
+ # Create a DataFrame with the provided data
85
+ unfreezed_data = {
86
+ 'epoch': [0, 1, 2, 3, 4],
87
+ 'train_loss': [0.989004, 0.699652, 0.447756, 0.258508, 0.160852],
88
+ 'valid_loss': [0.391414, 0.176702, 0.089814, 0.037954, 0.029704],
89
+ 'accuracy': [0.896381, 0.949714, 0.975238, 0.991238, 0.992762],
90
+ 'error_rate': [0.103619, 0.050286, 0.024762, 0.008762, 0.007238],
91
+ 'time': ['17:05', '12:41', '12:12', '14:43', '12:30']
92
+ }
93
+
94
+ df = pd.DataFrame(unfreezed_data)
95
+
96
+ # Create a Streamlit table
97
+ st.table(df)
98
+
99
+ #######################################################################################################################
models/birds_learner.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5c1e6951eb889c8ccc74ce374ad895dbc75729528cb9391869906db7f940281c
3
+ size 105634905
models/birds_vocab.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ba7936fc583eab66f5c0007492366a946ac7d19a411214f04122e97027214238
3
+ size 12695
models/freezed_model_summary.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bdca1fa49df71b40420b42e95803dbc66eb1ddc4bbf304b837099c74e2f7370c
3
+ size 13999
models/unfreezed_model_summary.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e7cf8743aa71a4cbb2a86a7cdf5447b58f5e438dd1438343b00bd5312ac3b79e
3
+ size 13968
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ fastai
2
+ streamlit
3
+ streamlit-option-menu