Deploy_ConvNext / convnext_mlp.py
Sirius16's picture
Upload 28 files
4dc60af verified
Raw
History Blame Contribute Delete
4.48 kB
import torch
import torch.nn as nn
from torchvision.models import convnext_tiny, ConvNeXt_Tiny_Weights
class ConvNeXtFeatureExtractor(nn.Module):
def __init__(
self,
freeze_backbone: bool = True,
unfreeze_last_stage: bool = False,
):
super().__init__()
weights = ConvNeXt_Tiny_Weights.DEFAULT
self.backbone = convnext_tiny(weights=weights)
if freeze_backbone:
for p in self.backbone.parameters():
p.requires_grad = False
if unfreeze_last_stage:
for p in self.backbone.features[-1].parameters():
p.requires_grad = True
self.output_dim = self.backbone.classifier[2].in_features
self.backbone.classifier = nn.Identity()
def forward(self, x):
x = self.backbone(x)
x = x.view(x.size(0), -1)
return x
class MLPHead(nn.Module):
def __init__(
self,
input_dim: int,
num_classes: int,
head_depth: int = 2,
hidden_dim_1: int = 512,
hidden_dim_2: int = 256,
dropout: float = 0.1,
head_style: str = "standard",
):
super().__init__()
if head_style == "rakyan":
if head_depth == 2:
self.net = nn.Sequential(
nn.Linear(input_dim, hidden_dim_1),
nn.BatchNorm1d(hidden_dim_1),
nn.ReLU(inplace=True),
nn.Dropout(p=0.3),
nn.Linear(hidden_dim_1, num_classes),
)
elif head_depth == 3:
self.net = nn.Sequential(
nn.Linear(input_dim, hidden_dim_1),
nn.BatchNorm1d(hidden_dim_1),
nn.ReLU(inplace=True),
nn.Dropout(p=0.3),
nn.Linear(hidden_dim_1, hidden_dim_2),
nn.BatchNorm1d(hidden_dim_2),
nn.ReLU(inplace=True),
nn.Dropout(p=0.3),
nn.Linear(hidden_dim_2, num_classes),
)
else:
raise ValueError("head_depth must be 2 or 3")
elif head_style == "standard":
if head_depth == 2:
self.net = nn.Sequential(
nn.LayerNorm(input_dim),
nn.Linear(input_dim, hidden_dim_1),
nn.LayerNorm(hidden_dim_1),
nn.GELU(),
nn.Dropout(dropout),
nn.Linear(hidden_dim_1, num_classes),
)
elif head_depth == 3:
self.net = nn.Sequential(
nn.LayerNorm(input_dim),
nn.Linear(input_dim, hidden_dim_1),
nn.LayerNorm(hidden_dim_1),
nn.GELU(),
nn.Dropout(dropout),
nn.Linear(hidden_dim_1, hidden_dim_2),
nn.LayerNorm(hidden_dim_2),
nn.GELU(),
nn.Dropout(dropout),
nn.Linear(hidden_dim_2, num_classes),
)
else:
raise ValueError("head_depth must be 2 or 3")
else:
raise ValueError("head_style must be 'standard' or 'rakyan'")
def forward(self, x):
return self.net(x)
class ConvNextMLP(nn.Module):
def __init__(
self,
num_classes: int = 10,
head_depth: int = 2,
hidden_dim_1: int = 512,
hidden_dim_2: int = 256,
dropout: float = 0.1,
freeze_backbone: bool = True,
unfreeze_last_stage: bool = False,
head_style: str = "standard"
):
super().__init__()
self.feature_extractor = ConvNeXtFeatureExtractor(
freeze_backbone=freeze_backbone,
unfreeze_last_stage=unfreeze_last_stage
)
self.head = MLPHead(
input_dim=self.feature_extractor.output_dim,
num_classes=num_classes,
head_depth=head_depth,
hidden_dim_1=hidden_dim_1,
hidden_dim_2=hidden_dim_2,
dropout=dropout,
head_style=head_style
)
def forward(self, x):
features = self.feature_extractor(x)
out = self.head(features)
return out