thinh-researcher commited on
Commit
9d17be0
·
1 Parent(s): dfb82f2
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ env
2
+ __pycache__
TUTORIAL.md ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ # Write a custom models
2
+
3
+ Ref: https://huggingface.co/docs/transformers/custom_models
4
+
5
+ ## Writing a custom configuration
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ transformers
2
+ timm
resnet_config/__init__.py ADDED
File without changes
resnet_config/configuration_resnet.py ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import List
2
+
3
+ from transformers import PretrainedConfig
4
+
5
+ """
6
+ The configuration of a model is an object that
7
+ will contain all the necessary information to build the model.
8
+
9
+ The three important things to remember when writing you own configuration are the following:
10
+
11
+ - you have to inherit from PretrainedConfig,
12
+ - the __init__ of your PretrainedConfig must accept any kwargs,
13
+ - those kwargs need to be passed to the superclass __init__.
14
+ """
15
+
16
+
17
+ class ResnetConfig(PretrainedConfig):
18
+
19
+ """
20
+ Defining a model_type for your configuration (here model_type="resnet") is not mandatory,
21
+ unless you want to register your model with the auto classes (see last section)."""
22
+
23
+ model_type = "resnet"
24
+
25
+ def __init__(
26
+ self,
27
+ block_type="bottleneck",
28
+ layers: List[int] = [3, 4, 6, 3],
29
+ num_classes: int = 1000,
30
+ input_channels: int = 3,
31
+ cardinality: int = 1,
32
+ base_width: int = 64,
33
+ stem_width: int = 64,
34
+ stem_type: str = "",
35
+ avg_down: bool = False,
36
+ **kwargs,
37
+ ):
38
+ if block_type not in ["basic", "bottleneck"]:
39
+ raise ValueError(
40
+ f"`block_type` must be 'basic' or bottleneck', got {block_type}."
41
+ )
42
+ if stem_type not in ["", "deep", "deep-tiered"]:
43
+ raise ValueError(
44
+ f"`stem_type` must be '', 'deep' or 'deep-tiered', got {stem_type}."
45
+ )
46
+
47
+ self.block_type = block_type
48
+ self.layers = layers
49
+ self.num_classes = num_classes
50
+ self.input_channels = input_channels
51
+ self.cardinality = cardinality
52
+ self.base_width = base_width
53
+ self.stem_width = stem_width
54
+ self.stem_type = stem_type
55
+ self.avg_down = avg_down
56
+ super().__init__(**kwargs)
57
+
58
+
59
+ if __name__ == "__main__":
60
+ """
61
+ With this done, you can easily create and save your configuration like
62
+ you would do with any other model config of the library.
63
+ Here is how we can create a resnet50d config and save it:
64
+ """
65
+ resnet50d_config = ResnetConfig(
66
+ block_type="bottleneck", stem_width=32, stem_type="deep", avg_down=True
67
+ )
68
+ resnet50d_config.save_pretrained("custom-resnet")
69
+
70
+ """
71
+ This will save a file named config.json inside the folder custom-resnet.
72
+ You can then reload your config with the from_pretrained method:
73
+ """
74
+ resnet50d_config = ResnetConfig.from_pretrained("custom-resnet")
75
+
76
+ """
77
+ You can also use any other method of the PretrainedConfig class,
78
+ like push_to_hub() to directly upload your config to the Hub.
79
+ """
resnet_config/custom-resnet/config.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "avg_down": true,
3
+ "base_width": 64,
4
+ "block_type": "bottleneck",
5
+ "cardinality": 1,
6
+ "input_channels": 3,
7
+ "layers": [
8
+ 3,
9
+ 4,
10
+ 6,
11
+ 3
12
+ ],
13
+ "model_type": "resnet",
14
+ "num_classes": 1000,
15
+ "stem_type": "deep",
16
+ "stem_width": 32,
17
+ "transformers_version": "4.26.1"
18
+ }
resnet_config/modeling_resnet.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Dict
2
+
3
+ import torch
4
+ from timm.models.resnet import BasicBlock, Bottleneck, ResNet
5
+ from torch import Tensor, nn
6
+ from transformers import PreTrainedModel
7
+
8
+ from .configuration_resnet import ResnetConfig
9
+
10
+ BLOCK_MAPPING = {"basic": BasicBlock, "bottleneck": Bottleneck}
11
+
12
+
13
+ class ResnetModel(PreTrainedModel):
14
+ config_class = ResnetConfig
15
+
16
+ def __init__(self, config: ResnetConfig):
17
+ super().__init__(config)
18
+ block_layer = BLOCK_MAPPING[config.block_type]
19
+ self.model = ResNet(
20
+ block_layer,
21
+ config.layers,
22
+ num_classes=config.num_classes,
23
+ in_chans=config.input_channels,
24
+ cardinality=config.cardinality,
25
+ base_width=config.base_width,
26
+ stem_width=config.stem_width,
27
+ stem_type=config.stem_type,
28
+ avg_down=config.avg_down,
29
+ )
30
+
31
+ def forward(self, tensor):
32
+ return self.model.forward_features(tensor)
33
+
34
+
35
+ class ResnetModelForImageClassification(PreTrainedModel):
36
+ config_class = ResnetConfig
37
+
38
+ def __init__(self, config: ResnetConfig):
39
+ super().__init__(config)
40
+ block_layer = BLOCK_MAPPING[config.block_type]
41
+ self.model = ResNet(
42
+ block_layer,
43
+ config.layers,
44
+ num_classes=config.num_classes,
45
+ in_chans=config.input_channels,
46
+ cardinality=config.cardinality,
47
+ base_width=config.base_width,
48
+ stem_width=config.stem_width,
49
+ stem_type=config.stem_type,
50
+ avg_down=config.avg_down,
51
+ )
52
+
53
+ def forward(self, tensor: Tensor, labels=None) -> Dict[str, Tensor]:
54
+ logits = self.model(tensor)
55
+ if labels is not None:
56
+ loss = nn.cross_entropy(logits, labels)
57
+ return {"loss": loss, "logits": logits}
58
+ return {"logits": logits}