attilaultzindur commited on
Commit
35f28e0
·
1 Parent(s): 45912c7

model & handler update

Browse files
Files changed (3) hide show
  1. README.md +4 -85
  2. config.json +1 -1
  3. handler.py +15 -13
README.md CHANGED
@@ -1,91 +1,10 @@
1
  ---
2
-
3
  pipeline_tag: image-classification
4
  library_name: torchvision
5
- tags:
6
- - image-classification
7
- - efficientnet
8
- - efficientnet-v2
9
- - garbage
10
- - waste-sorting
11
- metrics:
12
- - accuracy
13
-
14
- ---
15
-
16
- # Garbage Classifier – EfficientNet‑V2‑S
17
-
18
- A finetuned EfficientNet‑V2‑S model that recognises **10 waste categories**
19
- (battery, glass, plastic, etc.) for smart recycling and sorting applications.
20
-
21
- | id | class |
22
- | -: | ---------- |
23
- | 0 | battery |
24
- | 1 | biological |
25
- | 2 | cardboard |
26
- | 3 | clothes |
27
- | 4 | glass |
28
- | 5 | metal |
29
- | 6 | paper |
30
- | 7 | plastic |
31
- | 8 | shoes |
32
- | 9 | trash |
33
-
34
- ---
35
-
36
- ## Quick Start
37
-
38
- ```python
39
- from huggingface_hub import InferenceClient
40
-
41
- client = InferenceClient("attilaultzindur/garbage_classifier_effnetv2s_ft")
42
-
43
- with open("your_image.jpg", "rb") as f:
44
- predictions = client.post(data={"inputs": f.read()})
45
- print(predictions)
46
- ```
47
-
48
- Example output:
49
-
50
- ```json
51
- [
52
- {"label": "plastic", "score": 0.997},
53
- {"label": "metal", "score": 0.002},
54
-
55
- ]
56
- ```
57
-
58
- ---
59
-
60
- ## Model Details
61
-
62
- | Field | Value |
63
- | ------------------------ | --------------------------------------------------------- |
64
- | Architecture | EfficientNet‑V2‑S (torchvision) |
65
- | Input size | `3 × 224 × 224` |
66
- | Normalisation | mean = \[0.485 0.456 0.406], std = \[0.229 0.224 0.225] |
67
- | Classification head | `Linear(1280→256) → ReLU → Dropout(0.5) → Linear(256→10)` |
68
- | Best validation accuracy | **97.6 %** after 20 epochs |
69
-
70
- ### Training summary
71
-
72
- * **Dataset:** [Garbage Classification v2 (Kaggle)](https://www.kaggle.com/datasets/sumn2u/garbage-classification-v2)
73
- split 80 % train / 20 % val
74
- * **Augmentations:** RandomResizedCrop, ColorJitter, RandomAffine, HorizontalFlip
75
- * **Optimiser:** Adam, LR = 1 e‑4
76
- * **Frozen layers:** first 70 % of feature blocks
77
- * **Hardware:** single NVIDIA GPU
78
-
79
- ---
80
-
81
- ## Reproduce
82
-
83
- The full training script is provided in `train_script.py`.
84
- Run it with the same hyper‑parameters to reproduce the checkpoint.
85
-
86
  ---
87
 
88
- ## Licence
89
 
90
- No licence has been specified yet.
91
- Add an appropriate open‑source licence before using the model in production.
 
1
  ---
 
2
  pipeline_tag: image-classification
3
  library_name: torchvision
4
+ tags: [image-classification, efficientnet, garbage]
5
+ metrics: [accuracy]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  ---
7
 
8
+ # Garbage Classifier – EfficientNet‑V2‑S
9
 
10
+ Finetuned model that recognises 10 waste categories.
 
config.json CHANGED
@@ -14,5 +14,5 @@
14
  "shoes",
15
  "trash"
16
  ],
17
- "library": "torchvision"
18
  }
 
14
  "shoes",
