SamYuen101234 / Masked_Face_Recognition

2020/2021 HKUST CSE FYP Masked Facial Recognition, developer: Sam Yuen, Alex Xie, Tony Cheng
https://github.com/SamYuen101234/maskedfacerecognition
MIT License
118 stars 32 forks source link

Can't load pretrained model #24

Closed Newboot32 closed 2 years ago

Newboot32 commented 2 years ago

I'm trying to load the .pt model you provided, but I can't seem to make it work Code:

model = InceptionResnetV1(pretrained='vggface2')
checkpoint = torch.load("/content/drive/MyDrive/export/InceptionResNetV1_ArcFace.pt")
model.load_state_dict(checkpoint)
model = model.cuda()

Output:

`ModuleNotFoundError                       Traceback (most recent call last)
[<ipython-input-6-9840bef75f84>](https://localhost:8080/#) in <module>()
      1 model = InceptionResnetV1(pretrained='vggface2')
----> 2 checkpoint= torch.load("/content/drive/MyDrive/export/InceptionResNetV1_ArcFace.pt")
      3 model.load_state_dict(checkpoint)
      4 model = model.cuda()

2 frames
[/usr/local/lib/python3.7/dist-packages/torch/serialization.py](https://localhost:8080/#) in find_class(self, mod_name, name)
    873         def find_class(self, mod_name, name):
    874             mod_name = load_module_mapping.get(mod_name, mod_name)
--> 875             return super().find_class(mod_name, name)
    876 
    877     # Load the data (which may in turn use `persistent_load` to load tensors)

ModuleNotFoundError: No module named 'model'`

Can you please tell me what did I do wrong and how to fix it? I'm a beginner so I don't really know what to do here.

SamYuen101234 commented 2 years ago

You should not use InceptionResnetV1 to load the saved model. Their class structure is different, although the model is the same (because the saved model is a class that I defined). You should import the script of facenet2 which is the class of the saved model.

Newboot32 commented 2 years ago

I see. Thank you

Newboot32 commented 2 years ago

I'm really sorry for reopening the issue. I've tried importing facenet2 but it still won't load.

What I imported :

