Image Feature Extraction
Transformers
ONNX
Safetensors
English
Japanese
egara_net
feature-extraction
embeddings
illustration
vision-transformer
dino
custom-architecture
custom_code
Instructions to use Columba1198/EgaraNet with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Columba1198/EgaraNet with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-feature-extraction", model="Columba1198/EgaraNet", trust_remote_code=True)# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("Columba1198/EgaraNet", trust_remote_code=True, dtype="auto") - Notebooks
- Google Colab
- Kaggle
Upload folder using huggingface_hub
Browse files- README.md +12 -10
- config.json +17 -17
- configuration_egara_net.py +66 -66
- model.safetensors +1 -1
- modeling_egara_net.py +14 -14
- onnx/egara_net_fp16.onnx +2 -2
- onnx/egara_net_fp32.onnx +2 -2
- onnx/egara_net_int8.onnx +2 -2
README.md
CHANGED
|
@@ -8,8 +8,6 @@ tags:
|
|
| 8 |
- image-feature-extraction
|
| 9 |
- embeddings
|
| 10 |
- illustration
|
| 11 |
-
- art-style
|
| 12 |
-
- style-transfer
|
| 13 |
- vision-transformer
|
| 14 |
- dino
|
| 15 |
- custom-architecture
|
|
@@ -23,13 +21,15 @@ model-index:
|
|
| 23 |
|
| 24 |
# EgaraNet β Illustration Style Embedding Model
|
| 25 |
|
| 26 |
-
EgaraNet is an embedding model that encodes the artistic style of illustrations into 1024-dimensional L2-normalized vectors. It was trained on approximately
|
|
|
|
|
|
|
| 27 |
|
| 28 |
## Model Description
|
| 29 |
|
| 30 |
| | |
|
| 31 |
|---|---|
|
| 32 |
-
| **Architecture** | DINOv3 ViT-L/16 backbone + StyleNet (Transposed
|
| 33 |
| **Embedding Dim** | 1024 |
|
| 34 |
| **Input** | RGB images, any resolution (multiples of 16 recommended) |
|
| 35 |
| **Output** | L2-normalized style embedding vector |
|
|
@@ -38,8 +38,8 @@ EgaraNet is an embedding model that encodes the artistic style of illustrations
|
|
| 38 |
### Architecture
|
| 39 |
|
| 40 |
- **Backbone**: DINOv3 ViT-L/16 (frozen during training) β extracts rich visual features
|
| 41 |
-
- **StyleNet Head**: 3 Γ Transposed Transformer
|
| 42 |
-
- **Transposed Transformer
|
| 43 |
|
| 44 |
## Usage with Transformers
|
| 45 |
|
|
@@ -101,7 +101,7 @@ with torch.no_grad():
|
|
| 101 |
## Input Requirements
|
| 102 |
|
| 103 |
- **Image format**: RGB images (PNG, JPEG, WebP, etc.)
|
| 104 |
-
- **Resolution**: Dynamic β the model accepts images of
|
| 105 |
- **Batch size**: Dynamic. For batch inference, all images must have the same spatial dimensions. Process images with different aspect ratios individually or use padding.
|
| 106 |
- **Normalization**: ImageNet statistics β mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]
|
| 107 |
|
|
@@ -141,9 +141,11 @@ The model outputs an `EgaraNetOutput` dataclass with:
|
|
| 141 |
|
| 142 |
## References
|
| 143 |
|
| 144 |
-
- DINOv3: [arXiv:2508.10104](https://arxiv.org/abs/2508.10104)
|
| 145 |
-
-
|
| 146 |
-
-
|
|
|
|
|
|
|
| 147 |
|
| 148 |
## Links
|
| 149 |
|
|
|
|
| 8 |
- image-feature-extraction
|
| 9 |
- embeddings
|
| 10 |
- illustration
|
|
|
|
|
|
|
| 11 |
- vision-transformer
|
| 12 |
- dino
|
| 13 |
- custom-architecture
|
|
|
|
| 21 |
|
| 22 |
# EgaraNet β Illustration Style Embedding Model
|
| 23 |
|
| 24 |
+
EgaraNet is an embedding model that encodes the artistic style of illustrations into 1024-dimensional L2-normalized vectors. It was trained on approximately 1.2 million illustrations from around 12,000 artists, learning to produce embeddings where illustrations by the same artist are close together in the vector space.
|
| 25 |
+
|
| 26 |
+
> Produced under Article 30-4 of the Japanese Copyright Act.
|
| 27 |
|
| 28 |
## Model Description
|
| 29 |
|
| 30 |
| | |
|
| 31 |
|---|---|
|
| 32 |
+
| **Architecture** | DINOv3 ViT-L/16 backbone + StyleNet (Transposed Attention Transformer) head |
|
| 33 |
| **Embedding Dim** | 1024 |
|
| 34 |
| **Input** | RGB images, any resolution (multiples of 16 recommended) |
|
| 35 |
| **Output** | L2-normalized style embedding vector |
|
|
|
|
| 38 |
### Architecture
|
| 39 |
|
| 40 |
- **Backbone**: DINOv3 ViT-L/16 (frozen during training) β extracts rich visual features
|
| 41 |
+
- **StyleNet Head**: 3 Γ Transposed Attention Transformer β Attention Pooling β Projection Head
|
| 42 |
+
- **Transposed Attention Transformer (TAT)**: Computes cross-covariance attention in channel space (CΓC), discarding spatial information to isolate artistic style. Uses RMSNorm and SwiGLU FFN.
|
| 43 |
|
| 44 |
## Usage with Transformers
|
| 45 |
|
|
|
|
| 101 |
## Input Requirements
|
| 102 |
|
| 103 |
- **Image format**: RGB images (PNG, JPEG, WebP, etc.)
|
| 104 |
+
- **Resolution**: Dynamic β the model accepts images of any resolution where height and width are multiples of 16. The recommended preprocessing is `MaxResizeMod16(512)` which scales the long edge to 512px while preserving aspect ratio and snapping both dimensions to multiples of 16.
|
| 105 |
- **Batch size**: Dynamic. For batch inference, all images must have the same spatial dimensions. Process images with different aspect ratios individually or use padding.
|
| 106 |
- **Normalization**: ImageNet statistics β mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]
|
| 107 |
|
|
|
|
| 141 |
|
| 142 |
## References
|
| 143 |
|
| 144 |
+
- **DINOv3**: "DINOv3" [arXiv:2508.10104](https://arxiv.org/abs/2508.10104)
|
| 145 |
+
- **Style Transfer**: "Image Style Transfer Using Convolutional Neural Networks" [CVPR 2016](https://openaccess.thecvf.com/content_cvpr_2016/html/Gatys_Image_Style_Transfer_CVPR_2016_paper.html)
|
| 146 |
+
- **Restormer**: "Restormer: Efficient Transformer for High-Resolution Image Restoration" [arXiv:2111.09881](https://arxiv.org/abs/2111.09881)
|
| 147 |
+
- **MHTA**: "Multi-Head Transposed Attention Transformer for Sea Ice Segmentation in Sar Imagery" [IGARSS 2024](https://ieeexplore.ieee.org/document/10640437)
|
| 148 |
+
- **MANIQA**: "MANIQA: Multi-dimension Attention Network for No-Reference Image Quality Assessment" [arXiv:2204.08958](https://arxiv.org/abs/2204.08958)
|
| 149 |
|
| 150 |
## Links
|
| 151 |
|
config.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
{
|
| 2 |
-
"_comment": "EgaraNet: DINOv3 ViT-L backbone + StyleNet (Transposed
|
| 3 |
|
| 4 |
"model_type": "egara_net",
|
| 5 |
"architectures": ["EgaraNetModel"],
|
|
@@ -49,31 +49,31 @@
|
|
| 49 |
"transformers_version": "4.56.0.dev0"
|
| 50 |
},
|
| 51 |
|
| 52 |
-
"_section_stylenet": "--- StyleNet: Transposed Transformer
|
| 53 |
|
| 54 |
-
"
|
| 55 |
-
"
|
| 56 |
|
| 57 |
-
"
|
| 58 |
-
"
|
| 59 |
|
| 60 |
-
"
|
| 61 |
-
"
|
| 62 |
|
| 63 |
-
"
|
| 64 |
-
"
|
| 65 |
|
| 66 |
-
"
|
| 67 |
-
"
|
| 68 |
|
| 69 |
-
"
|
| 70 |
-
"
|
| 71 |
-
"
|
| 72 |
-
"
|
| 73 |
|
| 74 |
"_section_attnpool": "--- Attention Pooling ---",
|
| 75 |
"attn_pool_num_heads": 8,
|
| 76 |
-
"_attn_pool_note": "nn.MultiheadAttention heads used in AttentionPooling. Must divide
|
| 77 |
|
| 78 |
"_section_head": "--- Projection Head (hidden -> output) ---",
|
| 79 |
"head_act": "silu",
|
|
|
|
| 1 |
{
|
| 2 |
+
"_comment": "EgaraNet: DINOv3 ViT-L backbone + StyleNet (Transposed Attention Transformer) composite model config.",
|
| 3 |
|
| 4 |
"model_type": "egara_net",
|
| 5 |
"architectures": ["EgaraNetModel"],
|
|
|
|
| 49 |
"transformers_version": "4.56.0.dev0"
|
| 50 |
},
|
| 51 |
|
| 52 |
+
"_section_stylenet": "--- StyleNet: Transposed Attention Transformer (TAT) head ---",
|
| 53 |
|
| 54 |
+
"tat_input_dim": null,
|
| 55 |
+
"_tat_input_dim_note": "null = auto-inferred from backbone_config.hidden_size at model init",
|
| 56 |
|
| 57 |
+
"tat_hidden_dim": 1024,
|
| 58 |
+
"_tat_hidden_dim_note": "Internal channel dimension of TAT layers. Matches backbone hidden_size for ViT-L.",
|
| 59 |
|
| 60 |
+
"tat_output_dim": 1024,
|
| 61 |
+
"_tat_output_dim_note": "Final L2-normalised style vector dimension.",
|
| 62 |
|
| 63 |
+
"tat_num_layers": 3,
|
| 64 |
+
"_tat_num_layers_note": "Number of stacked TransposedAttentionTransformer layers.",
|
| 65 |
|
| 66 |
+
"tat_num_heads": 16,
|
| 67 |
+
"_tat_num_heads_note": "Number of attention heads in TAT. Must divide tat_hidden_dim evenly. (1024 / 16 = 64)",
|
| 68 |
|
| 69 |
+
"_section_tat_internals": "--- TAT internals (derived / documented for reference) ---",
|
| 70 |
+
"tat_rms_norm_eps": 1e-05,
|
| 71 |
+
"tat_swiglu_multiple": 64,
|
| 72 |
+
"_tat_swiglu_note": "SwiGLU hidden = round_up(floor(hidden_dim * 8/3), multiple). E.g. 768->2048, 1024->2752.",
|
| 73 |
|
| 74 |
"_section_attnpool": "--- Attention Pooling ---",
|
| 75 |
"attn_pool_num_heads": 8,
|
| 76 |
+
"_attn_pool_note": "nn.MultiheadAttention heads used in AttentionPooling. Must divide tat_hidden_dim.",
|
| 77 |
|
| 78 |
"_section_head": "--- Projection Head (hidden -> output) ---",
|
| 79 |
"head_act": "silu",
|
configuration_egara_net.py
CHANGED
|
@@ -10,8 +10,8 @@ Model structure
|
|
| 10 |
β config stored under `backbone_config`
|
| 11 |
βstyle_net : StyleNet
|
| 12 |
βinput_proj : Identity or Linear (input_dim β hidden_dim)
|
| 13 |
-
β
|
| 14 |
-
β βRMSNorm +
|
| 15 |
β βRMSNorm + SwiGLU FFN
|
| 16 |
βattn_pool : AttentionPooling (learned query β MHA)
|
| 17 |
βhead : Linear β SiLU β Linear (L2-normalised output)
|
|
@@ -22,10 +22,10 @@ Usage
|
|
| 22 |
|
| 23 |
# Build from scratch
|
| 24 |
cfg = EgaraNetConfig(
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
)
|
| 30 |
cfg.save_pretrained("./my_egara_net/")
|
| 31 |
|
|
@@ -75,35 +75,35 @@ class EgaraNetConfig(PretrainedConfig):
|
|
| 75 |
``"facebook/dinov3-vitl16-pretrain-lvd1689m"``. Ignored when
|
| 76 |
``backbone_config`` is provided explicitly.
|
| 77 |
|
| 78 |
-
|
| 79 |
Input channel dimension fed into StyleNet. ``None`` (default)
|
| 80 |
means it is inferred automatically from
|
| 81 |
``backbone_config.hidden_size`` at model initialisation.
|
| 82 |
|
| 83 |
-
|
| 84 |
-
Internal channel width of every
|
| 85 |
query. Should match ``backbone_config.hidden_size`` (1024 for ViT-L).
|
| 86 |
|
| 87 |
-
|
| 88 |
Dimension of the final L2-normalised style vector.
|
| 89 |
|
| 90 |
-
|
| 91 |
-
Number of stacked ``
|
| 92 |
|
| 93 |
-
|
| 94 |
-
Number of attention heads inside each
|
| 95 |
-
Must satisfy ``
|
| 96 |
|
| 97 |
-
|
| 98 |
Ξ΅ used in all ``RMSNorm`` layers.
|
| 99 |
|
| 100 |
-
|
| 101 |
SwiGLU hidden dim is rounded up to the nearest multiple of this
|
| 102 |
-
value. ``hidden = round_up(floor(
|
| 103 |
|
| 104 |
attn_pool_num_heads (int):
|
| 105 |
Number of heads for ``nn.MultiheadAttention`` inside
|
| 106 |
-
``AttentionPooling``. Must divide ``
|
| 107 |
|
| 108 |
head_act (str):
|
| 109 |
Activation between the two linear layers in the projection head.
|
|
@@ -130,14 +130,14 @@ class EgaraNetConfig(PretrainedConfig):
|
|
| 130 |
# Backbone
|
| 131 |
backbone_config: dict | PretrainedConfig | None = None,
|
| 132 |
backbone_model_id: str = "facebook/dinov3-vitl16-pretrain-lvd1689m",
|
| 133 |
-
# StyleNet /
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
# Attention Pooling
|
| 142 |
attn_pool_num_heads: int = 8,
|
| 143 |
# Projection Head
|
|
@@ -150,18 +150,18 @@ class EgaraNetConfig(PretrainedConfig):
|
|
| 150 |
**kwargs: Any,
|
| 151 |
) -> None:
|
| 152 |
# Validate constraints
|
| 153 |
-
if
|
| 154 |
raise ValueError(
|
| 155 |
-
f"
|
| 156 |
-
f"
|
| 157 |
)
|
| 158 |
-
if
|
| 159 |
raise ValueError(
|
| 160 |
-
f"
|
| 161 |
f"attn_pool_num_heads ({attn_pool_num_heads})."
|
| 162 |
)
|
| 163 |
-
if
|
| 164 |
-
raise ValueError(f"
|
| 165 |
|
| 166 |
# Backbone config
|
| 167 |
if isinstance(backbone_config, dict):
|
|
@@ -171,13 +171,13 @@ class EgaraNetConfig(PretrainedConfig):
|
|
| 171 |
self.backbone_model_id: str = backbone_model_id
|
| 172 |
|
| 173 |
# StyleNet params
|
| 174 |
-
self.
|
| 175 |
-
self.
|
| 176 |
-
self.
|
| 177 |
-
self.
|
| 178 |
-
self.
|
| 179 |
-
self.
|
| 180 |
-
self.
|
| 181 |
|
| 182 |
# Attention Pooling
|
| 183 |
self.attn_pool_num_heads: int = attn_pool_num_heads
|
|
@@ -205,20 +205,20 @@ class EgaraNetConfig(PretrainedConfig):
|
|
| 205 |
)
|
| 206 |
|
| 207 |
@property
|
| 208 |
-
def
|
| 209 |
"""Actual input_dim used by StyleNet input_proj."""
|
| 210 |
-
return self.
|
| 211 |
else self.backbone_hidden_size
|
| 212 |
|
| 213 |
@property
|
| 214 |
-
def
|
| 215 |
"""Derived SwiGLU intermediate dimension (not stored in JSON)."""
|
| 216 |
-
return _swiglu_hidden_dim(self.
|
| 217 |
|
| 218 |
@property
|
| 219 |
-
def
|
| 220 |
-
"""Per-head dimension inside
|
| 221 |
-
return self.
|
| 222 |
|
| 223 |
# Serialisation
|
| 224 |
|
|
@@ -245,14 +245,14 @@ class EgaraNetConfig(PretrainedConfig):
|
|
| 245 |
f"EgaraNetConfig(\n"
|
| 246 |
f" backbone : {backbone_name}"
|
| 247 |
f" (hidden={getattr(self.backbone_config, 'hidden_size', '?')})\n"
|
| 248 |
-
f"
|
| 249 |
-
f"({'auto' if self.
|
| 250 |
-
f"
|
| 251 |
-
f"
|
| 252 |
-
f"
|
| 253 |
-
f"
|
| 254 |
-
f"(head_dim={self.
|
| 255 |
-
f"
|
| 256 |
f" attn_pool_heads : {self.attn_pool_num_heads}\n"
|
| 257 |
f" head_act : {self.head_act}\n"
|
| 258 |
f" image_size : {self.image_size} "
|
|
@@ -284,10 +284,10 @@ if __name__ == "__main__":
|
|
| 284 |
|
| 285 |
cfg = EgaraNetConfig(
|
| 286 |
backbone_config=backbone_cfg,
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
|
| 291 |
attn_pool_num_heads=8,
|
| 292 |
)
|
| 293 |
print(cfg)
|
|
@@ -296,12 +296,12 @@ if __name__ == "__main__":
|
|
| 296 |
tmp = pathlib.Path("/tmp/egara_net_test")
|
| 297 |
cfg.save_pretrained(tmp)
|
| 298 |
cfg2 = EgaraNetConfig.from_pretrained(tmp)
|
| 299 |
-
assert cfg.
|
| 300 |
-
assert cfg.
|
| 301 |
-
assert cfg.
|
| 302 |
print("Round-trip OK β")
|
| 303 |
|
| 304 |
# Derived properties
|
| 305 |
-
print(f"SwiGLU hidden dim : {cfg.
|
| 306 |
-
print(f"
|
| 307 |
-
print(f"Effective input : {cfg.
|
|
|
|
| 10 |
β config stored under `backbone_config`
|
| 11 |
βstyle_net : StyleNet
|
| 12 |
βinput_proj : Identity or Linear (input_dim β hidden_dim)
|
| 13 |
+
βtat_layers [ΓN] : TransposedAttentionTransformer
|
| 14 |
+
β βRMSNorm + TAT attention (cross-covariance / transposed)
|
| 15 |
β βRMSNorm + SwiGLU FFN
|
| 16 |
βattn_pool : AttentionPooling (learned query β MHA)
|
| 17 |
βhead : Linear β SiLU β Linear (L2-normalised output)
|
|
|
|
| 22 |
|
| 23 |
# Build from scratch
|
| 24 |
cfg = EgaraNetConfig(
|
| 25 |
+
tat_hidden_dim=1024,
|
| 26 |
+
tat_output_dim=1024,
|
| 27 |
+
tat_num_layers=3,
|
| 28 |
+
tat_num_heads=16,
|
| 29 |
)
|
| 30 |
cfg.save_pretrained("./my_egara_net/")
|
| 31 |
|
|
|
|
| 75 |
``"facebook/dinov3-vitl16-pretrain-lvd1689m"``. Ignored when
|
| 76 |
``backbone_config`` is provided explicitly.
|
| 77 |
|
| 78 |
+
tat_input_dim (int | None):
|
| 79 |
Input channel dimension fed into StyleNet. ``None`` (default)
|
| 80 |
means it is inferred automatically from
|
| 81 |
``backbone_config.hidden_size`` at model initialisation.
|
| 82 |
|
| 83 |
+
tat_hidden_dim (int):
|
| 84 |
+
Internal channel width of every TAT layer and the AttentionPooling
|
| 85 |
query. Should match ``backbone_config.hidden_size`` (1024 for ViT-L).
|
| 86 |
|
| 87 |
+
tat_output_dim (int):
|
| 88 |
Dimension of the final L2-normalised style vector.
|
| 89 |
|
| 90 |
+
tat_num_layers (int):
|
| 91 |
+
Number of stacked ``TransposedAttentionTransformer`` layers.
|
| 92 |
|
| 93 |
+
tat_num_heads (int):
|
| 94 |
+
Number of attention heads inside each TAT.
|
| 95 |
+
Must satisfy ``tat_hidden_dim % tat_num_heads == 0``.
|
| 96 |
|
| 97 |
+
tat_rms_norm_eps (float):
|
| 98 |
Ξ΅ used in all ``RMSNorm`` layers.
|
| 99 |
|
| 100 |
+
tat_swiglu_multiple (int):
|
| 101 |
SwiGLU hidden dim is rounded up to the nearest multiple of this
|
| 102 |
+
value. ``hidden = round_up(floor(tat_hidden_dim * 8/3), multiple)``.
|
| 103 |
|
| 104 |
attn_pool_num_heads (int):
|
| 105 |
Number of heads for ``nn.MultiheadAttention`` inside
|
| 106 |
+
``AttentionPooling``. Must divide ``tat_hidden_dim``.
|
| 107 |
|
| 108 |
head_act (str):
|
| 109 |
Activation between the two linear layers in the projection head.
|
|
|
|
| 130 |
# Backbone
|
| 131 |
backbone_config: dict | PretrainedConfig | None = None,
|
| 132 |
backbone_model_id: str = "facebook/dinov3-vitl16-pretrain-lvd1689m",
|
| 133 |
+
# StyleNet / TAT
|
| 134 |
+
tat_input_dim: int | None = None,
|
| 135 |
+
tat_hidden_dim: int = 1024,
|
| 136 |
+
tat_output_dim: int = 1024,
|
| 137 |
+
tat_num_layers: int = 3,
|
| 138 |
+
tat_num_heads: int = 16,
|
| 139 |
+
tat_rms_norm_eps: float = 1e-5,
|
| 140 |
+
tat_swiglu_multiple: int = 64,
|
| 141 |
# Attention Pooling
|
| 142 |
attn_pool_num_heads: int = 8,
|
| 143 |
# Projection Head
|
|
|
|
| 150 |
**kwargs: Any,
|
| 151 |
) -> None:
|
| 152 |
# Validate constraints
|
| 153 |
+
if tat_hidden_dim % tat_num_heads != 0:
|
| 154 |
raise ValueError(
|
| 155 |
+
f"tat_hidden_dim ({tat_hidden_dim}) must be divisible by "
|
| 156 |
+
f"tat_num_heads ({tat_num_heads})."
|
| 157 |
)
|
| 158 |
+
if tat_hidden_dim % attn_pool_num_heads != 0:
|
| 159 |
raise ValueError(
|
| 160 |
+
f"tat_hidden_dim ({tat_hidden_dim}) must be divisible by "
|
| 161 |
f"attn_pool_num_heads ({attn_pool_num_heads})."
|
| 162 |
)
|
| 163 |
+
if tat_num_layers < 1:
|
| 164 |
+
raise ValueError(f"tat_num_layers must be >= 1, got {tat_num_layers}.")
|
| 165 |
|
| 166 |
# Backbone config
|
| 167 |
if isinstance(backbone_config, dict):
|
|
|
|
| 171 |
self.backbone_model_id: str = backbone_model_id
|
| 172 |
|
| 173 |
# StyleNet params
|
| 174 |
+
self.tat_input_dim: int | None = tat_input_dim
|
| 175 |
+
self.tat_hidden_dim: int = tat_hidden_dim
|
| 176 |
+
self.tat_output_dim: int = tat_output_dim
|
| 177 |
+
self.tat_num_layers: int = tat_num_layers
|
| 178 |
+
self.tat_num_heads: int = tat_num_heads
|
| 179 |
+
self.tat_rms_norm_eps: float = tat_rms_norm_eps
|
| 180 |
+
self.tat_swiglu_multiple: int = tat_swiglu_multiple
|
| 181 |
|
| 182 |
# Attention Pooling
|
| 183 |
self.attn_pool_num_heads: int = attn_pool_num_heads
|
|
|
|
| 205 |
)
|
| 206 |
|
| 207 |
@property
|
| 208 |
+
def effective_tat_input_dim(self) -> int:
|
| 209 |
"""Actual input_dim used by StyleNet input_proj."""
|
| 210 |
+
return self.tat_input_dim if self.tat_input_dim is not None \
|
| 211 |
else self.backbone_hidden_size
|
| 212 |
|
| 213 |
@property
|
| 214 |
+
def tat_swiglu_hidden_dim(self) -> int:
|
| 215 |
"""Derived SwiGLU intermediate dimension (not stored in JSON)."""
|
| 216 |
+
return _swiglu_hidden_dim(self.tat_hidden_dim, self.tat_swiglu_multiple)
|
| 217 |
|
| 218 |
@property
|
| 219 |
+
def tat_head_dim(self) -> int:
|
| 220 |
+
"""Per-head dimension inside TAT attention."""
|
| 221 |
+
return self.tat_hidden_dim // self.tat_num_heads
|
| 222 |
|
| 223 |
# Serialisation
|
| 224 |
|
|
|
|
| 245 |
f"EgaraNetConfig(\n"
|
| 246 |
f" backbone : {backbone_name}"
|
| 247 |
f" (hidden={getattr(self.backbone_config, 'hidden_size', '?')})\n"
|
| 248 |
+
f" tat_input_dim : {self.effective_tat_input_dim} "
|
| 249 |
+
f"({'auto' if self.tat_input_dim is None else 'explicit'})\n"
|
| 250 |
+
f" tat_hidden_dim : {self.tat_hidden_dim}\n"
|
| 251 |
+
f" tat_output_dim : {self.tat_output_dim}\n"
|
| 252 |
+
f" tat_num_layers : {self.tat_num_layers}\n"
|
| 253 |
+
f" tat_num_heads : {self.tat_num_heads} "
|
| 254 |
+
f"(head_dim={self.tat_head_dim})\n"
|
| 255 |
+
f" tat_swiglu_hidden : {self.tat_swiglu_hidden_dim}\n"
|
| 256 |
f" attn_pool_heads : {self.attn_pool_num_heads}\n"
|
| 257 |
f" head_act : {self.head_act}\n"
|
| 258 |
f" image_size : {self.image_size} "
|
|
|
|
| 284 |
|
| 285 |
cfg = EgaraNetConfig(
|
| 286 |
backbone_config=backbone_cfg,
|
| 287 |
+
tat_hidden_dim=backbone_cfg.get("hidden_size", 1024),
|
| 288 |
+
tat_output_dim=backbone_cfg.get("hidden_size", 1024),
|
| 289 |
+
tat_num_layers=3,
|
| 290 |
+
tat_num_heads=16,
|
| 291 |
attn_pool_num_heads=8,
|
| 292 |
)
|
| 293 |
print(cfg)
|
|
|
|
| 296 |
tmp = pathlib.Path("/tmp/egara_net_test")
|
| 297 |
cfg.save_pretrained(tmp)
|
| 298 |
cfg2 = EgaraNetConfig.from_pretrained(tmp)
|
| 299 |
+
assert cfg.tat_hidden_dim == cfg2.tat_hidden_dim
|
| 300 |
+
assert cfg.tat_output_dim == cfg2.tat_output_dim
|
| 301 |
+
assert cfg.tat_num_layers == cfg2.tat_num_layers
|
| 302 |
print("Round-trip OK β")
|
| 303 |
|
| 304 |
# Derived properties
|
| 305 |
+
print(f"SwiGLU hidden dim : {cfg.tat_swiglu_hidden_dim}")
|
| 306 |
+
print(f"TAT head dim : {cfg.tat_head_dim}")
|
| 307 |
+
print(f"Effective input : {cfg.effective_tat_input_dim}")
|
model.safetensors
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
size 1389584856
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2f4e3c6f00d0ffe0e40c9481150465c297805cc482fc83881d0212cc1f8cb90f
|
| 3 |
size 1389584856
|
modeling_egara_net.py
CHANGED
|
@@ -5,7 +5,7 @@ Hugging Face PreTrainedModel implementation for EgaraNet.
|
|
| 5 |
|
| 6 |
EgaraNet is a composite model:
|
| 7 |
backbone : DINOv3 ViT (frozen feature extractor)
|
| 8 |
-
style_net : StyleNet (Transposed Transformer
|
| 9 |
|
| 10 |
Usage:
|
| 11 |
from modeling_egara_net import EgaraNetModel
|
|
@@ -81,9 +81,9 @@ class SwiGLU(nn.Module):
|
|
| 81 |
return self.w_down(F.silu(self.w_gate(x)) * self.w_up(x))
|
| 82 |
|
| 83 |
|
| 84 |
-
class
|
| 85 |
"""
|
| 86 |
-
|
| 87 |
Cross-covariance attention in (HeadDim Γ HeadDim) space.
|
| 88 |
"""
|
| 89 |
|
|
@@ -151,13 +151,13 @@ class AttentionPooling(nn.Module):
|
|
| 151 |
|
| 152 |
class StyleNet(nn.Module):
|
| 153 |
"""
|
| 154 |
-
StyleNet head:
|
| 155 |
"""
|
| 156 |
|
| 157 |
def __init__(self, config: EgaraNetConfig):
|
| 158 |
super().__init__()
|
| 159 |
-
input_dim = config.
|
| 160 |
-
hidden_dim = config.
|
| 161 |
|
| 162 |
self.input_proj = (
|
| 163 |
nn.Identity()
|
|
@@ -165,14 +165,14 @@ class StyleNet(nn.Module):
|
|
| 165 |
else nn.Linear(input_dim, hidden_dim)
|
| 166 |
)
|
| 167 |
|
| 168 |
-
self.
|
| 169 |
-
|
| 170 |
dim=hidden_dim,
|
| 171 |
-
num_heads=config.
|
| 172 |
-
eps=config.
|
| 173 |
-
swiglu_multiple=config.
|
| 174 |
)
|
| 175 |
-
for _ in range(config.
|
| 176 |
])
|
| 177 |
|
| 178 |
self.attn_pool = AttentionPooling(
|
|
@@ -182,12 +182,12 @@ class StyleNet(nn.Module):
|
|
| 182 |
self.head = nn.Sequential(
|
| 183 |
nn.Linear(hidden_dim, hidden_dim),
|
| 184 |
nn.SiLU(),
|
| 185 |
-
nn.Linear(hidden_dim, config.
|
| 186 |
)
|
| 187 |
|
| 188 |
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 189 |
x = self.input_proj(x)
|
| 190 |
-
for layer in self.
|
| 191 |
x = layer(x)
|
| 192 |
x = self.attn_pool(x)
|
| 193 |
x = self.head(x)
|
|
|
|
| 5 |
|
| 6 |
EgaraNet is a composite model:
|
| 7 |
backbone : DINOv3 ViT (frozen feature extractor)
|
| 8 |
+
style_net : StyleNet (Transposed Attention Transformer head)
|
| 9 |
|
| 10 |
Usage:
|
| 11 |
from modeling_egara_net import EgaraNetModel
|
|
|
|
| 81 |
return self.w_down(F.silu(self.w_gate(x)) * self.w_up(x))
|
| 82 |
|
| 83 |
|
| 84 |
+
class TransposedAttentionTransformer(nn.Module):
|
| 85 |
"""
|
| 86 |
+
TAT β Transposed Attention Transformer.
|
| 87 |
Cross-covariance attention in (HeadDim Γ HeadDim) space.
|
| 88 |
"""
|
| 89 |
|
|
|
|
| 151 |
|
| 152 |
class StyleNet(nn.Module):
|
| 153 |
"""
|
| 154 |
+
StyleNet head: TAT layers β AttentionPooling β Projection β L2 norm.
|
| 155 |
"""
|
| 156 |
|
| 157 |
def __init__(self, config: EgaraNetConfig):
|
| 158 |
super().__init__()
|
| 159 |
+
input_dim = config.effective_tat_input_dim
|
| 160 |
+
hidden_dim = config.tat_hidden_dim
|
| 161 |
|
| 162 |
self.input_proj = (
|
| 163 |
nn.Identity()
|
|
|
|
| 165 |
else nn.Linear(input_dim, hidden_dim)
|
| 166 |
)
|
| 167 |
|
| 168 |
+
self.tat_layers = nn.ModuleList([
|
| 169 |
+
TransposedAttentionTransformer(
|
| 170 |
dim=hidden_dim,
|
| 171 |
+
num_heads=config.tat_num_heads,
|
| 172 |
+
eps=config.tat_rms_norm_eps,
|
| 173 |
+
swiglu_multiple=config.tat_swiglu_multiple,
|
| 174 |
)
|
| 175 |
+
for _ in range(config.tat_num_layers)
|
| 176 |
])
|
| 177 |
|
| 178 |
self.attn_pool = AttentionPooling(
|
|
|
|
| 182 |
self.head = nn.Sequential(
|
| 183 |
nn.Linear(hidden_dim, hidden_dim),
|
| 184 |
nn.SiLU(),
|
| 185 |
+
nn.Linear(hidden_dim, config.tat_output_dim),
|
| 186 |
)
|
| 187 |
|
| 188 |
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 189 |
x = self.input_proj(x)
|
| 190 |
+
for layer in self.tat_layers:
|
| 191 |
x = layer(x)
|
| 192 |
x = self.attn_pool(x)
|
| 193 |
x = self.head(x)
|
onnx/egara_net_fp16.onnx
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5a030df2d519143d655bf5e78ead47ad31317a37e5822fe6538883c961b3299a
|
| 3 |
+
size 699502106
|
onnx/egara_net_fp32.onnx
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:46ebe59d3dd13f9a0d5e73a0b847e816e1b1c476fff1a04b1acb34892dc3012b
|
| 3 |
+
size 1394095358
|
onnx/egara_net_int8.onnx
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:cbe9745cf78a8ed2833dda5e02d2cd3932041a6033d413e1c5d2e5b18279c9c7
|
| 3 |
+
size 362131297
|