人脸相似度比较的一些改进

本文介绍了如何通过训练神经网络改进人脸识别中的相似度计算,使用CASIA-WebFace数据集对人脸进行编码和特征组合,最终通过LR、随机森林等传统模型和自定义神经网络模型实现高精度的相似度判断。
摘要由CSDN通过智能技术生成

        在人脸识别中,我们通常采用欧氏距离和余弦距离来衡量人脸特征的相似度,判别是否为同一个人,但这样的精度通常比较低,本文将通过训练的方式提高相似度计算的精度。

一、数据集

        本文采用CASIA-WebFace数据集:

        如上图所示每个目录代表其中一个人

二、对人脸编码   

        首先需要对每一张人脸进行编码,将人脸转换为长度为128的向量,代码如下:

import face_recognition
image_path = './img.jpg'#图片路径
img = face_recognition.load_image_file(image_path)
encoding = face_recognition.face_encodings(img , num_jitters=4)

三、构建特征

        我们对任意两张图片的编码向量组合,同一目录的label记为1,不同label的记为0,组合成长度为256的向量。

四、相似度计算

        这里有训练数据有标签可以采样传统的机器学习模型:LR,随机森林,lightgbm等,本文将通过构建一个简单的神经网络来完成这个事情。

        首先是构建Dataset,以及评估函数

import pandas as pd
import torch
from torch import nn
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score,accuracy_score
from torch.utils.data import Dataset
import random
import os
from torch.utils.data import DataLoader
import torch.optim as optim
from tqdm import tqdm
class evaluate:
    def __init__(self):
        pass
    def set_lable(self,y_ture,y_pre):
        self.y_ture = torch.concat(y_ture).flatten().cpu().numpy()
        self.y_pre = torch.concat(y_pre).flatten().cpu().numpy()
    def evaluation(self, outputs, labels):  # 定义自己的评价函数,用分类的准确率来评价
        # outputs => probability (float)
        # labels => labels
        outputs[outputs >= 0.5] = 1  # 大於等於0.5為有惡意
        outputs[outputs < 0.5] = 0  # 小於0.5為無惡意
        correct = torch.sum(torch.eq(outputs, labels)).item()
        return correct
    def acc(self):
        return accuracy_score(self.y_ture, self.y_pre)
    def auc(self):
        return roc_auc_score(self.y_ture,self.y_pre)
class myDataset(Dataset):
    def __init__(self,x,y):
        self.x = x
        self.y = y
    def __getitem__(self, item):
        lable = self.y[item]
        feature = self.x[item]
        return feature,lable
    def __len__(self):
        return len(self.x)

        然后是module

class mymodule(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear = nn.Sequential(
            nn.Linear(256 ,512)
            ,nn.BatchNorm1d(512),
            nn.ReLU(),
            nn.Linear(512,256)
            ,nn.BatchNorm1d(256),
            nn.ReLU(),
            nn.Linear(256,128)
            ,nn.BatchNorm1d(128),
            nn.ReLU(),
            #nn.Dropout(p=0.5),
            nn.Linear(128, 2)
        )
    def forward(self,input):
        out = self.linear(input)
        return out

        最后是训练

traindataset = myDataset(x = torch.tensor(X_train.values),y = torch.tensor(y_train.values))
testdataset = myDataset(x = torch.tensor(X_test.values),y = torch.tensor(y_test.values))
batch_size = 16
train_loader = DataLoader(dataset = traindataset,batch_size=batch_size,shuffle=True)
val_loader = DataLoader(dataset = testdataset,batch_size=batch_size,shuffle=True)
model = mymodule()

e1 = evaluate()
e2 = evaluate()
criterion = nn.CrossEntropyLoss()
lr = 0.001
#optimizer = optim.Adam(model.parameters(), lr=lr)
optimizer = torch.optim.SGD(lr=lr,params=model.parameters(), momentum=0.5)
best_acc = 0.
epochs = 50
diff = []
pt = {}
for epoch in tqdm(range(epochs)):
    model.train()
    total_loss, total_acc = 0, 0
    pre_list_train,train_label = [],[]
    if epoch % 5 == 0:
        optimizer.param_groups[0]['lr'] *= 0.5
    for i, (inputs, labels) in enumerate(train_loader):
        inputs = inputs.to(dtype=torch.float)
        labels = labels.to(dtype=torch.long)  # 类型为float
        # 2. 清空梯度
        outputs = model(inputs)
        optimizer.zero_grad()
        #print(outputs)
        loss = criterion(outputs, labels.long())
        _,pre_train = outputs.max(1)
        pre_list_train.append(pre_train)
        train_label.append(labels)
        loss.backward()
        optimizer.step()
    model.eval()
    total_loss, total_acc = 0, 0
    pre_list_test, test_label = [],[]
    for i, (inputs, labels) in enumerate(val_loader):
        inputs = inputs.to(dtype=torch.float)
        labels = labels.to(dtype=torch.long)
        outputs = model(inputs)
        _,pre_test = outputs.max(1)
        loss = criterion(outputs, labels.long())
        total_loss += loss.item()
        pre_list_test.append(pre_test)
        test_label.append(labels)
    e2.set_lable(test_label,pre_list_test)
    e1.set_lable(train_label, pre_list_train)
    if e1.auc()>0.90 and e2.auc()>0.90:
        diff.append(abs(e1.auc() - e2.auc()))
        pt[epoch] = model.state_dict()
        print(epoch)
    print('\n','epoch:',epoch,
          'train_auc:',e1.auc(),
          'test_auc:',e2.auc())
    
# torch.save(model.state_dict(), f'{epoch}moth.pt')

        可以看到第三轮的时候auc已经达到了0.96

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值