A03HCY commited on
Commit
245a427
·
verified ·
1 Parent(s): 6601752

Upload 4 files

Browse files
Files changed (4) hide show
  1. README.md +186 -0
  2. config.json +36 -0
  3. model.safetensors +3 -0
  4. preprocessor_config.json +31 -0
README.md ADDED
@@ -0,0 +1,186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: other
3
+ license_name: dinov3-license
4
+ license_link: https://ai.meta.com/resources/models-and-libraries/dinov3-license
5
+ base_model: facebook/dinov3-vitb16-pretrain-lvd1689m
6
+ pipeline_tag: image-feature-extraction
7
+ library_name: codon
8
+ tags:
9
+ - dino
10
+ - dinov3
11
+ - vision
12
+ - feature-extraction
13
+ - fp16
14
+ ---
15
+
16
+ # DINOv3 ViT-B/16 — converted weights (codon layout, float16)
17
+
18
+ This repository hosts the weights of
19
+ [`facebook/dinov3-vitb16-pretrain-lvd1689m`](https://huggingface.co/facebook/dinov3-vitb16-pretrain-lvd1689m)
20
+ converted for the `codon` implementation of DINOv3:
21
+
22
+ - **renamed** to the codon naming convention (`codon.impl.DINOv3ViT`),
23
+ - **cast to float16** (2× smaller than the original fp32 checkpoint),
24
+ - **numerically verified** against the original weights and against the
25
+ `transformers` reference implementation.
26
+
27
+ The model itself is unchanged: same architecture, same parameter values, same
28
+ numerics up to fp16 quantization.
29
+
30
+ ## Why this exists
31
+
32
+ The upstream checkpoints use the `transformers`/Meta naming layout
33
+ (`layer.{i}.attention.*`, `layer_scale{1,2}.lambda1`, `embeddings.*`) and ship in
34
+ fp32. `codon.impl.DINOv3ViT` uses its own convention (all linear layers are
35
+ `*_proj`, the block list is `blocks`, Layer Scale is `gamma{1,2}`, register tokens
36
+ are `storage_tokens`), so the weights need a one-time remap. This repository is
37
+ that remap, pre-applied and stored in fp16 so it can be loaded directly with a
38
+ single call.
39
+
40
+ ## Files
41
+
42
+ | File | Description |
43
+ | --- | --- |
44
+ | `model.safetensors` | 163.4 MB, 211 tensors, all `F16`, codon key layout |
45
+ | `config.json` | Architecture summary plus `"dtype": "float16"` and `"key_layout": "codon"` |
46
+ | `preprocessor_config.json` | Image preprocessing parameters, carried over from the original model |
47
+ | `README.md` | This file |
48
+
49
+ ## Key mapping
50
+
51
+ | Original (transformers / Meta) | codon |
52
+ | --- | --- |
53
+ | `embeddings.patch_embeddings.*` | `patch_embed.*` |
54
+ | `embeddings.cls_token` | `cls_token` |
55
+ | `embeddings.register_tokens` | `storage_tokens` |
56
+ | `layer.{i}.attention.q_proj.*` | `blocks.{i}.q_proj.*` |
57
+ | `layer.{i}.attention.k_proj.*` | `blocks.{i}.k_proj.*` |
58
+ | `layer.{i}.attention.v_proj.*` | `blocks.{i}.v_proj.*` |
59
+ | `layer.{i}.attention.o_proj.*` | `blocks.{i}.o_proj.*` |
60
+ | `layer.{i}.norm1.*` / `norm2.*` | `blocks.{i}.norm1.*` / `norm2.*` |
61
+ | `layer.{i}.mlp.up_proj.*` / `down_proj.*` | `blocks.{i}.up_proj.*` / `down_proj.*` |
62
+ | `layer.{i}.layer_scale1.lambda1` | `blocks.{i}.gamma1` |
63
+ | `layer.{i}.layer_scale2.lambda1` | `blocks.{i}.gamma2` |
64
+ | `norm.*` | `norm.*` |
65
+ | `rope_embeddings.inv_freq` | dropped (rebuilt dynamically from input shape) |
66
+
67
+ Two notes on the conversion:
68
+
69
+ - The `inv_freq` rotary table is **not** stored. In this implementation the 2D axial
70
+ RoPE frequencies are recomputed from `rope_theta` and the input resolution at
71
+ runtime (a non-persistent buffer), which is what lets the same weights run at any
72
+ image size.
73
+ - A zero-initialized `mask_token` is included as a placeholder. It is part of this
74
+ implementation's MAE architecture but is absent from the original checkpoint;
75
+ `load_pretrained(strict=True)` does not require it.
76
+
77
+ ## Model overview
78
+
79
+ | Property | Value |
80
+ | --- | --- |
81
+ | Architecture | DINOv3 ViT (pre-norm Transformer, bidirectional attention, 2D axial RoPE) |
82
+ | Parameters | 85.7 M |
83
+ | Hidden size | 768 |
84
+ | Layers / attention heads | 12 / 12 |
85
+ | MLP hidden size | 3072 (ratio 4, GELU) |
86
+ | Patch size / default resolution | 16 / 224×224 |
87
+ | Register tokens | 4 |
88
+ | RoPE theta | 100.0 |
89
+ | Layer-norm eps | 1e-5 |
90
+ | Layer Scale init | 1.0 |
91
+ | Attention biases | q/v/o yes, k no |
92
+ | Drop path | 0.0 (inference) |
93
+ | Weight dtype | float16 |
94
+
95
+ ## Usage
96
+
97
+ ```python
98
+ import torch
99
+ from codon.impl import DINOv3ViT_Base
100
+
101
+ # Pulls config.json + model.safetensors from this repository.
102
+ # config.json says dtype=float16, so the model is built in float16.
103
+ model = DINOv3ViT_Base.from_remote().eval()
104
+
105
+ # Prefer fp32 compute? The weights are upcast on load.
106
+ model32 = DINOv3ViT_Base.from_remote(dtype=torch.float32).eval()
107
+ ```
108
+
109
+ `from_remote()` reads the architecture from `config.json` — `num_register_tokens`,
110
+ `rope_theta`, `pos_embed_rescale`, `layer_norm_eps`, `key_bias` and `dtype` are all
111
+ applied automatically, so no manual configuration is needed.
112
+
113
+ To load the file yourself:
114
+
115
+ ```python
116
+ model = DINOv3ViT_Base().half()
117
+ model.load_pretrained('model.safetensors', strict=True, dtype=torch.float16)
118
+ ```
119
+
120
+ ### Feature extraction
121
+
122
+ ```python
123
+ x = torch.randn(1, 3, 224, 224).half()
124
+
125
+ with torch.no_grad():
126
+ feats = model.forward_features(x)
127
+
128
+ feats['x_norm_clstoken'] # [1, 768] CLS token, post-norm
129
+ feats['x_storage_tokens'] # [1, 4, 768] 4 register tokens, post-norm
130
+ feats['x_norm_patchtokens'] # [1, 196, 768] 14x14 patch tokens, post-norm
131
+ feats['x_norm_alltokens'] # [1, 201, 768] full post-norm sequence
132
+ feats['x_prenorm'] # [1, 201, 768] full pre-norm sequence
133
+ ```
134
+
135
+ `forward(x)` (the default, `is_training=False`) returns just the CLS token of shape
136
+ `[N, 768]`.
137
+
138
+ Dense features at arbitrary resolutions work without interpolation, because the RoPE
139
+ frequencies are derived from the actual patch grid:
140
+
141
+ ```python
142
+ model.forward_features(torch.randn(1, 3, 256, 192).half())['x_norm_patchtokens'].shape
143
+ # torch.Size([1, 192, 768]) -> 16x12 patch grid
144
+ ```
145
+
146
+ Intermediate layers, optionally reshaped to feature maps:
147
+
148
+ ```python
149
+ with torch.no_grad():
150
+ layers = model.get_intermediate_layers(x, n=[0, 5, 11]) # tuple of [N, HW, C]
151
+ maps = model.get_intermediate_layers(x, n=1, reshape=True) # [N, C, 14, 14]
152
+ ```
153
+
154
+ ## Verification
155
+
156
+ The conversion was checked at every step, and these checks are reproducible via
157
+ `test/test_dinov3_vit.py` in the codon repository:
158
+
159
+ | Check | Result |
160
+ | --- | --- |
161
+ | Key remap + `strict=True` load from `model.safetensors` | passes |
162
+ | fp32 remapped weights vs `transformers` `DINOv3ViTModel`, 224×224 and 196×252 | `max|diff| = 0.000e+00` (bit-exact) |
163
+ | Per-block outputs vs `transformers` `output_hidden_states` (layers 0, 5, 11) | `max|diff| < 1e-5` |
164
+ | fp16 forward vs original fp32 model (CLS token) | `max|diff| = 6.9e-03` |
165
+ | fp16 weight quantization error (per tensor) | `≤ 2.0e-03` |
166
+ | Save → reload round trip | `max|diff| = 0.000e+00` |
167
+
168
+ The fp16 error is well within the expected range for a 12-layer model: activations
169
+ reach an order of magnitude of ~10-30, and fp16 carries roughly three significant
170
+ decimal digits.
171
+ ## Precision notes
172
+
173
+ - Inference in float16 works on CPU and CUDA. The rotary `cos`/`sin` tables are
174
+ computed in fp32 and then **cast to the activation dtype**, so attention inputs
175
+ stay in float16 throughout instead of being silently promoted to fp32.
176
+ - If you need maximum fidelity, use `dtype=torch.float32`; the weights are exact
177
+ float16 representations of the original fp32 values, so this only recovers the
178
+ rounding that happened at export time.
179
+
180
+ ## License
181
+
182
+ The weights are derived from Meta's DINOv3 and remain subject to the
183
+ [DINOv3 License](https://ai.meta.com/resources/models-and-libraries/dinov3-license).
184
+ Please read and comply with that license before use. In particular, the license
185
+ governs acceptable use, redistribution and attribution; this conversion adds no
186
+ additional permissions and no warranty.
config.json ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "DINOv3ViT"
4
+ ],
5
+ "model_type": "dinov3_vit",
6
+ "library_name": "codon",
7
+ "key_layout": "codon",
8
+ "converted_from": "facebook/dinov3-vitb16-pretrain-lvd1689m",
9
+ "dinov3_repo": "CodonProject/DINOv3-ViT-Base",
10
+ "dtype": "float16",
11
+ "torch_dtype": "float16",
12
+ "hidden_size": 768,
13
+ "intermediate_size": 3072,
14
+ "num_hidden_layers": 12,
15
+ "num_attention_heads": 12,
16
+ "num_channels": 3,
17
+ "patch_size": 16,
18
+ "image_size": 224,
19
+ "num_register_tokens": 4,
20
+ "hidden_act": "gelu",
21
+ "layer_norm_eps": 1e-05,
22
+ "layerscale_value": 1.0,
23
+ "query_bias": true,
24
+ "key_bias": false,
25
+ "value_bias": true,
26
+ "proj_bias": true,
27
+ "mlp_bias": true,
28
+ "use_gated_mlp": false,
29
+ "rope_theta": 100.0,
30
+ "pos_embed_shift": null,
31
+ "pos_embed_jitter": null,
32
+ "pos_embed_rescale": 2.0,
33
+ "drop_path_rate": 0.0,
34
+ "attention_dropout": 0.0,
35
+ "initializer_range": 0.02
36
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a8b1c229664c031632392b7890bea9d10c13fb8c972dc24710c1a8fa8e374b11
3
+ size 171340048
preprocessor_config.json ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "crop_size": null,
3
+ "data_format": "channels_first",
4
+ "default_to_square": true,
5
+ "device": null,
6
+ "disable_grouping": null,
7
+ "do_center_crop": null,
8
+ "do_convert_rgb": null,
9
+ "do_normalize": true,
10
+ "do_rescale": true,
11
+ "do_resize": true,
12
+ "image_mean": [
13
+ 0.485,
14
+ 0.456,
15
+ 0.406
16
+ ],
17
+ "image_processor_type": "DINOv3ViTImageProcessorFast",
18
+ "image_std": [
19
+ 0.229,
20
+ 0.224,
21
+ 0.225
22
+ ],
23
+ "input_data_format": null,
24
+ "resample": 2,
25
+ "rescale_factor": 0.00392156862745098,
26
+ "return_tensors": null,
27
+ "size": {
28
+ "height": 224,
29
+ "width": 224
30
+ }
31
+ }