1. Why Siamese
在人脸识别中,存在所谓的one-shot问题。举例来说,就是对公司员工进行人脸识别,每个员工只有一张照片(因为每个类别训练样本少),并且员工会离职、入职(每次变动都要重新训练模型是不现实的)。如果当成分类问题,直接训练模型进行人脸识别在实际应用中是不可行。
为了解决one-shot问题,我们会训练一个模型来输出给定两张图像的相似度,所以模型学习得到的是similarity函数,通过对相似度设定一个阈值判断是否属于同一个人。
哪些模型能通过学习得到similarity函数呢?Siamese网络就是这样的一种模型。
2. What is Siamese network
(Siamese网络是一种模型设计框架,这里举人脸验证为例,用的是CNN模型,其他任务中可以是LSTM等模型,最早应该是[1]这篇论文)
上图中上下两个CNN模型的模型参数值完全相同。Siamese网络输出一个向量(比如上图中是128个数值组成的一维特征向量,用于face embedding):
- 若输入的图像X1和X2为同一个人,则上下两个模型输出的一维特征向量欧氏距离较小
- 若输入的图像X1和X2不是同一个人,则上下两个模型输出的一维特征向量欧氏距离较大
所以通过对上下两个模型输出的向量做欧氏距离计算,就能得到输入两幅图像的相似度。
3. How to train Siamese network
对图中的一幅照片A,如果给定了同一个人的另一幅照片P,则模型的输出向量f(A)和f(P)应该是距离比较小的。如果给定了另一个人的照片N,则模型的输出向量f(A)和f(N)之间的距离就比较大。所以d(A,P)<d(A,N)。
目标函数:(这里叫triple loss[2])
这个loss function 的三元组(A,P,N),表示A和P是相同类别的样本,A和N是不同样本的类别,最终通过梯度下降学习使得f(A)与f(P)的距离最小化,f(A)与f(N)的距离最大化。α是个超参数,用于做margin。
【pytorch教程】PyTorch 实现孪生网络识别面部相似度
https://www.pytorchtutorial.com/pytorch-one-shot-learning/
【代码】https://github.com/harveyslash/Facial-Similarity-with-Siamese-Networks-in-Pytorch/tree/master
【代码片段】
孪生网络模型:
class SiameseNetwork(nn.Module):
def __init__(self):
super(SiameseNetwork, self).__init__()
self.cnn1 = nn.Sequential(
nn.ReflectionPad2d(1),
nn.Conv2d(1, 4, kernel_size=3),
nn.ReLU(inplace=True),
nn.BatchNorm2d(4),
nn.Dropout2d(p=.2),
nn.ReflectionPad2d(1),
nn.Conv2d(4, 8, kernel_size=3),
nn.ReLU(inplace=True),
nn.BatchNorm2d(8),
nn.Dropout2d(p=.2),
nn.ReflectionPad2d(1),
nn.Conv2d(8, 8, kernel_size=3),
nn.ReLU(inplace=True),
nn.BatchNorm2d(8),
nn.Dropout2d(p=.2),
)
self.fc1 = nn.Sequential(
nn.Linear(8*100*100, 500),
nn.ReLU(inplace=True),
nn.Linear(500, 500),
nn.ReLU(inplace=True),
nn.Linear(500, 5)
)
def forward_once(self, x):
output = self.cnn1(x)
output = output.view(output.size()[0], -1)
output = self.fc1(output)
return output
def forward(self, input1, input2):
output1 = self.forward_once(input1)
output2 = self.forward_once(input2)
return output1, output2
默认边际价值为2的对比损失:
class ContrastiveLoss(torch.nn.Module):
"""
Contrastive loss function.
Based on: http://yann.lecun.com/exdb/publis/pdf/hadsell-chopra-lecun-06.pdf
"""
def __init__(self, margin=2.0):
super(ContrastiveLoss, self).__init__()
self.margin = margin
def forward(self, output1, output2, label):
euclidean_distance = F.pairwise_distance(output1, output2)
loss_contrastive = torch.mean((1-label) * torch.pow(euclidean_distance, 2)
(label) * torch.pow(torch.clamp(self.margin - euclidean_distance, min=0.0), 2))
return loss_contrastive
训练孪生网络:
net = SiameseNetwork().cuda()
criterion = ContrastiveLoss()
optimizer = optim.Adam(net.parameters(), lr=0.0005)
counter = []
loss_history = []
iteration_number = 0
for epoch in range(0, Config.train_number_epochs):
for i, data in enumerate(train_dataloader, 0):
img0, img1, label = data
img0, img1, label = Variable(img0).cuda(), Variable(img1).cuda(), Variable(label).cuda()
output1, output2 = net(img0, img1)
optimizer.zero_grad()
loss_contrastive = criterion(output1, output2, label)
loss_contrastive.backward()
optimizer.step()
if i % 10 == 0:
print("Epoch number {}\n Current loss {}\n".format(epoch, loss_contrastive.data[0]))
iteration_number = 10
counter.append(iteration_number)
loss_history.append(loss_contrastive.data[0])
show_plot(counter,loss_history)
4. Face verification supervised learning
通过孪生网络得到人脸特征向量之后,通过监督学习(同一个人标签为1,不是同一个人标签为0),学习人脸特征向量每一维的权重和偏置项b。
5. RankIQA
Xialei Liu等人[4]提出RankIQA模型来评估无参考图像的质量。之前的模型主要都是从提取特征和网络方面做改进,并没有考虑数据集图像少的问题。而RankIQA正是从数据预处理出发,取得了NR-IQA最好效果。 为了解决IQA数据集不足的问题,通过已知质量的图片使用图像处理变换生成不同级别不同类型的排序的失真图像。这些排序的图像集是自动生成的,而不用人工标注。这样就得到一个大数据集,然后就可以选择一个更宽更深的网络来训练。作者首先选择Siamese网络学习出生成数据排序关系的表示特征,然后将训练好的Siamese网络中表示的知识迁移到传统的CNN中,从而估算出单个图像的绝对图像质量。作者还改进了一个比传统Siamese网络更高效的反向传播算法:以前Siamese网络使用成对的样本训练网络,这样有大量样本有重复计算,现在所有样本只前向传播一次,统计出loss,然后计算梯度进行反向传播,这样得到更快的训练速度和更低的损失。作者实验了三个从浅到深的网络:Shallow,Alexnet,VGG16。Shallow包含4个卷积层和一个fc层,最后VGG16的结果最好。我们还可以训练测试一些更深的网络或者设计一些新网络。作者测试TID2013表明,RankIQA超过state-of-the-art 5%,并且在LIVE测试中,RankIQA优于现有的NR-IQA技术,甚至超越了FR-IQA方法的最新技术,从而无需参考图像就可以推断IQA。
参考资料:
[1] Learning a similarity metric discriminatively, with application to face verification
[2] Hamming Distance Metric Learning
[3] FaceNet: A Unified Embedding for Face Recognition and Clustering
[4] RankIQA: Learning from Rankings for No-reference Image Quality Assessment
[6] 详解Siamese网络
[7] 图像质量评估综述
[8] [CVPR2019]我对Siamese网络的一点思考(SiamMask)
学习资源: