欢迎访问个人网络日志🌹🌹知行空间🌹🌹
孪生神经网络介绍及pytorch实现
*
– 1.孪生神经网络
– 2.孪生神经网络的损失函数
– 2.1 Triplet Loss
– 2.2 Contrastive Loss
– 3.动手实现一个孪生网络
–
+ 3.1 网络结构
+ 3.2 损失函数
+ 3.3 数据
+ 3.4 训练结果
– 4.SiameseNetWork的一些应用
– 参考资料
1.孪生神经网络
在深度学习领域,神经网络取得了成功。但普通的神经网络模型的训练需要大量的数据,对于一些数据有限的场景,如人脸验证,签字验证,必须考虑其他方法。
Siamese
古语表示 瞿罗
,即现在的泰国,如 Siamese cat
,之所以 Siamese
表示孪生,是因为19世纪 瞿罗
出了一对连体双胞胎,在 美国玲玲马戏团
做演出比较出名,因此提起 Siamese
即表示孪生的意思。1
孪生神经网络 Siamese Network
,如其名字 孪生Siamese
的意思即存在连体,连体即彼此共享一部分。孪生神经网络的结构也包括两个子网络,两个子网络之间共享权重。
图片来自于1
如上图,两个网络是同一个并共享权重,当两个子网络不共享权重时,通常定义为 伪孪生神经网络
。
图片来自于1
从上面的图中可以看出来,孪生神经网络有两个输入, input1
和 input2
,因此孪生神经网络常用来通过比较两个输入特征向量的距离来衡量两个输入的相似度。早在 1993
年的 NIPS
上 Yann Lecun
就发表了使用孪生神经网络做签名验证的论文。现在的人脸识别应用也有基于孪生神经来做的。
孪生神经网络的优点,对于类别不平衡问题更鲁棒,更易于做集成学习(Ensemble Learning),可以从语义相似性上学习来估测两个输入的距离。 孪生神经网络的缺点,由于有两个输入,两个子网,其训练相对于常规网络运算量更大,需要的时间更长。输出的结果不是概率,孪生神经网络时成对的输入,其输出是两个类间的距离而不是概率。
; 2.孪生神经网络的损失函数
由与孪生神经网络是计算的两个输入的相似度,距离,而不是对输入做分类,因此 交叉商损失函数
不适用于此种场景, 孪生神经网络的
常用的损失函数有 Triplet Loss
和 Contrastive Loss
。
2.1 Triplet Loss
Triplet Loss
三元组损失函数,其应用见谷歌 2015
年发表在 CVPR
上的做人脸验证的论文 facenet
。该损失函数定义一个三元组作为输入,分别是( X a n c h o r , X p o s i t i v e , X n e g a t i v e ) (X_{anchor},X_{positive},X_{negative})(X a n c h o r ,X p o s i t i v e ,X n e g a t i v e )这三个输入的通过如下方式构成,先从训练数据集中随机选一个样本作为 Anchor
,再随机选取一个和 Anchor
属于同一类的样本作为正样本X p o s i t i v e X_{positive}X p o s i t i v e ,和一个不同类的样本作为负样本X n e g a t i v e X_{negative}X n e g a t i v e ,通过这种方式定义一个输入的三元组( X a n c h o r , X p o s i t i v e , X n e g a t i v e ) (X_{anchor},X_{positive},X_{negative})(X a n c h o r ,X p o s i t i v e ,X n e g a t i v e ),将其输入到网络可以得到对应的特征向量[ f ( X a n c h o r ) , f ( X p o s i t i v e ) , f ( X n e g a t i v e ) ] [f(X_{anchor}),f(X_{positive}),f(X_{negative})][f (X a n c h o r ),f (X p o s i t i v e ),f (X n e g a t i v e )], Triplet Loss
的目的是通过训练,使得同种类别的距离更近,不通类别的距离更大,即 拉近anchor与positive推远anchor和negative,如下图:
图片来自FaceNet论文
通过这种相似度比较式的学习,模型不仅与同类别更像,还学会了与不同类别增大区分度的信息。通常定义一个α \alpha α,使得 Anchor
距离 Negative
的距离比距离 Positive
大α \alpha α,公式化表示为:
∣ ∣ f ( X a n c h o r ) − f ( X n e g a t i v e ) ∣ ∣ − ∣ ∣ f ( X a n c h o r ) − f ( X p o s i t i v e ) ∣ ∣ > α ||f(X_{anchor}) – f(X_{negative})|| – ||f(X_{anchor}) – f(X_{positive})|| \gt \alpha ∣∣f (X a n c h o r )−f (X n e g a t i v e )∣∣−∣∣f (X a n c h o r )−f (X p o s i t i v e )∣∣>α
定义为:
L ( X a n c h o r , X p o s i t i v e , X n e g a t i v e ) = m a x ( ∣ ∣ f ( X a n c h o r ) − f ( X p o s i t i v e ) ∣ ∣ − ∣ ∣ f ( X a n c h o r ) − f ( X n e g a t i v e ) ∣ ∣ + α , 0 ) L(X_{anchor}, X_{positive}, X_{negative}) = max(||f(X_{anchor}) – f(X_{positive})|| – ||f(X_{anchor}) – f(X_{negative})|| + \alpha, 0)L (X a n c h o r ,X p o s i t i v e ,X n e g a t i v e )=m a x (∣∣f (X a n c h o r )−f (X p o s i t i v e )∣∣−∣∣f (X a n c h o r )−f (X n e g a t i v e )∣∣+α,0 )
; 2.2 Contrastive Loss
衡量相似度的另一常用函数是 Yann Lecun
在 2005
年的一篇论文Dimensionality Reduction by Learning an Invariant Mapping中使用的 Contrastive Loss
。
Contrastive Loss
的输入是一对样本,基于相似的一对对象特征距离应该更小,不相似的一对对象特征距离应该较大来计算。从数据中选一对样本( X a , X b ) (X_a, X_b)(X a ,X b ),这两个样本的 欧式距离表示为d = ∣ ∣ X a − X b ∣ ∣ 2 = ( X a − X b ) 2 d=||X_a-X_b||_2=\sqrt{({X_a-X_b})^2}d =∣∣X a −X b ∣∣2 =(X a −X b )2 ,则 Contrastive Loss
可表示为:
L ( X a , X b ) = ( 1 − Y ) 1 2 d 2 + Y 1 2 { m a x ( 0 , m − d ) } 2 L(X_a,X_b) = (1-Y)\frac{1}{2}d^2 + Y\frac{1}{2}{max(0, m-d)}^2 L (X a ,X b )=(1 −Y )2 1 d 2 +Y 2 1 {m a x (0 ,m −d )}2
Y
表示( X a , X b ) (X_a,X_b)(X a ,X b )是否匹配,匹配为1
不匹配为0
m
是设置的安全距离
,当( X a , X b ) (X_a, X_b)(X a ,X b )的距离小于m m m时,Contrasive Loss
将变成0
,这使得X a X_a X a 与X b X_b X b 相似而不是相同,能保证算法的泛化能力
3.动手实现一个孪生网络
3.1 网络结构
这里使用 Contrasive Loss
定义一个孪生神经网络,网络结构如图:
这里上下两个网络使用同一个网络来实现,对于两个输入,每一步推理使用相同的权重 forward
两次,然后计算损失函数更新权重,这里并没有定义两个网络。为了简化训练,自定义了比较小的网络
class SiameseNetwork(nn.Module):
"""Custom Siamese Network
"""
def __init__(self):
super(SiameseNetwork, self).__init__()
self.cnn = nn.Sequential(
nn.Conv2d(1, 128, kernel_size=5, stride=3, padding=2),
nn.ReLU(inplace=True),
nn.LocalResponseNorm(5, alpha=0.001, beta=.75, k=2),
nn.MaxPool2d(4, stride=2),
nn.Dropout2d(p=.5),
)
self.fc = nn.Sequential(
nn.Linear(2048, 512),
nn.ReLU(inplace=True),
nn.Dropout2d(p=0.5),
nn.Linear(512, 128),
nn.ReLU(inplace=True),
nn.Linear(128, 2)
)
def forward_once(self, x):
y = self.cnn(x)
y = y.view(y.size()[0], -1)
y = self.fc(y)
return y
def forward(self, x1, x2):
y1 = self.forward_once(x1)
y2 = self.forward_once(x2)
return y1, y2
3.2 损失函数
损失函数使用的是前述的 Contrastive Loss
,其定义为:
class ContrastiveLoss(torch.nn.Module):
def __init__(self, margin):
super(ContrastiveLoss, self).__init__()
self.margin = margin
def forward(self, x1, x2, y):
dist = F.pairwise_distance(x1, x2)
total_loss = (1-y) * torch.pow(dist, 2) + \
y * torch.pow(torch.clamp_min_(self.margin - dist, 0), 2)
loss = torch.mean(total_loss)
return loss
3.3 数据
这里使用的是基于 MNIST
数据集随机选取的 1000
张图像然后生成了 8000
对作为输入来训练的,测试时输入两张手写字图片输出其相似度。
3.4 训练结果
训练了 20
个 epoch
,损失函数值的变化趋势如下图:
由于使用的 batch_size
较小,迭代的次数较少,可以看到损失函数没有很好的收敛。且打开训练数据看了下自己生成的 train.csv
中的图像对,绝大部分 label
都是 0
,存在严重的数据不平衡问题,需要改进。在测试数据上的输出,对于有些输入可以比较好的衡量其相似度。
Predicted Distance: 0.0020178589038550854
Actual Label: Different Signature
Predicted Distance: 0.0002805054828058928
Actual Label: Same Signature
Predicted Distance: 0.003011130029335618
Actual Label: Different Signature
Predicted Distance: 0.0018709745490923524
Actual Label: Different Signature
完整代码见gitee仓库
4.SiameseNetWork的一些应用
1.签名验证Signature Verification using a “Siamese”
Time Delay Neural Network
2.三胞胎网络Deep metric learning using Triplet network
3.One-ShotLearning, Siamese Neural Networks for One-shot Image Recognition
4.人脸验证Learning a Similarity Metric Discriminatively, with Application to Face
Verification
参考资料
- 1.Siamese network 孪生神经网络–一个简单神奇的结构
- 2.FaceNet
- 3.Contrastive Loss
- 4.A friendly introduction to Siamese Networks
欢迎访问个人网络日志🌹🌹知行空间🌹🌹
Original: https://blog.csdn.net/lx_ros/article/details/124439120
Author: 恒友成
Title: (四)孪生神经网络介绍及pytorch实现
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/646521/
转载文章受原作者版权保护。转载请注明原作者出处!