class PKSampler(Sampler):

    def __init__(self, data_source, p=15, k=20):
        super().__init__(data_source)
        self.p = p
        self.k = k
        self.data_source = data_source

    def __iter__(self):
        pk_count = len(self) // (self.p * self.k)
        for _ in range(pk_count):
            labels = np.random.choice(np.arange(len(self.data_source.label_to_samples)), self.p, replace=False)
            for l in labels:
                indices = self.data_source.label_to_samples[l]
                replace = True if len(indices) < self.k else False
                for i in np.random.choice(indices, self.k, replace=replace):
                    yield i

    def __len__(self):
        pk = self.p * self.k
        samples = ((len(self.data_source) - 1) // pk + 1) * pk
        return samples

def grouper(iterable, n):
    it = itertools.cycle(iter(iterable))
    for _ in range((len(iterable) - 1) // n + 1):
        yield list(itertools.islice(it, n))
class PKSampler2(Sampler):

    def __init__(self, data_source, p=15, k=20):
        super().__init__(data_source)
        self.p = p
        self.k = k
        self.data_source = data_source

    def __iter__(self):
        rand_labels = np.random.permutation(np.arange(len(self.data_source.label_to_samples)))
        for labels in grouper(rand_labels, self.p):
            for l in labels:
                indices = self.data_source.label_to_samples[l]
                replace = True if len(indices) < self.k else False
                for j in np.random.choice(indices, self.k, replace=replace):
                    yield j

    def __len__(self):
        num_labels = len(self.data_source.label_to_samples)
        samples = ((num_labels - 1) // self.p + 1) * self.p * self.k
        return samples
class ArcMarginProduct(nn.Module):
    def __init__(self, in_features, out_features):
        super().__init__()
        self.weight = nn.Parameter(torch.Tensor(out_features, in_features))
        self.reset_parameters()

    def reset_parameters(self):
        nn.init.xavier_uniform_(self.weight)

    def forward(self, features):
        cosine = F.linear(F.normalize(features), F.normalize(self.weight))
        return cosine

def get_Optimizer(model, optimizer_type=None, lr=1e-3, weight_decay=1e-3):
    if(optimizer_type=='sgd'):
        return optim.SGD(model.parameters(), lr=lr, momentum=0.9, nesterov=True, weight_decay=weight_decay)
    elif(optimizer_type=='rmsprop'):
        return optim.RMSprop(model.parameters(), lr=lr, weight_decay=weight_decay)
    elif(optimizer_type=='adadelta'):
        return optim.Adadelta(model.parameters(), lr=lr, weight_decay=weight_decay)
    else:
        return optim.Adam(model.parameters(), lr=lr, weight_decay=weight_decay)

def get_Scheduler(optimizer, lr, scheduler_name=None):
    if(scheduler_name=='cyclic'):
        return optim.lr_scheduler.CyclicLR(optimizer, base_lr=5e-4, max_lr=lr, step_size_up=500)
    elif(scheduler_name=='cosine'):
        return optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=1000)
    elif(scheduler_name=='multistep'):
        return optim.lr_scheduler.MultiStepLR(optimizer, milestones=[5, 10, 15, 20], gamma=0.1)
    else:
        return optim.lr_scheduler.StepLR(optimizer, step_size=1, gamma=0.7)
class InceptionResnet(nn.Module):
    def __init__(self, device, pool=None, dropout=0.3, pretrain=True):
        super(InceptionResnet, self).__init__()
        # fit an image, the output is a 512 embedding original
        # the model is pre-trained on vggface2
        # pretrained='vggface2'
        if pretrain:
            self.net = InceptionResnetV1(pretrained='vggface2', dropout_prob=dropout, device=device)
        else:
            self.net = InceptionResnetV1(dropout_prob=dropout, device=device)
        # the number of channels in the output of convolutional layers
        self.out_features = self.net.last_linear.in_features
        # keep convolutional layers only and remove linear layers and global average pooling layer
        if pool == 'gem':
            self.net.avgpool_1a = GeM(p_trainable=True)
    def forward(self, x):
        # return a 512 dimension vector
        return self.net(x)

class EfficientNetEncoderHead(nn.Module):
    def __init__(self, depth, pretrain=True):
        super(EfficientNetEncoderHead, self).__init__()
        self.depth = depth
        if pretrain:
            self.net = EfficientNet.from_pretrained(f'efficientnet-b{self.depth}')
        else:
            self.net = EfficientNet.from_name(f'efficientnet-b{self.depth}')
        self.out_features = self.net._fc.in_features
    def forward(self, x):
        # only the cnn part
        return self.net.extract_features(x)

class SEResNeXt101(nn.Module):
    def __init__(self, pretrained=True):
        super(SEResNeXt101, self).__init__()
        self.net = timm.create_model('gluon_seresnext101_32x4d', pretrained=pretrained)
        # the output size of this model
        self.out_features = self.net.fc.in_features
    def forward(self, x):
        return self.net.forward_features(x)

def gem(x, p=3, eps=1e-6):
    return F.avg_pool2d(x.clamp(min=eps).pow(p), (x.size(-2), x.size(-1))).pow(1./p)

class GeM(nn.Module):
    def __init__(self, p=3, eps=1e-6, p_trainable=True):
        super(GeM,self).__init__()
        if p_trainable:
            self.p = Parameter(torch.ones(1)*p)
        else:
            self.p = p
        self.eps = eps

    def forward(self, x):
        return gem(x, p=self.p, eps=self.eps)      
    def __repr__(self):
        return self.__class__.__name__ + '(' + 'p=' + '{:.4f}'.format(self.p.data.tolist()[0]) + ', ' + 'eps=' + str(self.eps) + ')'
class FaceNet(nn.Module):
    def __init__(self, model_name=None, pool=None, dropout=0.0, embedding_size=512, device='cuda', pretrain=True):
        super(FaceNet, self).__init__()
        # Backbone
        # three models choice 1. SE-ResNeXt101 2.EfficientNetB7 3.InceptionResnetV1 (Pre-trained for face recog.)
        self.model_name = model_name

        # model (backbone)
        if(model_name=='resnet'):
            self.model = SEResNeXt101(pretrain)
        elif(model_name=='effnet'):
            self.model = EfficientNetEncoderHead(depth=3, pretrain=pretrain)
        else:
            self.model = InceptionResnet(device, pool=pool, dropout=dropout, pretrain=pretrain)

        if(pool == "gem"):
            self.global_pool = GeM(p_trainable=True)
        else:
            self.global_pool = nn.AdaptiveAvgPool2d(1)
        self.neck = nn.Sequential(
                nn.Linear(self.model.out_features, embedding_size, bias=True),
                nn.BatchNorm1d(embedding_size, eps=0.001),
                #nn.Sigmoid()
            )
        self.dropout = nn.Dropout(p=dropout)

    def forward(self, x):
        # backbone
        if self.model_name == None:
            return self.model(x)

        x = self.model(x)
        # global pool
        x = self.global_pool(x)
        x = self.dropout(x)
        # change the output from cnn to a vector first
        x = x[:,:,0,0]
        # neck
        embeddings = self.neck(x)
        return embeddings
class ArcMarginProduct(nn.Module):
    def __init__(self, in_features, out_features):
        super().__init__()
        self.weight = nn.Parameter(torch.Tensor(out_features, in_features))
        self.reset_parameters()

    def reset_parameters(self):
        nn.init.xavier_uniform_(self.weight)

    def forward(self, features):
        cosine = F.linear(F.normalize(features), F.normalize(self.weight))
        return cosine

class FaceNet2(nn.Module):
    def __init__(self, num_classes, model_name=None, pool=None, dropout=0.0, embedding_size=512, device='cuda', pretrain=True):
        super(FaceNet2, self).__init__()
        # Backbone (backbone)
        # three models choice 1. SE-ResNeXt101 2.EfficientNetB7 3.InceptionResnetV1 (Pre-trained for face recog.)
        self.model_name = model_name

        # model
        if(model_name=='resnet'):
            self.model = SEResNeXt101(pretrain)
        elif(model_name=='effnet'):
            self.model = EfficientNetEncoderHead(depth=3, pretrain=pretrain)
        else:
            self.model = InceptionResnet(device, pool=pool, dropout=dropout, pretrain=pretrain)

        # global pooling
        if(pool == "gem"):
            # Generalizing Pooling
            self.global_pool = GeM(p_trainable=True)
        else:
            # global average pooling
            self.global_pool = nn.AdaptiveAvgPool2d(1)
        # neck
        self.neck = nn.Sequential(
                nn.Linear(self.model.out_features, embedding_size, bias=True),
                nn.BatchNorm1d(embedding_size, eps=0.001),
            )
        self.dropout = nn.Dropout(p=dropout)

        self.head = ArcMarginProduct(embedding_size, num_classes)

    def forward(self, x):   
        # backbone
        if self.model_name == None:
            embeddings = self.model(x)
            logits = self.head(embeddings)
            return {'logits': logits, 'embeddings': embeddings}

        x = self.model(x)
        # global pool
        x = self.global_pool(x)
        x = self.dropout(x)
        # change the output from cnn to a vector first
        x = x[:,:,0,0]
        # neck
        embeddings = self.neck(x)
        # vector with num_classes
        logits = self.head(embeddings)
        return {'logits': logits, 'embeddings': embeddings}
def load(save_path):
    save_path = '/content/drive/MyDrive/export/InceptionResNetV1_ArcFace.pt'
    checkpoint = torch.load(save_path)
    model = checkpoint['model']
    optimizer = checkpoint['optimizer']
    scheduler = checkpoint['scheduler']
    print(f'Model loaded from <== {save_path}')
    return model, optimizer, scheduler`

Yet when I run this code:

facenet = FaceNet2(num_classes=8631)
optimizer = get_Optimizer(model=facenet) # optimizer
scheduler = get_Scheduler(optimizer,lr=5e-2) # scheduler
facenet, optimizer, scheduler = load('/content/drive/MyDrive/export/InceptionResNetV1_ArcFace.pt')

I got this instead:

ModuleNotFoundError                       Traceback (most recent call last)
[<ipython-input-35-887c94ca79c9>](https://localhost:8080/#) in <module>()
----> 1 facenet, optimizer, scheduler = load('/content/drive/MyDrive/export/InceptionResNetV1_ArcFace.pt')

3 frames
[<ipython-input-34-6acbab7e4d87>](https://localhost:8080/#) in load(save_path)
      1 def load(save_path):
      2     save_path = '/content/drive/MyDrive/export/InceptionResNetV1_ArcFace.pt'
----> 3     checkpoint = torch.load(save_path)
      4     model = checkpoint['model']
      5     optimizer = checkpoint['optimizer']

[/usr/local/lib/python3.7/dist-packages/torch/serialization.py](https://localhost:8080/#) in load(f, map_location, pickle_module, **pickle_load_args)
    710                     opened_file.seek(orig_position)
    711                     return torch.jit.load(opened_file)
--> 712                 return _load(opened_zipfile, map_location, pickle_module, **pickle_load_args)
    713         return _legacy_load(opened_file, map_location, pickle_module, **pickle_load_args)
    714 

[/usr/local/lib/python3.7/dist-packages/torch/serialization.py](https://localhost:8080/#) in _load(zip_file, map_location, pickle_module, pickle_file, **pickle_load_args)
   1044     unpickler = UnpicklerWrapper(data_file, **pickle_load_args)
   1045     unpickler.persistent_load = persistent_load
-> 1046     result = unpickler.load()
   1047 
   1048     torch._utils._validate_loaded_sparse_tensors()

[/usr/local/lib/python3.7/dist-packages/torch/serialization.py](https://localhost:8080/#) in find_class(self, mod_name, name)
   1037                     pass
   1038             mod_name = load_module_mapping.get(mod_name, mod_name)
-> 1039             return super().find_class(mod_name, name)
   1040 
   1041     # Load the data (which may in turn use `persistent_load` to load tensors)

ModuleNotFoundError: No module named 'model'

Have I made a mistake? Is there any workaround or solution to solve this problem?

SamYuen101234 commented 2 years ago

Can you run my code with python3 main2.py?

You have loaded the .pth model but there is no attribute name called model in the loaded class. Can you check all attributes variables after checkpoint = torch.load(save_path) and post it here? Then, I can figure out what problem is there.

Newboot32 commented 2 years ago

Never mind, turns out I'm using the wrong model by mistake. It works now when I used the triplet model Thank you and sorry for disturbing