python dlib caffe人脸相似度_人脸属性识别之PyTorch简单实现

人脸属性识别已经是一个解决的比较好的问题了。这里是花了一天时间做的一个简单的验证性项目。工程完整代码(GitHub)在

训练数据使用CUHK的 Large-scale CelebFaces Attributes (CelebA) Dataset . 该数据集有40个属性标定(Attribute Label). 情况如下[1]:

CelebA Label分布(蓝色为正样本)

可见其中各个Label的正负样本都是不均衡的,而且大部分的Label都不实用。这里我选择了6个比较实用的Attribute Label做试验:Attractive(魅力), EyeGlasses(眼镜), Male(男性), MouthOpen(张嘴), Smiling(微笑), Young(年轻).

数据预处理

数据预处理的目的在于减少数据集内数据分布的差异性,有减少类内距离的同时增加类间距离的实际效果。在人脸数据处理方面,常用的有人脸检测和对齐。由于人脸属性识别任务比较简单,在这里的验证中我只使用了人脸检测(抠出图像中的人脸)。

在GitHub的代码中( https:// github.com/WynMew/FaceA ttribute/blob/master/detMTCNN_celebA.py ),人脸检测使用MTCNN[2]实现,这依赖于caffe,并且效果在当今看来已经差强人意了。如果希望不依赖caffe, 可以使用dlib解决这个问题:

在检测完之后,会有部分的图像中不能检测出人脸,这部分数据就不管了。我们使用能检测出人脸的数据做训练和测试。为了训练,我们需要知道每个检测到的人脸的Label. 这就需要从celebA提供的图像Label中查找图像名称和对应的Label值。代码为 https:// github.com/WynMew/FaceA ttribute/blob/master/AttrListGen.py

预处理完后将数据分解为三部分: Train, Val 和Test.

数据读取

PyTorch提供了数据读取接口(torch.utils.data.Dataloader),可供很方便的读取数据,对数据进行变换(data augmentation) 和调试。在dataloader中我们需要读取图像, 并归一化:

self.normalize = transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])

读取6个label, 并转换成Tensor.

def __getitem__(self, idx)

class ToTensorDict(object)

完整代码为

模型

数据集有限,同时仅仅是验证目的,所以这里从现成的模型开始。我们选用ResNet [3]开始finetune. 验证使用了ResNet18和ResNet34两个相对较小的模型作为feature提取器:

在feature提取之后,简单的接上了6个暴力分类器:

class Classifier(nn.Module):

def __init__(self, output_dim=1):

super(Classifier, self).__init__()

self.fc1 = nn.Sequential(

nn.Linear(2048, 512),

nn.ReLU(True),

nn.Dropout(p=0.5),

nn.Linear(512, 128),

nn.ReLU(True),

nn.Dropout(p=0.5),

nn.Linear(128, output_dim),

)

self.fc1.cuda()

self.fc2 = nn.Sequential(

nn.Linear(2048, 512),

nn.ReLU(True),

nn.Dropout(p=0.5),

nn.Linear(512, 128),

nn.ReLU(True),

nn.Dropout(p=0.5),

nn.Linear(128, output_dim),

)

self.fc2.cuda()

self.fc3 = nn.Sequential(

nn.Linear(2048, 512),

nn.ReLU(True),

nn.Dropout(p=0.5),

nn.Linear(512, 128),

nn.ReLU(True),

nn.Dropout(p=0.5),

nn.Linear(128, output_dim),

)

self.fc3.cuda()

self.fc4 = nn.Sequential(

nn.Linear(2048, 512),

nn.ReLU(True),

nn.Dropout(p=0.5),

nn.Linear(512, 128),

nn.ReLU(True),

nn.Dropout(p=0.5),

nn.Linear(128, output_dim),

)

self.fc4.cuda()

self.fc5 = nn.Sequential(

nn.Linear(2048, 512),

nn.ReLU(True),

nn.Dropout(p=0.5),

nn.Linear(512, 128),

nn.ReLU(True),

nn.Dropout(p=0.5),

nn.Linear(128, output_dim),

)

self.fc5.cuda()

self.fc6 = nn.Sequential(

nn.Linear(2048, 512),

nn.ReLU(True),

nn.Dropout(p=0.5),

nn.Linear(512, 128),

nn.ReLU(True),

nn.Dropout(p=0.5),

nn.Linear(128, output_dim),

)

self.fc6.cuda()

def forward(self, x):

x = x.view(x.size(0), -1)

x1 = self.fc1(x)

x2 = self.fc2(x)

x3 = self.fc3(x)

x4 = self.fc4(x)

x5 = self.fc5(x)

x6 = self.fc6(x)

return x1, x2, x3, x4, x5, x6

然后将二者接起来:

feature = self.FeatureExtraction(img)

Attractive, EyeGlasses, Male, MouthOpen, Smiling, Young = self.classifier(feature)

训练

在训练部分需要设置model, GPU, optimizer, learning rate, loss等参数:

torch.cuda.set_device(2)

cwd = os.getcwd()

print(cwd)

model = AttrPre()

model.cuda()

init_lr = 1e-4

optimizer = optim.SGD(model.parameters(), lr= init_lr, momentum=0.5)

loss = nn.MSELoss()

这里optimizer和loss使用了简单的参数。

同时,我们希望learning rate随着训练epoch的增加而变化:

def adjust_lr(optimizer, epoch, maxepoch, init_lr, power = 0.9):

lr = init_lr * (1-epoch/maxepoch)**power

for param_group in optimizer.param_groups:

param_group['lr'] = lr

return lr

在每个epoch之后存储模型参数:

checkpoint_name = os.path.join('AttrPreResNet18Det256V0_MSEloss.pth.tar')

save_checkpoint({

'epoch': epoch + 1,

'state_dict': model.state_dict(),

'best_test_loss': best_test_loss,

'optimizer': optimizer.state_dict(),

}, is_best, checkpoint_name)

完整代码为

分别对应ResNet18 和 ResNet34.

可以看到模型很快收敛了。

模型评估

训练完各个epoch之后,我们希望能评估模型训练的效果。

流程为设置模型,读取模型参数,作出预测和统计(预测值大于0的视为预测label 1)。完整代码为

评估发现,在训练5到9个epoch之后模型达到最优。我测试的最优结果如下:

Attractive: 0.8123

EyeGlasses: 0.9947

Male: 0.9550

MouthOpen: 0.9291

Smiling: 0.9028

Young: 0.8530

可以看到,即使使用如此简单暴力的方法,结果还是不错的。只在Attractive,Smiling和Young这几个Label标定比较主观,缺乏准确性的属性上效果比较差。不过模型预测给出的是评分,可以用此方法给出人脸的魅力值,情绪值等参数。

[1] Rudd, Ethan M., M. Günther, and T. E. Boult. "MOON: A Mixed Objective Optimization Network for the Recognition of Facial Attributes." European Conference on Computer Vision Springer, Cham, 2016:19-35.

[2] Zhang, Kaipeng, et al. "Joint Face Detection and Alignment Using Multitask Cascaded Convolutional Networks." IEEE Signal Processing Letters 23.10(2016):1499-1503.

[3] He, Kaiming, et al. "Deep Residual Learning for Image Recognition." (2015):770-778.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值