metnet-3 / model /metnet3_blocks.py
yzt15806542928's picture
Upload folder using huggingface_hub
38f9214 verified
Raw
History Blame Contribute Delete
1.68 kB
"""Small self-contained blocks approximating the paper's spatial backbone."""
import torch
from torch import nn
class FiLM(nn.Module):
def __init__(self, channels: int, condition_dim: int):
super().__init__()
self.proj = nn.Linear(condition_dim, channels * 2)
def forward(self, x: torch.Tensor, condition: torch.Tensor) -> torch.Tensor:
scale, shift = self.proj(condition).chunk(2, dim=-1)
return x * (1 + scale[..., None, None]) + shift[..., None, None]
class ConvBlock(nn.Module):
def __init__(self, in_channels: int, out_channels: int, condition_dim: int):
super().__init__()
self.net = nn.Sequential(
nn.Conv2d(in_channels, out_channels, 3, padding=1), nn.GroupNorm(4, out_channels), nn.GELU(),
nn.Conv2d(out_channels, out_channels, 3, padding=1), nn.GroupNorm(4, out_channels), nn.GELU(),
)
self.film = FiLM(out_channels, condition_dim)
def forward(self, x: torch.Tensor, condition: torch.Tensor) -> torch.Tensor:
return self.film(self.net(x), condition)
class LongRangeMaxViT(nn.Module):
"""Compact global token mixer; PAPER_GAP: not the unpublished full MaxViT graph."""
def __init__(self, channels: int, heads: int = 4, blocks: int = 1):
super().__init__()
layer = nn.TransformerEncoderLayer(channels, heads, channels * 2, batch_first=True, norm_first=True)
self.encoder = nn.TransformerEncoder(layer, blocks)
def forward(self, x: torch.Tensor) -> torch.Tensor:
b, c, h, w = x.shape
tokens = x.flatten(2).transpose(1, 2)
return self.encoder(tokens).transpose(1, 2).reshape(b, c, h, w)