把vgg-face.mat权重迁移到pytorch模型

最近使用pytorch时,需要用到一个预训练好的人脸识别模型提取人脸ID特征,想到很多人都在用用vgg-face,但是vgg-face没有pytorch的模型,于是写个vgg-face.mat转到pytorch模型的代码

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
Created on Thu May 10 10:41:40 2018

@author: hy
"""
import torch
import math
import torch.nn as nn
from torch.autograd import Variable
import numpy as np
from scipy.io import loadmat
import scipy.misc as sm
import matplotlib.pyplot as plt

class vgg16_face(nn.Module):
    def __init__(self,num_classes=2622):
        super(vgg16_face,self).__init__()
        inplace = True
        self.conv1_1 = nn.Conv2d(3,64,kernel_size=(3,3),stride=(1,1),padding=(1,1))
        self.relu1_1 = nn.ReLU(inplace)
        self.conv1_2 = nn.Conv2d(64,64,kernel_size=(3,3),stride=(1,1),padding=(1,1))
        self.relu1_2 = nn.ReLU(inplace)
        self.pool1 = nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2), dilation=(1, 1), ceil_mode=False)
            
        self.conv2_1 = nn.Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        self.relu2_1 = nn.ReLU(inplace)
        self.conv2_2 = nn.Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        self.relu2_2 = nn.ReLU(inplace)
        self.pool2 = nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2), dilation=(1, 1), ceil_mode=False)
            
        self.conv3_1 = nn.Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        self.relu3_1 = nn.ReLU(inplace)
        self.conv3_2 = nn.Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        self.relu3_2 = nn.ReLU(inplace)
        self.conv3_3 = nn.Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        self.relu3_3 = nn.ReLU(inplace)
        self.pool3 = nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2), dilation=(1, 1), ceil_mode=False)
            
        self.conv4_1 = nn.Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        self.relu4_1 = nn.ReLU(inplace)
        self.conv4_2 = nn.Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        self.relu4_2 = nn.ReLU(inplace)
        self.conv4_3 = nn.Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        self.relu4_3 = nn.ReLU(inplace)
        self.pool4 = nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2), dilation=(1, 1), ceil_mode=False)
            
        self.conv5_1 = nn.Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        self.relu5_1 = nn.ReLU(inplace)
        self.conv5_2 = nn.Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        self.relu5_2 = nn.ReLU(inplace)
        self.conv5_3 = nn.Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        self.relu5_3 = nn.ReLU(inplace)
        self.pool5 = nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2), dilation=(1, 1), ceil_mode=False) 
            
        self.fc6 = nn.Linear(in_features=25088, out_features=4096, bias=True)
        self.relu6 = nn.ReLU(inplace)
        self.drop6 = nn.Dropout(p=0.5)
        
        self.fc7 = nn.Linear(in_features=4096, out_features=4096, bias=True)
        self.relu7 = nn.ReLU(inplace)
        self.drop7 = nn.Dropout(p=0.5)
        self.fc8 = nn.Linear(in_features=4096, out_features=num_classes, bias=True)
            
        self._initialize_weights()
    def forward(self,x):
        out = self.conv1_1(x)
        x_conv1 = out
        out = self.relu1_1(out)
        out = self.conv1_2(out)
        out = self.relu1_2(out)
        out = self.pool1(out)
        x_pool1 = out
        
        out = self.conv2_1(out)
        out = self.relu2_1(out)
        out = self.conv2_2(out)
        out = self.relu2_2(out)
        out = self.pool2(out)
        x_pool2 = out
        
        out = self.conv3_1(out)
        out = self.relu3_1(out)
        out = self.conv3_2(out)
        out = self.relu3_2(out)
        out = self.conv3_3(out)
        out = self.relu3_3(out)
        out = self.pool3(out)
        x_pool3 = out
        
        out = self.conv4_1(out)
        out = self.relu4_1(out)
        out = self.conv4_2(out)
        out = self.relu4_2(out)
        out = self.conv4_3(out)
        out = self.relu4_3(out)
        out = self.pool4(out)
        x_pool4 = out
        
        out = self.conv5_1(out)
        out = self.relu5_1(out)
        out = self.conv5_2(out)
        out = self.relu5_2(out)
        out = self.conv5_3(out)
        out = self.relu5_3(out)
        out = self.pool5(out)
        x_pool5 = out
        
        out = out.view(out.size(0),-1)
        
        out = self.fc6(out)
        out = self.relu6(out)
        out = self.fc7(out)
        out = self.relu7(out)
        out = self.fc8(out)
        
        return out, x_pool1, x_pool2, x_pool3, x_pool4, x_pool5

    def _initialize_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
                m.weight.data.normal_(0, math.sqrt(2. / n))
                if m.bias is not None:
                    m.bias.data.zero_()
            elif isinstance(m, nn.BatchNorm2d):
                m.weight.data.fill_(1)
                m.bias.data.zero_()
            elif isinstance(m, nn.Linear):
                m.weight.data.normal_(0, 0.01)
                m.bias.data.zero_()
          
def copy(vgglayers, dstlayer,idx):
    layer = vgglayers[0][idx]
    kernel, bias = layer[0]['weights'][0][0]
    if idx in [33,35]: # fc7, fc8
        kernel = kernel.squeeze()
        dstlayer.weight.data.copy_(torch.from_numpy(kernel.transpose([1,0]))) # matrix format: axb -> bxa
    elif idx == 31: # fc6
        kernel = kernel.reshape(-1,4096)
        dstlayer.weight.data.copy_(torch.from_numpy(kernel.transpose([1,0]))) # matrix format: axb -> bxa
    else:
        dstlayer.weight.data.copy_(torch.from_numpy(kernel.transpose([3,2,1,0]))) # matrix format: axbxcxd -> dxcxbxa
    dstlayer.bias.data.copy_(torch.from_numpy(bias.reshape(-1)))

def get_vggface(vgg_path):
    """1. define pytorch model"""      
    model = vgg16_face()     
    
    """2. get pre-trained weights and other params"""          
    #vgg_path = "/home/hy/vgg-face.mat" # download from http://www.vlfeat.org/matconvnet/pretrained/
    vgg_weights = loadmat(vgg_path)
    data = vgg_weights
    meta = data['meta']
    classes = meta['classes']
    class_names = classes[0][0]['description'][0][0]
    normalization = meta['normalization']
    average_image = np.squeeze(normalization[0][0]['averageImage'][0][0][0][0])
    image_size = np.squeeze(normalization[0][0]['imageSize'][0][0])
    layers = data['layers']
    # =============================================================================
    # for idx,layer in enumerate(layers[0]):
    #     name = layer[0]['name'][0][0]
    #     print idx,name
    # """
    # 0 conv1_1
    # 1 relu1_1
    # 2 conv1_2
    # 3 relu1_2
    # 4 pool1
    # 5 conv2_1
    # 6 relu2_1
    # 7 conv2_2
    # 8 relu2_2
    # 9 pool2
    # 10 conv3_1
    # 11 relu3_1
    # 12 conv3_2
    # 13 relu3_2
    # 14 conv3_3
    # 15 relu3_3
    # 16 pool3
    # 17 conv4_1
    # 18 relu4_1
    # 19 conv4_2
    # 20 relu4_2
    # 21 conv4_3
    # 22 relu4_3
    # 23 pool4
    # 24 conv5_1
    # 25 relu5_1
    # 26 conv5_2
    # 27 relu5_2
    # 28 conv5_3
    # 29 relu5_3
    # 30 pool5
    # 31 fc6
    # 32 relu6
    # 33 fc7
    # 34 relu7
    # 35 fc8
    # 36 prob
    # """
    # =============================================================================
    
    """3. load weights to pytorch model"""   
    copy(layers,model.conv1_1,0)
    copy(layers,model.conv1_2,2)
    copy(layers,model.conv2_1,5)
    copy(layers,model.conv2_2,7)
    copy(layers,model.conv3_1,10)
    copy(layers,model.conv3_2,12)
    copy(layers,model.conv3_3,14)
    copy(layers,model.conv4_1,17)
    copy(layers,model.conv4_2,19)
    copy(layers,model.conv4_3,21)
    copy(layers,model.conv5_1,24)
    copy(layers,model.conv5_2,26)
    copy(layers,model.conv5_3,28)
    copy(layers,model.fc6,31)
    copy(layers,model.fc7,33)
    copy(layers,model.fc8,35)
    return model,class_names,average_image,image_size

if __name__ == '__main__':
    """test""" 
    vgg_path = "/home/hy/vgg-face.mat" # download from http://www.vlfeat.org/matconvnet/pretrained/ 
    model,class_names,average_image,image_size = get_vggface(vgg_path) 
    imgpath = "/home/hy/e/avg_face.jpg"
    img = sm.imread(imgpath)
    img = sm.imresize(img,[image_size[0],image_size[1]])
    input_arr = np.float32(img)#-average_image # h,w,c
    x = torch.from_numpy(input_arr.transpose((2,0,1))) # c,h,w
    avg = torch.from_numpy(average_image) # 
    avg = avg.view(3,1,1).expand(3,224,224)
    x = x - avg
    x = x.contiguous()
    x = x.view(1, x.size(0), x.size(1), x.size(2))
    x = Variable(x)
    out, x_pool1, x_pool2, x_pool3, x_pool4, x_pool5 = model(x)
#    plt.imshow(x_pool1.data.numpy()[0,45]) # plot

参考:https://blog.csdn.net/raby_gyl/article/details/80172346

 

 

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值