ffgs 0.1.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ffgs/__init__.py +39 -0
- ffgs/dynamic.py +239 -0
- ffgs/geometry.py +418 -0
- ffgs/image.py +204 -0
- ffgs/models/__init__.py +2 -0
- ffgs/models/anysplat/LICENSE +1120 -0
- ffgs/models/anysplat/__init__.py +49 -0
- ffgs/models/anysplat/encoder.py +372 -0
- ffgs/models/anysplat/evaluation.py +98 -0
- ffgs/models/anysplat/gaussian_adapter.py +96 -0
- ffgs/models/anysplat/gs_head.py +166 -0
- ffgs/models/anysplat/modeling.py +95 -0
- ffgs/models/anysplat/processing.py +249 -0
- ffgs/models/anysplat/vggt/__init__.py +0 -0
- ffgs/models/anysplat/vggt/heads/__init__.py +0 -0
- ffgs/models/anysplat/vggt/heads/camera_head.py +181 -0
- ffgs/models/anysplat/vggt/heads/dpt_head.py +612 -0
- ffgs/models/anysplat/vggt/heads/head_act.py +134 -0
- ffgs/models/anysplat/vggt/heads/utils.py +126 -0
- ffgs/models/anysplat/vggt/layers/__init__.py +28 -0
- ffgs/models/anysplat/vggt/layers/attention.py +92 -0
- ffgs/models/anysplat/vggt/layers/block.py +157 -0
- ffgs/models/anysplat/vggt/layers/drop_path.py +42 -0
- ffgs/models/anysplat/vggt/layers/layer_scale.py +32 -0
- ffgs/models/anysplat/vggt/layers/mlp.py +45 -0
- ffgs/models/anysplat/vggt/layers/patch_embed.py +106 -0
- ffgs/models/anysplat/vggt/layers/rope.py +211 -0
- ffgs/models/anysplat/vggt/layers/swiglu_ffn.py +77 -0
- ffgs/models/anysplat/vggt/layers/vision_transformer.py +463 -0
- ffgs/models/anysplat/vggt/models/__init__.py +0 -0
- ffgs/models/anysplat/vggt/models/aggregator.py +398 -0
- ffgs/models/anysplat/vggt/utils/__init__.py +0 -0
- ffgs/models/anysplat/vggt/utils/geometry.py +230 -0
- ffgs/models/anysplat/vggt/utils/pose_enc.py +144 -0
- ffgs/models/anysplat/vggt/utils/rotation.py +148 -0
- ffgs/models/tokengs/__init__.py +43 -0
- ffgs/models/tokengs/activations.py +135 -0
- ffgs/models/tokengs/attention.py +189 -0
- ffgs/models/tokengs/enc_dec.py +323 -0
- ffgs/models/tokengs/modeling.py +173 -0
- ffgs/models/tokengs/processing.py +339 -0
- ffgs/pipeline.py +341 -0
- ffgs/processor.py +236 -0
- ffgs/registry.py +132 -0
- ffgs/render.py +111 -0
- ffgs/types.py +291 -0
- ffgs/zoo/__init__.py +234 -0
- ffgs/zoo/anysplat/default.json +34 -0
- ffgs/zoo/tokengs/dl3dv-2v.json +29 -0
- ffgs/zoo/tokengs/dl3dv-4v.json +29 -0
- ffgs/zoo/tokengs/dl3dv-6v.json +29 -0
- ffgs/zoo/tokengs/dl3dv-base.json +29 -0
- ffgs/zoo/tokengs/dl3dv-latent-2v-lpips.json +48 -0
- ffgs/zoo/tokengs/dl3dv-latent-2v-ssim.json +48 -0
- ffgs/zoo/tokengs/dl3dv-latent-4v-lpips.json +48 -0
- ffgs/zoo/tokengs/dl3dv-latent-4v-ssim.json +48 -0
- ffgs/zoo/tokengs/dl3dv-latent-6v-lpips.json +48 -0
- ffgs/zoo/tokengs/dl3dv-latent-6v-ssim.json +48 -0
- ffgs-0.1.0.dev0.dist-info/METADATA +320 -0
- ffgs-0.1.0.dev0.dist-info/RECORD +63 -0
- ffgs-0.1.0.dev0.dist-info/WHEEL +4 -0
- ffgs-0.1.0.dev0.dist-info/licenses/LICENSE +237 -0
- ffgs-0.1.0.dev0.dist-info/licenses/src/ffgs/models/anysplat/LICENSE +1120 -0
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
#
|
|
3
|
+
# This source code is licensed under the Apache License, Version 2.0
|
|
4
|
+
# found in the LICENSE file in the root directory of this source tree.
|
|
5
|
+
#
|
|
6
|
+
# Modified by the libgs contributors, 2026, from
|
|
7
|
+
# src/model/encoder/vggt/layers/vision_transformer.py of
|
|
8
|
+
# https://github.com/InternRobotics/AnySplat (5f5e208): formatted with black, unused
|
|
9
|
+
# imports removed.
|
|
10
|
+
# Apache License 2.0: see the Apache-2.0 text in LICENSE (this directory).
|
|
11
|
+
|
|
12
|
+
# References:
|
|
13
|
+
# https://github.com/facebookresearch/dino/blob/main/vision_transformer.py
|
|
14
|
+
# https://github.com/rwightman/pytorch-image-models/tree/master/timm/models/vision_transformer.py
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
import math
|
|
18
|
+
from functools import partial
|
|
19
|
+
from typing import Callable, Sequence, Tuple, Union
|
|
20
|
+
|
|
21
|
+
import torch
|
|
22
|
+
import torch.nn as nn
|
|
23
|
+
from torch.nn.init import trunc_normal_
|
|
24
|
+
from torch.utils.checkpoint import checkpoint
|
|
25
|
+
|
|
26
|
+
from . import (
|
|
27
|
+
MemEffAttention,
|
|
28
|
+
Mlp,
|
|
29
|
+
PatchEmbed,
|
|
30
|
+
SwiGLUFFNFused,
|
|
31
|
+
)
|
|
32
|
+
from . import (
|
|
33
|
+
NestedTensorBlock as Block,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
logger = logging.getLogger("dinov2")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def named_apply(
|
|
40
|
+
fn: Callable, module: nn.Module, name="", depth_first=True, include_root=False
|
|
41
|
+
) -> nn.Module:
|
|
42
|
+
if not depth_first and include_root:
|
|
43
|
+
fn(module=module, name=name)
|
|
44
|
+
for child_name, child_module in module.named_children():
|
|
45
|
+
child_name = ".".join((name, child_name)) if name else child_name
|
|
46
|
+
named_apply(
|
|
47
|
+
fn=fn,
|
|
48
|
+
module=child_module,
|
|
49
|
+
name=child_name,
|
|
50
|
+
depth_first=depth_first,
|
|
51
|
+
include_root=True,
|
|
52
|
+
)
|
|
53
|
+
if depth_first and include_root:
|
|
54
|
+
fn(module=module, name=name)
|
|
55
|
+
return module
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class BlockChunk(nn.ModuleList):
|
|
59
|
+
def forward(self, x):
|
|
60
|
+
for b in self:
|
|
61
|
+
x = b(x)
|
|
62
|
+
return x
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class DinoVisionTransformer(nn.Module):
|
|
66
|
+
def __init__(
|
|
67
|
+
self,
|
|
68
|
+
img_size=224,
|
|
69
|
+
patch_size=16,
|
|
70
|
+
in_chans=3,
|
|
71
|
+
embed_dim=768,
|
|
72
|
+
depth=12,
|
|
73
|
+
num_heads=12,
|
|
74
|
+
mlp_ratio=4.0,
|
|
75
|
+
qkv_bias=True,
|
|
76
|
+
ffn_bias=True,
|
|
77
|
+
proj_bias=True,
|
|
78
|
+
drop_path_rate=0.0,
|
|
79
|
+
drop_path_uniform=False,
|
|
80
|
+
init_values=None, # for layerscale: None or 0 => no layerscale
|
|
81
|
+
embed_layer=PatchEmbed,
|
|
82
|
+
act_layer=nn.GELU,
|
|
83
|
+
block_fn=Block,
|
|
84
|
+
ffn_layer="mlp",
|
|
85
|
+
block_chunks=1,
|
|
86
|
+
num_register_tokens=0,
|
|
87
|
+
interpolate_antialias=False,
|
|
88
|
+
interpolate_offset=0.1,
|
|
89
|
+
qk_norm=False,
|
|
90
|
+
):
|
|
91
|
+
"""
|
|
92
|
+
Args:
|
|
93
|
+
img_size (int, tuple): input image size
|
|
94
|
+
patch_size (int, tuple): patch size
|
|
95
|
+
in_chans (int): number of input channels
|
|
96
|
+
embed_dim (int): embedding dimension
|
|
97
|
+
depth (int): depth of transformer
|
|
98
|
+
num_heads (int): number of attention heads
|
|
99
|
+
mlp_ratio (int): ratio of mlp hidden dim to embedding dim
|
|
100
|
+
qkv_bias (bool): enable bias for qkv if True
|
|
101
|
+
proj_bias (bool): enable bias for proj in attn if True
|
|
102
|
+
ffn_bias (bool): enable bias for ffn if True
|
|
103
|
+
drop_path_rate (float): stochastic depth rate
|
|
104
|
+
drop_path_uniform (bool): apply uniform drop rate across blocks
|
|
105
|
+
weight_init (str): weight init scheme
|
|
106
|
+
init_values (float): layer-scale init values
|
|
107
|
+
embed_layer (nn.Module): patch embedding layer
|
|
108
|
+
act_layer (nn.Module): MLP activation layer
|
|
109
|
+
block_fn (nn.Module): transformer block class
|
|
110
|
+
ffn_layer (str): "mlp", "swiglu", "swiglufused" or "identity"
|
|
111
|
+
block_chunks: (int) split block sequence into block_chunks units for FSDP wrap
|
|
112
|
+
num_register_tokens: (int) number of extra cls tokens (so-called "registers")
|
|
113
|
+
interpolate_antialias: (str) flag to apply anti-aliasing when interpolating positional embeddings
|
|
114
|
+
interpolate_offset: (float) work-around offset to apply when interpolating positional embeddings
|
|
115
|
+
"""
|
|
116
|
+
super().__init__()
|
|
117
|
+
norm_layer = partial(nn.LayerNorm, eps=1e-6)
|
|
118
|
+
|
|
119
|
+
# tricky but makes it work
|
|
120
|
+
self.use_checkpoint = True
|
|
121
|
+
self.use_reentrant = False
|
|
122
|
+
#
|
|
123
|
+
|
|
124
|
+
self.num_features = self.embed_dim = (
|
|
125
|
+
embed_dim # num_features for consistency with other models
|
|
126
|
+
)
|
|
127
|
+
self.num_tokens = 1
|
|
128
|
+
self.n_blocks = depth
|
|
129
|
+
self.num_heads = num_heads
|
|
130
|
+
self.patch_size = patch_size
|
|
131
|
+
self.num_register_tokens = num_register_tokens
|
|
132
|
+
self.interpolate_antialias = interpolate_antialias
|
|
133
|
+
self.interpolate_offset = interpolate_offset
|
|
134
|
+
|
|
135
|
+
self.patch_embed = embed_layer(
|
|
136
|
+
img_size=img_size,
|
|
137
|
+
patch_size=patch_size,
|
|
138
|
+
in_chans=in_chans,
|
|
139
|
+
embed_dim=embed_dim,
|
|
140
|
+
)
|
|
141
|
+
num_patches = self.patch_embed.num_patches
|
|
142
|
+
|
|
143
|
+
self.cls_token = nn.Parameter(torch.zeros(1, 1, embed_dim))
|
|
144
|
+
self.pos_embed = nn.Parameter(
|
|
145
|
+
torch.zeros(1, num_patches + self.num_tokens, embed_dim)
|
|
146
|
+
)
|
|
147
|
+
assert num_register_tokens >= 0
|
|
148
|
+
self.register_tokens = (
|
|
149
|
+
nn.Parameter(torch.zeros(1, num_register_tokens, embed_dim))
|
|
150
|
+
if num_register_tokens
|
|
151
|
+
else None
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
if drop_path_uniform is True:
|
|
155
|
+
dpr = [drop_path_rate] * depth
|
|
156
|
+
else:
|
|
157
|
+
dpr = [
|
|
158
|
+
x.item() for x in torch.linspace(0, drop_path_rate, depth)
|
|
159
|
+
] # stochastic depth decay rule
|
|
160
|
+
|
|
161
|
+
if ffn_layer == "mlp":
|
|
162
|
+
logger.info("using MLP layer as FFN")
|
|
163
|
+
ffn_layer = Mlp
|
|
164
|
+
elif ffn_layer == "swiglufused" or ffn_layer == "swiglu":
|
|
165
|
+
logger.info("using SwiGLU layer as FFN")
|
|
166
|
+
ffn_layer = SwiGLUFFNFused
|
|
167
|
+
elif ffn_layer == "identity":
|
|
168
|
+
logger.info("using Identity layer as FFN")
|
|
169
|
+
|
|
170
|
+
def f(*args, **kwargs):
|
|
171
|
+
return nn.Identity()
|
|
172
|
+
|
|
173
|
+
ffn_layer = f
|
|
174
|
+
else:
|
|
175
|
+
raise NotImplementedError
|
|
176
|
+
|
|
177
|
+
blocks_list = [
|
|
178
|
+
block_fn(
|
|
179
|
+
dim=embed_dim,
|
|
180
|
+
num_heads=num_heads,
|
|
181
|
+
mlp_ratio=mlp_ratio,
|
|
182
|
+
qkv_bias=qkv_bias,
|
|
183
|
+
proj_bias=proj_bias,
|
|
184
|
+
ffn_bias=ffn_bias,
|
|
185
|
+
drop_path=dpr[i],
|
|
186
|
+
norm_layer=norm_layer,
|
|
187
|
+
act_layer=act_layer,
|
|
188
|
+
ffn_layer=ffn_layer,
|
|
189
|
+
init_values=init_values,
|
|
190
|
+
qk_norm=qk_norm,
|
|
191
|
+
)
|
|
192
|
+
for i in range(depth)
|
|
193
|
+
]
|
|
194
|
+
if block_chunks > 0:
|
|
195
|
+
self.chunked_blocks = True
|
|
196
|
+
chunked_blocks = []
|
|
197
|
+
chunksize = depth // block_chunks
|
|
198
|
+
for i in range(0, depth, chunksize):
|
|
199
|
+
# this is to keep the block index consistent if we chunk the block list
|
|
200
|
+
chunked_blocks.append(
|
|
201
|
+
[nn.Identity()] * i + blocks_list[i : i + chunksize]
|
|
202
|
+
)
|
|
203
|
+
self.blocks = nn.ModuleList([BlockChunk(p) for p in chunked_blocks])
|
|
204
|
+
else:
|
|
205
|
+
self.chunked_blocks = False
|
|
206
|
+
self.blocks = nn.ModuleList(blocks_list)
|
|
207
|
+
|
|
208
|
+
self.norm = norm_layer(embed_dim)
|
|
209
|
+
self.head = nn.Identity()
|
|
210
|
+
|
|
211
|
+
self.mask_token = nn.Parameter(torch.zeros(1, embed_dim))
|
|
212
|
+
|
|
213
|
+
self.init_weights()
|
|
214
|
+
|
|
215
|
+
def init_weights(self):
|
|
216
|
+
trunc_normal_(self.pos_embed, std=0.02)
|
|
217
|
+
nn.init.normal_(self.cls_token, std=1e-6)
|
|
218
|
+
if self.register_tokens is not None:
|
|
219
|
+
nn.init.normal_(self.register_tokens, std=1e-6)
|
|
220
|
+
named_apply(init_weights_vit_timm, self)
|
|
221
|
+
|
|
222
|
+
def interpolate_pos_encoding(self, x, w, h):
|
|
223
|
+
previous_dtype = x.dtype
|
|
224
|
+
npatch = x.shape[1] - 1
|
|
225
|
+
N = self.pos_embed.shape[1] - 1
|
|
226
|
+
if npatch == N and w == h:
|
|
227
|
+
return self.pos_embed
|
|
228
|
+
pos_embed = self.pos_embed.float()
|
|
229
|
+
class_pos_embed = pos_embed[:, 0]
|
|
230
|
+
patch_pos_embed = pos_embed[:, 1:]
|
|
231
|
+
dim = x.shape[-1]
|
|
232
|
+
w0 = w // self.patch_size
|
|
233
|
+
h0 = h // self.patch_size
|
|
234
|
+
M = int(math.sqrt(N)) # Recover the number of patches in each dimension
|
|
235
|
+
assert N == M * M
|
|
236
|
+
kwargs = {}
|
|
237
|
+
if self.interpolate_offset:
|
|
238
|
+
# Historical kludge: add a small number to avoid floating point error in the interpolation, see https://github.com/facebookresearch/dino/issues/8
|
|
239
|
+
# Note: still needed for backward-compatibility, the underlying operators are using both output size and scale factors
|
|
240
|
+
sx = float(w0 + self.interpolate_offset) / M
|
|
241
|
+
sy = float(h0 + self.interpolate_offset) / M
|
|
242
|
+
kwargs["scale_factor"] = (sx, sy)
|
|
243
|
+
else:
|
|
244
|
+
# Simply specify an output size instead of a scale factor
|
|
245
|
+
kwargs["size"] = (w0, h0)
|
|
246
|
+
patch_pos_embed = nn.functional.interpolate(
|
|
247
|
+
patch_pos_embed.reshape(1, M, M, dim).permute(0, 3, 1, 2),
|
|
248
|
+
mode="bicubic",
|
|
249
|
+
antialias=self.interpolate_antialias,
|
|
250
|
+
**kwargs,
|
|
251
|
+
)
|
|
252
|
+
assert (w0, h0) == patch_pos_embed.shape[-2:]
|
|
253
|
+
patch_pos_embed = patch_pos_embed.permute(0, 2, 3, 1).view(1, -1, dim)
|
|
254
|
+
return torch.cat((class_pos_embed.unsqueeze(0), patch_pos_embed), dim=1).to(
|
|
255
|
+
previous_dtype
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
def prepare_tokens_with_masks(self, x, masks=None):
|
|
259
|
+
B, nc, w, h = x.shape
|
|
260
|
+
x = self.patch_embed(x)
|
|
261
|
+
if masks is not None:
|
|
262
|
+
x = torch.where(
|
|
263
|
+
masks.unsqueeze(-1), self.mask_token.to(x.dtype).unsqueeze(0), x
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
x = torch.cat((self.cls_token.expand(x.shape[0], -1, -1), x), dim=1)
|
|
267
|
+
x = x + self.interpolate_pos_encoding(x, w, h)
|
|
268
|
+
|
|
269
|
+
if self.register_tokens is not None:
|
|
270
|
+
x = torch.cat(
|
|
271
|
+
(
|
|
272
|
+
x[:, :1],
|
|
273
|
+
self.register_tokens.expand(x.shape[0], -1, -1),
|
|
274
|
+
x[:, 1:],
|
|
275
|
+
),
|
|
276
|
+
dim=1,
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
return x
|
|
280
|
+
|
|
281
|
+
def forward_features_list(self, x_list, masks_list):
|
|
282
|
+
x = [
|
|
283
|
+
self.prepare_tokens_with_masks(x, masks)
|
|
284
|
+
for x, masks in zip(x_list, masks_list)
|
|
285
|
+
]
|
|
286
|
+
|
|
287
|
+
for blk in self.blocks:
|
|
288
|
+
if self.use_checkpoint:
|
|
289
|
+
x = checkpoint(blk, x, use_reentrant=self.use_reentrant)
|
|
290
|
+
else:
|
|
291
|
+
x = blk(x)
|
|
292
|
+
|
|
293
|
+
all_x = x
|
|
294
|
+
output = []
|
|
295
|
+
for x, masks in zip(all_x, masks_list):
|
|
296
|
+
x_norm = self.norm(x)
|
|
297
|
+
output.append(
|
|
298
|
+
{
|
|
299
|
+
"x_norm_clstoken": x_norm[:, 0],
|
|
300
|
+
"x_norm_regtokens": x_norm[:, 1 : self.num_register_tokens + 1],
|
|
301
|
+
"x_norm_patchtokens": x_norm[:, self.num_register_tokens + 1 :],
|
|
302
|
+
"x_prenorm": x,
|
|
303
|
+
"masks": masks,
|
|
304
|
+
}
|
|
305
|
+
)
|
|
306
|
+
return output
|
|
307
|
+
|
|
308
|
+
def forward_features(self, x, masks=None):
|
|
309
|
+
if isinstance(x, list):
|
|
310
|
+
return self.forward_features_list(x, masks)
|
|
311
|
+
|
|
312
|
+
x = self.prepare_tokens_with_masks(x, masks)
|
|
313
|
+
|
|
314
|
+
for blk in self.blocks:
|
|
315
|
+
if self.use_checkpoint:
|
|
316
|
+
x = checkpoint(blk, x, use_reentrant=self.use_reentrant)
|
|
317
|
+
else:
|
|
318
|
+
x = blk(x)
|
|
319
|
+
|
|
320
|
+
x_norm = self.norm(x)
|
|
321
|
+
return {
|
|
322
|
+
"x_norm_clstoken": x_norm[:, 0],
|
|
323
|
+
"x_norm_regtokens": x_norm[:, 1 : self.num_register_tokens + 1],
|
|
324
|
+
"x_norm_patchtokens": x_norm[:, self.num_register_tokens + 1 :],
|
|
325
|
+
"x_prenorm": x,
|
|
326
|
+
"masks": masks,
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
def _get_intermediate_layers_not_chunked(self, x, n=1):
|
|
330
|
+
x = self.prepare_tokens_with_masks(x)
|
|
331
|
+
# If n is an int, take the n last blocks. If it's a list, take them
|
|
332
|
+
output, total_block_len = [], len(self.blocks)
|
|
333
|
+
blocks_to_take = (
|
|
334
|
+
range(total_block_len - n, total_block_len) if isinstance(n, int) else n
|
|
335
|
+
)
|
|
336
|
+
for i, blk in enumerate(self.blocks):
|
|
337
|
+
x = blk(x)
|
|
338
|
+
if i in blocks_to_take:
|
|
339
|
+
output.append(x)
|
|
340
|
+
assert len(output) == len(
|
|
341
|
+
blocks_to_take
|
|
342
|
+
), f"only {len(output)} / {len(blocks_to_take)} blocks found"
|
|
343
|
+
return output
|
|
344
|
+
|
|
345
|
+
def _get_intermediate_layers_chunked(self, x, n=1):
|
|
346
|
+
x = self.prepare_tokens_with_masks(x)
|
|
347
|
+
output, i, total_block_len = [], 0, len(self.blocks[-1])
|
|
348
|
+
# If n is an int, take the n last blocks. If it's a list, take them
|
|
349
|
+
blocks_to_take = (
|
|
350
|
+
range(total_block_len - n, total_block_len) if isinstance(n, int) else n
|
|
351
|
+
)
|
|
352
|
+
for block_chunk in self.blocks:
|
|
353
|
+
for blk in block_chunk[i:]: # Passing the nn.Identity()
|
|
354
|
+
x = blk(x)
|
|
355
|
+
if i in blocks_to_take:
|
|
356
|
+
output.append(x)
|
|
357
|
+
i += 1
|
|
358
|
+
assert len(output) == len(
|
|
359
|
+
blocks_to_take
|
|
360
|
+
), f"only {len(output)} / {len(blocks_to_take)} blocks found"
|
|
361
|
+
return output
|
|
362
|
+
|
|
363
|
+
def get_intermediate_layers(
|
|
364
|
+
self,
|
|
365
|
+
x: torch.Tensor,
|
|
366
|
+
n: Union[int, Sequence] = 1, # Layers or n last layers to take
|
|
367
|
+
reshape: bool = False,
|
|
368
|
+
return_class_token: bool = False,
|
|
369
|
+
norm=True,
|
|
370
|
+
) -> Tuple[Union[torch.Tensor, Tuple[torch.Tensor]]]:
|
|
371
|
+
if self.chunked_blocks:
|
|
372
|
+
outputs = self._get_intermediate_layers_chunked(x, n)
|
|
373
|
+
else:
|
|
374
|
+
outputs = self._get_intermediate_layers_not_chunked(x, n)
|
|
375
|
+
if norm:
|
|
376
|
+
outputs = [self.norm(out) for out in outputs]
|
|
377
|
+
class_tokens = [out[:, 0] for out in outputs]
|
|
378
|
+
outputs = [out[:, 1 + self.num_register_tokens :] for out in outputs]
|
|
379
|
+
if reshape:
|
|
380
|
+
B, _, w, h = x.shape
|
|
381
|
+
outputs = [
|
|
382
|
+
out.reshape(B, w // self.patch_size, h // self.patch_size, -1)
|
|
383
|
+
.permute(0, 3, 1, 2)
|
|
384
|
+
.contiguous()
|
|
385
|
+
for out in outputs
|
|
386
|
+
]
|
|
387
|
+
if return_class_token:
|
|
388
|
+
return tuple(zip(outputs, class_tokens))
|
|
389
|
+
return tuple(outputs)
|
|
390
|
+
|
|
391
|
+
def forward(self, *args, is_training=True, **kwargs):
|
|
392
|
+
ret = self.forward_features(*args, **kwargs)
|
|
393
|
+
if is_training:
|
|
394
|
+
return ret
|
|
395
|
+
else:
|
|
396
|
+
return self.head(ret["x_norm_clstoken"])
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def init_weights_vit_timm(module: nn.Module, name: str = ""):
|
|
400
|
+
"""ViT weight initialization, original timm impl (for reproducibility)"""
|
|
401
|
+
if isinstance(module, nn.Linear):
|
|
402
|
+
trunc_normal_(module.weight, std=0.02)
|
|
403
|
+
if module.bias is not None:
|
|
404
|
+
nn.init.zeros_(module.bias)
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def vit_small(patch_size=16, num_register_tokens=0, **kwargs):
|
|
408
|
+
model = DinoVisionTransformer(
|
|
409
|
+
patch_size=patch_size,
|
|
410
|
+
embed_dim=384,
|
|
411
|
+
depth=12,
|
|
412
|
+
num_heads=6,
|
|
413
|
+
mlp_ratio=4,
|
|
414
|
+
block_fn=partial(Block, attn_class=MemEffAttention),
|
|
415
|
+
num_register_tokens=num_register_tokens,
|
|
416
|
+
**kwargs,
|
|
417
|
+
)
|
|
418
|
+
return model
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
def vit_base(patch_size=16, num_register_tokens=0, **kwargs):
|
|
422
|
+
model = DinoVisionTransformer(
|
|
423
|
+
patch_size=patch_size,
|
|
424
|
+
embed_dim=768,
|
|
425
|
+
depth=12,
|
|
426
|
+
num_heads=12,
|
|
427
|
+
mlp_ratio=4,
|
|
428
|
+
block_fn=partial(Block, attn_class=MemEffAttention),
|
|
429
|
+
num_register_tokens=num_register_tokens,
|
|
430
|
+
**kwargs,
|
|
431
|
+
)
|
|
432
|
+
return model
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
def vit_large(patch_size=16, num_register_tokens=0, **kwargs):
|
|
436
|
+
model = DinoVisionTransformer(
|
|
437
|
+
patch_size=patch_size,
|
|
438
|
+
embed_dim=1024,
|
|
439
|
+
depth=24,
|
|
440
|
+
num_heads=16,
|
|
441
|
+
mlp_ratio=4,
|
|
442
|
+
block_fn=partial(Block, attn_class=MemEffAttention),
|
|
443
|
+
num_register_tokens=num_register_tokens,
|
|
444
|
+
**kwargs,
|
|
445
|
+
)
|
|
446
|
+
return model
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def vit_giant2(patch_size=16, num_register_tokens=0, **kwargs):
|
|
450
|
+
"""
|
|
451
|
+
Close to ViT-giant, with embed-dim 1536 and 24 heads => embed-dim per head 64
|
|
452
|
+
"""
|
|
453
|
+
model = DinoVisionTransformer(
|
|
454
|
+
patch_size=patch_size,
|
|
455
|
+
embed_dim=1536,
|
|
456
|
+
depth=40,
|
|
457
|
+
num_heads=24,
|
|
458
|
+
mlp_ratio=4,
|
|
459
|
+
block_fn=partial(Block, attn_class=MemEffAttention),
|
|
460
|
+
num_register_tokens=num_register_tokens,
|
|
461
|
+
**kwargs,
|
|
462
|
+
)
|
|
463
|
+
return model
|
|
File without changes
|