| Backbone | MobileNetV3-L (ImageNet pretrained, timm) |
| 輸入解析度 | 192 × 192 |
| Heads | gender (3-class CE) + age regression (smooth L1) + age bucket (6-class aux CE, λ=0.5) |
| Optimizer | AdamW lr=1e-3 wd=1e-4 + Cosine LR |
| Batch | 128 × 2 GPUs (DDP NCCL) |
| Epoch | 30 (best epoch 28, val MAE 6.91) |
| Aug | RandomResizedCrop, HFlip, ColorJitter, RandomErasing(p=0.1) |
| Sampling | Class-balanced (by age_bucket) on single-GPU; DistributedSampler on DDP |
| 訓練機 | 5090-2 雙卡 RTX 5090 (BF16 AMP) |
| 訓練時長 | ~7 min(30 epoch × 9s/ep) |
R2 公開連結:
https://pub-478929a98a5c440cb22c2241c0bde314.r2.dev/age_gender_v20260508/best.pt
用法(Python,timm + torch):
import torch, timm, torch.nn as nn
ckpt = torch.load('best.pt', map_location='cpu')
class AgeGenderModel(nn.Module):
def __init__(self):
super().__init__()
self.backbone = timm.create_model('mobilenetv3_large_100',
pretrained=False, num_classes=0,
global_pool='avg', drop_rate=0.3)
d = self.backbone(torch.zeros(1,3,192,192)).shape[-1]
self.gender_head = nn.Linear(d, 3)
self.age_head = nn.Linear(d, 1)
self.bucket_head = nn.Linear(d, 6)
def forward(self, x):
f = self.backbone(x)
return self.gender_head(f), self.age_head(f).squeeze(-1), self.bucket_head(f)
m = AgeGenderModel()
m.load_state_dict(ckpt['state_dict'])
m.eval()
# input: 192×192 RGB normalized ImageNet stats
# output: (gender_logits[3], age_norm[0,1] *100=年齡, bucket_logits[6])