fer-inference / model.py
kshitizgajurel's picture
Deploy FER inference app
eec43fb
Raw
History Blame Contribute Delete
2.1 kB
from torch.autograd import Function
import torch.nn as nn
from transformers import ViTModel
class GradientReversalFn(Function):
@staticmethod
def forward(ctx, x, lambda_):
ctx.lambda_ = lambda_
return x.clone()
@staticmethod
def backward(ctx, grads):
return -ctx.lambda_ * grads, None
class GradientReversal(nn.Module):
def __init__(self, lambda_=1.0):
super().__init__()
self.lambda_ = lambda_
def forward(self, x):
return GradientReversalFn.apply(x, self.lambda_)
def set_lambda(self, v):
self.lambda_ = v
class FERModel(nn.Module):
def __init__(self, num_classes=7, num_domains=2, domain_lambda=0.1):
super().__init__()
self.backbone = ViTModel.from_pretrained(
'trpakov/vit-face-expression',
ignore_mismatched_sizes=True,
add_pooling_layer=False
)
D = 768 # ViT-base feature dim
self.emotion_head = nn.Sequential(
nn.LayerNorm(D),
nn.Linear(D, 512),
nn.GELU(),
nn.Dropout(0.4),
nn.Linear(512, 256),
nn.GELU(),
nn.Dropout(0.3),
nn.Linear(256, num_classes)
)
self.grl = GradientReversal(lambda_=domain_lambda)
self.domain_head = nn.Sequential(
nn.LayerNorm(D),
nn.Linear(D, 256),
nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(256, num_domains)
)
def forward(self, x):
out = self.backbone(pixel_values=x)
features = out.last_hidden_state[:, 0, :] # CLS token [B, 768]
return self.emotion_head(features), self.domain_head(self.grl(features))
# Config constants
BACKBONE = 'trpakov/vit-face-expression'
IMG_SIZE = 224
FEATURE_DIM = 768
NUM_CLASSES = 7
NUM_DOMAINS = 2
VIT_MEAN = [0.5, 0.5, 0.5]
VIT_STD = [0.5, 0.5, 0.5]
ID_TO_EMOTION = {
0: 'angry',
1: 'disgust',
2: 'fear',
3: 'happy',
4: 'neutral',
5: 'sad',
6: 'surprise'
}
EMOTION_TO_ID = {v: k for k, v in ID_TO_EMOTION.items()}