FabianGroeger's picture
SkinMap: 12-teacher ensemble + predict_meta (validated release)
4fc0ad6
Raw
History Blame Contribute Delete
2.37 kB
import torch.nn as nn
from ...models.dino.head import DINOHead
class iBOTHead(DINOHead):
def __init__(
self,
*args,
patch_out_dim=8192,
n_layers=3,
hidden_dim=2048,
bottleneck_dim=256,
norm_last_layer=True,
shared_head=False,
**kwargs
):
super(iBOTHead, self).__init__(
*args,
n_layers=n_layers,
hidden_dim=hidden_dim,
bottleneck_dim=bottleneck_dim,
norm_last_layer=norm_last_layer,
**kwargs
)
if not shared_head:
if bottleneck_dim > 0:
self.last_layer2 = nn.utils.weight_norm(
nn.Linear(bottleneck_dim, patch_out_dim, bias=False)
)
self.last_layer2.weight_g.data.fill_(1)
if norm_last_layer:
self.last_layer2.weight_g.requires_grad = False
else:
self.mlp2 = nn.Linear(hidden_dim, patch_out_dim)
self.last_layer2 = None
else:
if bottleneck_dim > 0:
self.last_layer2 = self.last_layer
else:
self.mlp2 = self.mlp[-1]
self.last_layer2 = None
def forward(self, x):
if len(x.shape) == 2:
return super(iBOTHead, self).forward(x)
if self.last_layer is not None:
x = self.mlp(x)
x = nn.functional.normalize(x, dim=-1, p=2)
x1 = self.last_layer(x[:, 0])
x2 = self.last_layer2(x[:, 1:])
else:
x = self.mlp[:-1](x)
x1 = self.mlp[-1](x[:, 0])
x2 = self.mlp2(x[:, 1:])
return x1, x2
def _build_norm(self, norm, hidden_dim, **kwargs):
if norm == "bn":
norm = nn.BatchNorm1d(hidden_dim, **kwargs)
elif norm == "syncbn":
norm = nn.SyncBatchNorm(hidden_dim, **kwargs)
elif norm == "ln":
norm = nn.LayerNorm(hidden_dim, **kwargs)
else:
assert norm is None, "unknown norm type {}".format(norm)
return norm
def _build_act(self, act):
if act == "relu":
act = nn.ReLU()
elif act == "gelu":
act = nn.GELU()
else:
assert False, "unknown act type {}".format(act)
return act