umeleti commited on
Commit
162c17c
·
verified ·
1 Parent(s): 463ae93

Upload folder using huggingface_hub

Browse files
acevedo_baseline_resnet18/config.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "BaselineClassifierForImageClassification"
4
+ ],
5
+ "model_type": "baseline_classifier",
6
+ "auto_map": {
7
+ "AutoConfig": "hf_model.BaselineClassifierConfig",
8
+ "AutoModel": "hf_model.BaselineClassifierForImageClassification"
9
+ },
10
+ "arch": "resnet18",
11
+ "num_classes": 8,
12
+ "dropout_p": 0.5,
13
+ "pretrained": false
14
+ }
acevedo_baseline_resnet18/hf_model.py ADDED
@@ -0,0 +1,255 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ HuggingFace-compatible model wrapper for BaselineClassifier.
3
+ This allows model loading without dependency on the source code.
4
+ """
5
+
6
+ from typing import Optional, Tuple
7
+ import torch
8
+ import torch.nn as nn
9
+ import torch.nn.functional as F
10
+ from transformers import PreTrainedModel, PretrainedConfig
11
+ from transformers.utils import logging
12
+
13
+ logger = logging.get_logger(__name__)
14
+
15
+
16
+ class BaselineClassifierConfig(PretrainedConfig):
17
+ """Configuration class for BaselineClassifier."""
18
+ model_type = "baseline_classifier"
19
+
20
+ def __init__(
21
+ self,
22
+ arch: str = "resnet18",
23
+ num_classes: int = 2,
24
+ dropout_p: float = 0.5,
25
+ pretrained: bool = False,
26
+ **kwargs
27
+ ):
28
+ super().__init__(**kwargs)
29
+ self.arch = arch
30
+ self.num_classes = num_classes
31
+ self.dropout_p = dropout_p
32
+ self.pretrained = pretrained
33
+
34
+
35
+ class BaselineClassifier(nn.Module):
36
+ """
37
+ Classification model with selectable ResNet/ViT backbone.
38
+ Grabs penultimate features, then applies Dropout + Linear.
39
+ Includes helpers for Monte Carlo Dropout inference.
40
+ """
41
+
42
+ def __init__(
43
+ self,
44
+ arch: str = "resnet50",
45
+ num_classes: int = 2,
46
+ dropout_p: float = 0.5,
47
+ pretrained: bool = True,
48
+ ):
49
+ super().__init__()
50
+ self.backbone_name = arch
51
+ self.num_classes = num_classes
52
+ self.dropout_p = dropout_p
53
+ self.pretrained = pretrained
54
+
55
+ if arch.startswith("resnet"):
56
+ self.feature_extractor, feat_dim = self._build_resnet(arch, pretrained)
57
+ elif arch.startswith("vit_"):
58
+ self.feature_extractor, feat_dim = self._build_vit(arch, pretrained)
59
+ else:
60
+ raise ValueError(f"Unsupported backbone: {arch}")
61
+
62
+ self.classifier = nn.Sequential(
63
+ nn.Dropout(p=dropout_p, inplace=False),
64
+ nn.Linear(feat_dim, num_classes),
65
+ )
66
+
67
+ def _build_resnet(self, name: str, pretrained: bool) -> Tuple[nn.Module, int]:
68
+ from torchvision import models
69
+
70
+ ctor_map = {
71
+ "resnet18": models.resnet18,
72
+ "resnet34": models.resnet34,
73
+ "resnet50": models.resnet50,
74
+ }
75
+ weights_enums = {
76
+ "resnet18": getattr(models, "ResNet18_Weights", None),
77
+ "resnet34": getattr(models, "ResNet34_Weights", None),
78
+ "resnet50": getattr(models, "ResNet50_Weights", None),
79
+ }
80
+ default_weights_attr = {
81
+ "resnet18": "IMAGENET1K_V1",
82
+ "resnet34": "IMAGENET1K_V1",
83
+ "resnet50": "IMAGENET1K_V2",
84
+ }
85
+
86
+ ctor = ctor_map[name]
87
+ weights = None
88
+ if pretrained:
89
+ enum = weights_enums[name]
90
+ if enum is not None:
91
+ try:
92
+ weights = getattr(enum, default_weights_attr[name])
93
+ except Exception:
94
+ weights = None
95
+
96
+ try:
97
+ model = ctor(weights=weights if pretrained else None)
98
+ except TypeError:
99
+ model = ctor(pretrained=pretrained)
100
+
101
+ feat_dim = model.fc.in_features
102
+ model.fc = nn.Identity()
103
+ return model, feat_dim
104
+
105
+ def _build_vit(self, name: str, pretrained: bool) -> Tuple[nn.Module, int]:
106
+ from torchvision import models
107
+
108
+ ctor_map = {
109
+ "vit_b_16": models.vit_b_16,
110
+ "vit_b_32": models.vit_b_32,
111
+ "vit_l_16": models.vit_l_16,
112
+ "vit_l_32": models.vit_l_32,
113
+ "vit_h_14": models.vit_h_14,
114
+ }
115
+ weights_enums = {
116
+ "vit_b_16": getattr(models, "ViT_B_16_Weights", None),
117
+ "vit_b_32": getattr(models, "ViT_B_32_Weights", None),
118
+ "vit_l_16": getattr(models, "ViT_L_16_Weights", None),
119
+ "vit_l_32": getattr(models, "ViT_L_32_Weights", None),
120
+ "vit_h_14": getattr(models, "ViT_H_14_Weights", None),
121
+ }
122
+ default_attr = "IMAGENET1K_V1"
123
+
124
+ ctor = ctor_map[name]
125
+ weights = None
126
+ if pretrained:
127
+ enum = weights_enums[name]
128
+ if enum is not None:
129
+ try:
130
+ weights = getattr(enum, default_attr)
131
+ except Exception:
132
+ weights = None
133
+
134
+ try:
135
+ vit = ctor(weights=weights if pretrained else None)
136
+ except TypeError:
137
+ vit = ctor(pretrained=pretrained)
138
+
139
+ feat_dim: Optional[int] = None
140
+ if hasattr(vit, "heads") and hasattr(vit.heads, "head") and hasattr(vit.heads.head, "in_features"):
141
+ feat_dim = vit.heads.head.in_features
142
+ else:
143
+ last_linear = None
144
+ for m in vit.heads.modules():
145
+ if isinstance(m, nn.Linear):
146
+ last_linear = m
147
+ if last_linear is not None:
148
+ feat_dim = last_linear.in_features
149
+ if feat_dim is None:
150
+ raise RuntimeError(f"Could not infer feature dimension for {name}")
151
+
152
+ vit.heads = nn.Identity()
153
+ return vit, feat_dim
154
+
155
+ def forward(self, x: torch.Tensor, return_features: bool = False):
156
+ feats = self.feature_extractor(x)
157
+ if isinstance(feats, torch.Tensor) and feats.dim() == 4:
158
+ feats = feats.flatten(1)
159
+ logits = self.classifier(feats)
160
+ if return_features:
161
+ return logits, feats
162
+ return logits
163
+
164
+ @staticmethod
165
+ def _set_batchnorm_eval(module: nn.Module):
166
+ if isinstance(module, (nn.BatchNorm1d, nn.BatchNorm2d, nn.BatchNorm3d, nn.SyncBatchNorm)):
167
+ module.eval()
168
+
169
+ @staticmethod
170
+ def _set_dropout_train(module: nn.Module):
171
+ if isinstance(module, (nn.Dropout, nn.Dropout1d, nn.Dropout2d, nn.Dropout3d)):
172
+ module.train()
173
+
174
+ def enable_mc_dropout(self):
175
+ """Activate dropout layers while leaving other layers as-is."""
176
+ self.apply(self._set_dropout_train)
177
+
178
+ @torch.no_grad()
179
+ def mc_predict(
180
+ self,
181
+ x: torch.Tensor,
182
+ T: int = 20,
183
+ return_std: bool = True,
184
+ apply_softmax: bool = True,
185
+ ):
186
+ """
187
+ Perform T stochastic passes with dropout active and BN frozen.
188
+ """
189
+ was_training = self.training
190
+ try:
191
+ self.train(True)
192
+ self.apply(self._set_batchnorm_eval)
193
+ self.apply(self._set_dropout_train)
194
+
195
+ all_logits = []
196
+ all_probs = []
197
+ for _ in range(T):
198
+ logits = self.forward(x)
199
+ all_logits.append(logits)
200
+ all_probs.append(F.softmax(logits, dim=-1) if apply_softmax else logits)
201
+
202
+ logits_stack = torch.stack(all_logits, 0)
203
+ probs_stack = torch.stack(all_probs, 0)
204
+ mean_logits = logits_stack.mean(0)
205
+ mean_probs = probs_stack.mean(0)
206
+ if return_std:
207
+ std = logits_stack.std(0, unbiased=False)
208
+ return mean_logits, mean_probs, std
209
+ return mean_logits, mean_probs
210
+ finally:
211
+ self.train(was_training)
212
+
213
+
214
+ class BaselineClassifierForImageClassification(PreTrainedModel):
215
+ """
216
+ HuggingFace-compatible wrapper for BaselineClassifier.
217
+
218
+ This allows the model to be loaded with:
219
+ from transformers import AutoModel
220
+ model = AutoModel.from_pretrained("org/my-model", trust_remote_code=True)
221
+ """
222
+ config_class = BaselineClassifierConfig
223
+ base_model_prefix = "model"
224
+
225
+ def __init__(self, config: BaselineClassifierConfig):
226
+ super().__init__(config)
227
+ self.model = BaselineClassifier(
228
+ arch=config.arch,
229
+ num_classes=config.num_classes,
230
+ dropout_p=config.dropout_p,
231
+ pretrained=config.pretrained,
232
+ )
233
+
234
+ def forward(
235
+ self,
236
+ pixel_values: torch.Tensor,
237
+ return_dict: bool = True,
238
+ return_features: bool = False,
239
+ ):
240
+ """
241
+ Args:
242
+ pixel_values: Input tensor of shape (batch_size, 3, 224, 224)
243
+ return_dict: Whether to return dict or tuple
244
+ return_features: Whether to return intermediate features
245
+ """
246
+ if return_features:
247
+ logits, features = self.model(pixel_values, return_features=True)
248
+ if return_dict:
249
+ return {"logits": logits, "features": features}
250
+ return logits, features
251
+
252
+ logits = self.model(pixel_values)
253
+ if return_dict:
254
+ return {"logits": logits}
255
+ return logits
acevedo_baseline_resnet18/pytorch_model.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2ce202f1dd0099817041fddb8366de1e7d060aad8cc8051a3bec5f7658baf2d3
3
+ size 44802123