15
  "trash"
16
  ],
17
+ "library_name": "torchvision"
18
  }
handler.py CHANGED
@@ -1,37 +1,39 @@
1
  from typing import Dict, Any
2
  import io, base64, torch, torchvision
3
- from safetensors.torch import load_file
4
  from PIL import Image
5
  from torchvision import transforms as T
 
6
 
7
  class EndpointHandler:
8
- def __init__(self, path='.'): # path = repo root in container
9
  self.labels = ['battery', 'biological', 'cardboard', 'clothes', 'glass', 'metal', 'paper', 'plastic', 'shoes', 'trash']
10
- self.model = torchvision.models.efficientnet_v2_s(weights=None)
11
  nf = self.model.classifier[1].in_features
12
  self.model.classifier = torch.nn.Sequential(
13
  torch.nn.Linear(nf, 256),
14
  torch.nn.ReLU(inplace=True),
15
  torch.nn.Dropout(0.5),
16
- torch.nn.Linear(256, len(self.labels))
17
  )
18
- state = load_file(str(pth), device="cpu")
19
  self.model.load_state_dict(state)
20
  self.model.eval()
21
- self.trans = T.Compose([
 
22
  T.Resize((224, 224)),
23
  T.ToTensor(),
24
- T.Normalize(mean=[0.485,0.456,0.406], std=[0.229,0.224,0.225])
 
25
  ])
26
 
27
  def __call__(self, data: Dict[str, Any]):
28
- img_bytes = data['inputs']
29
- if isinstance(img_bytes, str): # base64
30
  img_bytes = base64.b64decode(img_bytes)
31
- img = Image.open(io.BytesIO(img_bytes)).convert('RGB')
32
- x = self.trans(img).unsqueeze(0)
33
  with torch.no_grad():
34
  probs = self.model(x).softmax(1)[0]
35
  topk = probs.topk(5)
36
- return [{'label': self.labels[i], 'score': float(topk.values[j])}
37
- for j, i in enumerate(topk.indices)]
 
1
  from typing import Dict, Any
2
  import io, base64, torch, torchvision
 
3
  from PIL import Image
4
  from torchvision import transforms as T
5
+ from safetensors.torch import load_file
6
 
7
  class EndpointHandler:
8
+ def __init__(self, path: str = "."):
9
  self.labels = ['battery', 'biological', 'cardboard', 'clothes', 'glass', 'metal', 'paper', 'plastic', 'shoes', 'trash']
10
+ self.model = torchvision.models.efficientnet_v2_s(weights=None)
11
  nf = self.model.classifier[1].in_features
12
  self.model.classifier = torch.nn.Sequential(
13
  torch.nn.Linear(nf, 256),
14
  torch.nn.ReLU(inplace=True),
15
  torch.nn.Dropout(0.5),
16
+ torch.nn.Linear(256, len(self.labels)),
17
  )
18
+ state = load_file(f"{path}/model.safetensors", device="cpu")
19
  self.model.load_state_dict(state)
20
  self.model.eval()
21
+
22
+ self.preprocess = T.Compose([
23
  T.Resize((224, 224)),
24
  T.ToTensor(),
25
+ T.Normalize(mean=[0.485,0.456,0.406],
26
+ std =[0.229,0.224,0.225])
27
  ])
28
 
29
  def __call__(self, data: Dict[str, Any]):
30
+ img_bytes = data["inputs"]
31
+ if isinstance(img_bytes, str): # base64
32
  img_bytes = base64.b64decode(img_bytes)
33
+ img = Image.open(io.BytesIO(img_bytes)).convert("RGB")
34
+ x = self.preprocess(img).unsqueeze(0)
35
  with torch.no_grad():
36
  probs = self.model(x).softmax(1)[0]
37
  topk = probs.topk(5)
38
+ return [{"label": self.labels[i], "score": float(topk.values[j])}
39
+ for j,i in enumerate(topk.indices)]