bel_canto / model.py
MuGeminorum
upl base
f945864
raw
history blame
4.64 kB
import os
import torch
import torch.nn as nn
import torchvision.models as models
from modelscope.msdatasets import MsDataset
from utils import url_download, create_dir, DOMAIN
def get_backbone(ver, backbone_list):
for bb in backbone_list:
if ver == bb['ver']:
return bb
print('Backbone name not found, using default option - alexnet.')
return backbone_list[0]
def model_info(m_ver):
backbone_list = MsDataset.load(
'monetjoe/cv_backbones',
subset_name='ImageNet1k_v1',
split='train'
)
backbone = get_backbone(m_ver, backbone_list)
m_type = str(backbone['type'])
input_size = int(backbone['input_size'])
return m_type, input_size
def download_model(log_name='vit_b_16_mel_2024-01-07_05-16-24'):
pre_model_url = f'{DOMAIN}{log_name}/save.pt'
pre_model_path = f"./model/{log_name}.pt"
m_ver = '_'.join(log_name.split('_')[:-3])
create_dir('./model')
if not os.path.exists(pre_model_path):
url_download(pre_model_url, pre_model_path)
return pre_model_path, m_ver
def Classifier(cls_num: int, output_size: int, linear_output: bool):
q = (1.0 * output_size / cls_num) ** 0.25
l1 = int(q * cls_num)
l2 = int(q * l1)
l3 = int(q * l2)
if linear_output:
return torch.nn.Sequential(
nn.Dropout(),
nn.Linear(output_size, l3),
nn.ReLU(inplace=True),
nn.Dropout(),
nn.Linear(l3, l2),
nn.ReLU(inplace=True),
nn.Dropout(),
nn.Linear(l2, l1),
nn.ReLU(inplace=True),
nn.Linear(l1, cls_num)
)
else:
return torch.nn.Sequential(
nn.Dropout(),
nn.Conv2d(output_size, l3, kernel_size=(1, 1), stride=(1, 1)),
nn.ReLU(inplace=True),
nn.AdaptiveAvgPool2d(output_size=(1, 1)),
nn.Flatten(),
nn.Linear(l3, l2),
nn.ReLU(inplace=True),
nn.Dropout(),
nn.Linear(l2, l1),
nn.ReLU(inplace=True),
nn.Linear(l1, cls_num)
)
class EvalNet():
model = None
m_type = 'squeezenet'
input_size = 224
output_size = 512
def __init__(self, log_name, cls_num=4):
saved_model_path, m_ver = download_model(log_name)
self.m_type, self.input_size = model_info(m_ver)
if not hasattr(models, m_ver):
print('Unsupported model.')
exit()
self.model = eval('models.%s()' % m_ver)
linear_output = self._set_outsize()
self._set_classifier(cls_num, linear_output)
checkpoint = torch.load(saved_model_path, map_location='cpu')
if torch.cuda.is_available():
checkpoint = torch.load(saved_model_path)
self.model.load_state_dict(checkpoint, False)
self.model.eval()
def _set_outsize(self, debug_mode=False):
for name, module in self.model.named_modules():
if str(name).__contains__('classifier') or str(name).__eq__('fc') or str(name).__contains__('head'):
if isinstance(module, torch.nn.Linear):
self.output_size = module.in_features
if debug_mode:
print(
f"{name}(Linear): {self.output_size} -> {module.out_features}")
return True
if isinstance(module, torch.nn.Conv2d):
self.output_size = module.in_channels
if debug_mode:
print(
f"{name}(Conv2d): {self.output_size} -> {module.out_channels}")
return False
return False
def _set_classifier(self, cls_num, linear_output):
if hasattr(self.model, 'classifier'):
self.model.classifier = Classifier(
cls_num, self.output_size, linear_output)
return
elif hasattr(self.model, 'fc'):
self.model.fc = Classifier(
cls_num, self.output_size, linear_output)
return
elif hasattr(self.model, 'head'):
self.model.head = Classifier(
cls_num, self.output_size, linear_output)
return
self.model.heads.head = Classifier(
cls_num, self.output_size, linear_output)
def forward(self, x):
if torch.cuda.is_available():
x = x.cuda()
self.model = self.model.cuda()
if self.m_type == 'googlenet' and self.training:
return self.model(x)[0]
else:
return self.model(x)