Arko007 commited on
Commit
7f04373
·
verified ·
1 Parent(s): 62c0f00

Create README.md

Browse files
Files changed (1) hide show
  1. README.md +166 -0
README.md ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language: en
3
+ license: apache-2.0
4
+ tags:
5
+ - image-classification
6
+ - saffron
7
+ - food-quality
8
+ - convnext
9
+ - timm
10
+ - pytorch
11
+ - adulteration-detection
12
+ datasets:
13
+ - Arko007/saffron-verify
14
+ metrics:
15
+ - f1
16
+ - accuracy
17
+ model-index:
18
+ - name: SaffronVerify ConvNeXt-Base
19
+ results:
20
+ - task:
21
+ type: image-classification
22
+ dataset:
23
+ name: saffron-verify
24
+ type: Arko007/saffron-verify
25
+ metrics:
26
+ - type: f1
27
+ value: 0.9888
28
+ name: Macro F1 (best checkpoint)
29
+ - type: accuracy
30
+ value: 0.9896
31
+ name: Accuracy (best checkpoint)
32
+ base_model:
33
+ - facebook/convnext-base-224-22k-1k
34
+ ---
35
+
36
+ # SaffronVerify — ConvNeXt-Base (Pretrained)
37
+
38
+ A high-accuracy saffron quality classification model trained on the
39
+ [Arko007/saffron-verify](https://huggingface.co/datasets/Arko007/saffron-verify)
40
+ dataset. The model classifies saffron images into three grades:
41
+ **Mogra**, **Lacha**, and **Adulterated**.
42
+
43
+ ## Model Performance
44
+
45
+ Best checkpoint saved at **Epoch 13** with early stopping triggered at Epoch 20.
46
+
47
+ | Metric | Value |
48
+ |---|---|
49
+ | Macro F1 | **0.9888** |
50
+ | Accuracy | **98.96%** |
51
+ | Val Loss | 0.3562 |
52
+
53
+ ### Per-Class Results (Epoch 13 — Best Checkpoint)
54
+
55
+ | Class | Precision | Recall | F1-Score | Support |
56
+ |---|---|---|---|---|
57
+ | mogra | 0.98 | 0.98 | 0.98 | 56 |
58
+ | lacha | 0.98 | 0.98 | 0.98 | 64 |
59
+ | adulterated | 1.00 | 1.00 | 1.00 | 72 |
60
+ | **macro avg** | **0.99** | **0.99** | **0.99** | **192** |
61
+
62
+ ## Training Details
63
+
64
+ | Parameter | Value |
65
+ |---|---|
66
+ | Base Model | `convnext_base` (ImageNet-21k pretrained via timm) |
67
+ | Image Size | 512 × 512 |
68
+ | Effective Batch Size | 96 (16 per GPU × 2 GPUs × 3 grad accum) |
69
+ | Optimizer | AdamW (β₁=0.9, β₂=0.999) |
70
+ | Learning Rate | 5e-6 (backbone) / 2.5e-5 (head) |
71
+ | Scheduler | Warmup (5 epochs) + Cosine Annealing |
72
+ | Regularization | Drop rate 0.3, Drop path 0.2, Label smoothing 0.1 |
73
+ | Augmentation | Mixup (α=0.4) + CutMix (α=1.0) |
74
+ | AMP | float16 |
75
+ | Hardware | 2× NVIDIA Tesla T4 (DDP) |
76
+ | Best Epoch | 13 / 50 |
77
+ | Early Stopping | Patience 7 — triggered at Epoch 20 |
78
+
79
+ ## Training Progression
80
+
81
+ | Epoch | Val Loss | Accuracy | Macro F1 |
82
+ |---|---|---|---|
83
+ | 1 | 1.0631 | 51.04% | 0.5088 |
84
+ | 2 | 0.9541 | 71.88% | 0.7154 |
85
+ | 3 | 0.8096 | 81.77% | 0.8118 |
86
+ | 5 | 0.5122 | 90.62% | 0.9033 |
87
+ | 7 | 0.4153 | 95.31% | 0.9506 |
88
+ | 10 | 0.3676 | 97.92% | 0.9777 |
89
+ | **13** | **0.3562** | **98.96%** | **0.9888** |
90
+ | 20 | — | — | — (early stop) |
91
+
92
+ ## Offline Data Augmentation
93
+
94
+ Training data was augmented offline from 167 real images to 3840 balanced
95
+ training images (1280 per class) using a heavy Albumentations pipeline
96
+ including random crops, flips, rotations, colour jitter, blur, noise,
97
+ elastic transforms, perspective distortion, CoarseDropout, and CLAHE.
98
+ Validation set was augmented from 41 real images to 192 balanced images
99
+ (64 per class).
100
+
101
+ ## Usage
102
+
103
+ ```python
104
+ import torch
105
+ import timm
106
+ import torch.nn as nn
107
+ from torchvision import transforms
108
+ from PIL import Image
109
+
110
+ class SaffronVerifyModel(nn.Module):
111
+ def __init__(self):
112
+ super().__init__()
113
+ self.backbone = timm.create_model(
114
+ "convnext_base", pretrained=False,
115
+ num_classes=0, drop_rate=0.3, drop_path_rate=0.2
116
+ )
117
+ feat_dim = self.backbone.num_features
118
+ self.head = nn.Sequential(
119
+ nn.LayerNorm(feat_dim),
120
+ nn.Dropout(p=0.3),
121
+ nn.Linear(feat_dim, 512),
122
+ nn.GELU(),
123
+ nn.Dropout(p=0.15),
124
+ nn.Linear(512, 3),
125
+ )
126
+
127
+ def forward(self, x):
128
+ return self.head(self.backbone(x))
129
+
130
+ CLASSES = ["mogra", "lacha", "adulterated"]
131
+
132
+ # Load model
133
+ model = SaffronVerifyModel()
134
+ ckpt = torch.load("best_model.pth", map_location="cpu")
135
+ model.load_state_dict(ckpt["model_state"])
136
+ model.eval()
137
+
138
+ # Preprocess
139
+ transform = transforms.Compose([
140
+ transforms.Resize(512),
141
+ transforms.CenterCrop(512),
142
+ transforms.ToTensor(),
143
+ transforms.Normalize([0.485, 0.456, 0.406],
144
+ [0.229, 0.224, 0.225]),
145
+ ])
146
+
147
+ img = Image.open("saffron.jpg").convert("RGB")
148
+ tensor = transform(img).unsqueeze(0)
149
+
150
+ with torch.no_grad():
151
+ logits = model(tensor)
152
+ pred = logits.argmax(1).item()
153
+
154
+ print(f"Predicted class: {CLASSES[pred]}")
155
+ ```
156
+ ## Dataset
157
+
158
+ - **Source:** [Arko007/saffron-verify](https://huggingface.co/datasets/Arko007/saffron-verify)
159
+ - **Raw train:** 64 mogra + 64 lacha + 39 adulterated = 167 images
160
+ - **Raw val:** 16 mogra + 16 lacha + 9 adulterated = 41 images
161
+ - **Augmented train:** 3840 (balanced, 1280/class)
162
+ - **Augmented val:** 192 (balanced, 64/class)
163
+
164
+ ## License
165
+
166
+ Apache 2.0