Download cure/backbone.py from mannicui0/CuRe: direct link, hf CLI and curl.
- Browser
- Download file 4.76 kB
-
https://huggingface.co/mannicui0/CuRe/resolve/main/cure/backbone.py
- Command line
-
hf download hf://mannicui0/CuRe/cure/backbone.py
-
curl -L -o backbone.py https://huggingface.co/mannicui0/CuRe/resolve/main/cure/backbone.py
4.76 kB
| # Copyright (c) Meta Platforms, Inc. and affiliates. | |
| # Adapted for fixed-resolution CuRe inference. See LICENSE and NOTICE. | |
| """PE Core L/14 patch features with Q/V LoRA at 336 x 336 resolution.""" | |
| from collections import OrderedDict | |
| import torch | |
| from torch import nn | |
| from torch.nn import functional as F | |
| class Rotary2D(nn.Module): | |
| def __init__(self): | |
| super().__init__() | |
| frequencies = 1.0 / (10000 ** (torch.arange(0, 32, 2).float() / 32)) | |
| positions = torch.arange(24).to(frequencies.dtype) + 1 | |
| axis = torch.einsum("..., f -> ... f", positions, frequencies) | |
| axis = axis.repeat_interleave(2, dim=-1) | |
| vertical = axis[:, None].expand(24, 24, -1) | |
| horizontal = axis[None, :].expand(24, 24, -1) | |
| angles = torch.cat([horizontal, vertical], dim=-1).reshape(576, 64) | |
| angles = torch.cat([torch.zeros(1, 64), angles], dim=0) | |
| self.register_buffer("angles", angles[None, None], persistent=False) | |
| def forward(self, values): | |
| first, second = values.reshape(*values.shape[:-1], -1, 2).unbind(-1) | |
| rotated = torch.stack([-second, first], dim=-1).flatten(-2) | |
| result = values * self.angles.cos() + rotated * self.angles.sin() | |
| return result.contiguous().to(values.dtype) | |
| class Attention(nn.Module): | |
| def __init__(self, rope): | |
| super().__init__() | |
| self.in_proj_weight = nn.Parameter(torch.empty(3072, 1024)) | |
| self.in_proj_bias = nn.Parameter(torch.empty(3072)) | |
| self.out_proj = nn.Linear(1024, 1024) | |
| self.lora_A_q = nn.Parameter(torch.empty(64, 1024)) | |
| self.lora_B_q = nn.Parameter(torch.empty(1024, 64)) | |
| self.lora_A_v = nn.Parameter(torch.empty(64, 1024)) | |
| self.lora_B_v = nn.Parameter(torch.empty(1024, 64)) | |
| self.rope = rope | |
| def forward(self, x): | |
| batch, sequence, width = x.shape | |
| projection = F.linear(x, self.in_proj_weight, self.in_proj_bias) | |
| projection = ( | |
| projection.unflatten(-1, (3, width)) | |
| .unsqueeze(0).transpose(0, -2).squeeze(-2).contiguous() | |
| ) | |
| query, key, value = projection[0], projection[1], projection[2] | |
| query = query + 2.0 * F.linear(F.linear(x, self.lora_A_q), self.lora_B_q) | |
| value = value + 2.0 * F.linear(F.linear(x, self.lora_A_v), self.lora_B_v) | |
| query = query.reshape(batch, sequence, 16, 64).transpose(1, 2) | |
| key = key.reshape(batch, sequence, 16, 64).transpose(1, 2) | |
| value = value.reshape(batch, sequence, 16, 64).transpose(1, 2) | |
| query, key = self.rope(query), self.rope(key) | |
| attended = F.scaled_dot_product_attention( | |
| query, key, value, attn_mask=None, dropout_p=0.0, | |
| is_causal=False, scale=64 ** -0.5, | |
| ) | |
| attended = attended.transpose(1, 2).reshape(batch, sequence, width) | |
| return F.linear(attended, self.out_proj.weight, self.out_proj.bias) | |
| class ResidualBlock(nn.Module): | |
| def __init__(self, rope): | |
| super().__init__() | |
| self.attn = Attention(rope) | |
| self.ln_1 = nn.LayerNorm(1024, eps=1e-5) | |
| self.ln_2 = nn.LayerNorm(1024, eps=1e-5) | |
| self.mlp = nn.Sequential(OrderedDict([ | |
| ("c_fc", nn.Linear(1024, 4096)), | |
| ("gelu", nn.GELU()), | |
| ("c_proj", nn.Linear(4096, 1024)), | |
| ])) | |
| def forward(self, x): | |
| x = x + self.attn(self.ln_1(x)) | |
| return x + self.mlp(self.ln_2(x)) | |
| class Transformer(nn.Module): | |
| def __init__(self, rope): | |
| super().__init__() | |
| self.resblocks = nn.ModuleList([ResidualBlock(rope) for _ in range(24)]) | |
| def forward(self, x): | |
| for block in self.resblocks: | |
| x = block(x) | |
| return x | |
| class PECore(nn.Module): | |
| def __init__(self): | |
| super().__init__() | |
| self.conv1 = nn.Conv2d(3, 1024, kernel_size=14, stride=14, bias=False) | |
| self.class_embedding = nn.Parameter(torch.empty(1024)) | |
| self.positional_embedding = nn.Parameter(torch.empty(577, 1024)) | |
| self.ln_pre = nn.LayerNorm(1024, eps=1e-5) | |
| self.ln_post = nn.LayerNorm(1024, eps=1e-5) | |
| self.transformer = Transformer(Rotary2D()) | |
| def forward(self, images): | |
| if images.ndim != 4 or tuple(images.shape[1:]) != (3, 336, 336): | |
| raise ValueError("Expected image tensors with shape [N, 3, 336, 336]") | |
| batch = images.shape[0] | |
| x = self.conv1(images).permute(0, 2, 3, 1).reshape(batch, 576, 1024) | |
| cls = self.class_embedding.view(1, 1, -1).expand(batch, -1, -1) | |
| x = torch.cat([cls, x], dim=1) | |
| x = x + self.positional_embedding[None] | |
| x = self.transformer(self.ln_pre(x)) | |
| return self.ln_post(x)[:, 1:].mean(dim=1).float() | |