(四)孪生神经网络介绍及pytorch实现


欢迎访问个人网络日志🌹🌹知行空间🌹🌹


1.孪生神经网络

在深度学习领域,神经网络取得了成功。但普通的神经网络模型的训练需要大量的数据,对于一些数据有限的场景,如人脸验证,签字验证,必须考虑其他方法。

Siamese 古语表示瞿罗,即现在的泰国,如Siamese cat,之所以Siamese表示孪生,是因为19世纪瞿罗出了一对连体双胞胎,在美国玲玲马戏团做演出比较出名,因此提起Siamese即表示孪生的意思。1

孪生神经网络Siamese Network,如其名字孪生Siamese的意思即存在连体,连体即彼此共享一部分。孪生神经网络的结构也包括两个子网络,两个子网络之间共享权重。

> 图片来自于1

在这里插入图片描述

如上图,两个网络是同一个并共享权重,当两个子网络不共享权重时,通常定义为伪孪生神经网络

图片来自于1

在这里插入图片描述

从上面的图中可以看出来,孪生神经网络有两个输入,input1input2,因此孪生神经网络常用来通过比较两个输入特征向量的距离来衡量两个输入的相似度。早在1993年的NIPSYann Lecun就发表了使用孪生神经网络做签名验证的论文。现在的人脸识别应用也有基于孪生神经来做的。

孪生神经网络的优点,对于类别不平衡问题更鲁棒,更易于做集成学习(Ensemble Learning),可以从语义相似性上学习来估测两个输入的距离。孪生神经网络的缺点,由于有两个输入,两个子网,其训练相对于常规网络运算量更大,需要的时间更长。输出的结果不是概率,孪生神经网络时成对的输入,其输出是两个类间的距离而不是概率。

2.孪生神经网络的损失函数

由与孪生神经网络是计算的两个输入的相似度,距离,而不是对输入做分类,因此交叉商损失函数不适用于此种场景,孪生神经网络的常用的损失函数有Triplet LossContrastive 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}) (Xanchor,Xpositive,Xnegative)这三个输入的通过如下方式构成,先从训练数据集中随机选一个样本作为Anchor,再随机选取一个和Anchor属于同一类的样本作为正样本 X p o s i t i v e X_{positive} Xpositive,和一个不同类的样本作为负样本 X n e g a t i v e X_{negative} Xnegative,通过这种方式定义一个输入的三元组 ( 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}) (Xanchor,Xpositive,Xnegative),将其输入到网络可以得到对应的特征向量 [ 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(Xanchor),f(Xpositive),f(Xnegative)],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(Xanchor)f(Xnegative)f(Xanchor)f(Xpositive)>α

定义为:

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(Xanchor,Xpositive,Xnegative)=max(f(Xanchor)f(Xpositive)f(Xanchor)f(Xnegative)+α,0)

2.2 Contrastive Loss

衡量相似度的另一常用函数是Yann Lecun2005年的一篇论文Dimensionality Reduction by Learning an Invariant Mapping中使用的Contrastive Loss

Contrastive Loss的输入是一对样本,基于相似的一对对象特征距离应该更小,不相似的一对对象特征距离应该较大来计算。从数据中选一对样本 ( X a , X b ) (X_a, X_b) (Xa,Xb),这两个样本的欧式距离表示为 d = ∣ ∣ X a − X b ∣ ∣ 2 = ( X a − X b ) 2 d=||X_a-X_b||_2=\sqrt{({X_a-X_b})^2} d=XaXb2=(XaXb)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(Xa,Xb)=(1Y)21d2+Y21{max(0,md)}2

  • Y表示 ( X a , X b ) (X_a,X_b) (Xa,Xb)是否匹配,匹配为1不匹配为0

  • m是设置的安全距离,当 ( X a , X b ) (X_a, X_b) (Xa,Xb)的距离小于 m m m时,Contrasive Loss将变成0,这使得 X a X_a Xa X b X_b Xb相似而不是相同,能保证算法的泛化能力

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), # 10
            nn.ReLU(inplace=True),
            nn.LocalResponseNorm(5, alpha=0.001, beta=.75, k=2), # TODO
            nn.MaxPool2d(4, stride=2), # 4
            nn.Dropout2d(p=.5),          
        ) # 12544
        
        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 训练结果

训练了20epoch,损失函数值的变化趋势如下图:

在这里插入图片描述

由于使用的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

参考资料


欢迎访问个人网络日志🌹🌹知行空间🌹🌹


  • 23
    点赞
  • 156
    收藏
    觉得还不错? 一键收藏
  • 19
    评论
### 回答1: 孪生神经网络是一种用于处理成对数据的深度学习模型,在pytorch中也提供了相关的工具和库以支持该模型的实现和训练。 孪生神经网络主要用于比较两个输入之间的相似性或差异性,常用于人脸识别、语义匹配等任务。其基本原理是通过对两个相似或相关的输入进行编码,然后将编码结果输入到一个共享的神经网络结构中,最后通过比较这两个编码结果来判断它们的相似程度。 在pytorch中,我们可以使用nn.Module和nn.ModuleList来定义其中的神经网络组件。首先,我们可以定义一个编码器网络结构,将输入数据进行特征提取和编码。然后,我们可以使用nn.CosineSimilarity或nn.PairwiseDistance等函数来计算两个编码结果之间的相似性或差异性。最后,我们可以根据实际任务需求和损失函数来设计网络结构。 在训练孪生神经网络时,我们需要准备一对成对的训练样本,例如一对相似的人脸图像或文本语义匹配的句子。然后,我们可以将这一对训练样本输入到孪生神经网络中进行训练,通过最小化损失函数来优化网络参数。常见的损失函数包括对比损失(Contrastive Loss)、三元组损失(Triplet Loss)等。 总之,孪生神经网络pytorch中的实现相对简单,可以通过定义编码器网络结构、选择合适的相似性度量函数和损失函数来实现对成对数据的相似性或差异性比较。这为深度学习任务中的人脸识别、语义匹配等问题提供了一种强大的解决方法。 ### 回答2: 孪生神经网络是一种用于处理具有相似性的数据对的深度学习模型。它由两个相同结构的神经网络组成,其中一个网络作为“锚”网络,另一个网络作为“目标”网络。通过训练这两个网络,使它们能够学习到数据对之间的相似性。 PyTorch是一种基于Python的开源深度学习框架,提供了丰富的工具和接口,使得构建和训练神经网络变得更加简单和高效。 使用PyTorch进行孪生神经网络实现通常包括以下几个步骤: 1. 构建网络结构:首先,定义神经网络的结构。可以使用PyTorch提供的各种层和模块来构建网络,如全连接层、卷积层和池化层等。 2. 定义损失函数:为了训练网络,需要定义一个损失函数。对于孪生神经网络来说,常用的损失函数有对比损失和三元组损失等。这些损失函数可以通过PyTorch提供的函数来定义和计算。 3. 训练网络:使用训练数据对网络进行训练。在每个训练批次中,将数据对输入到网络中,计算损失值并进行反向传播,更新网络参数。可以使用PyTorch提供的优化器来自动更新参数。 4. 测试网络:在训练完成后,可以使用测试数据对网络进行评估。将数据对输入到网络中,得到输出并进行相似性判断。根据具体的任务和需求,可以使用不同的评估指标来衡量网络的性能。 总的来说,使用PyTorch实现孪生神经网络可以更方便地构建和训练模型,而且PyTorch的灵活性和可扩展性也使得对于不同任务的定制化变得更加容易。 ### 回答3: 孪生神经网络是一种基于对比学习的神经网络模型,其中包含两个相同结构的子网络,其目的是应用于匹配或对比任务。通过孪生神经网络,我们可以输入两个相似或相关的实例,然后通过网络的学习来比较和分析它们之间的相似度或差异。 PyTorch是一个开源的深度学习框架,它提供了广泛的工具和库,用于快速、灵活地构建和训练神经网络模型。PyTorch具有方便的动态计算图,使得模型的构建和调试更加直观和灵活,同时也具有良好的性能和可扩展性。 使用PyTorch可以很方便地构建和训练孪生神经网络模型。我们可以通过定义两个相同结构的子网络,然后将它们作为孪生神经网络的组成部分。在训练过程中,我们可以利用对比损失函数来度量和优化两个实例的相似性。 PyTorch提供了丰富的神经网络层和损失函数,可以用于构建孪生神经网络模型。我们可以使用卷积神经网络(CNN)或递归神经网络(RNN)等常见的网络结构,根据任务的需求选择合适的网络层和激活函数。同时,PyTorch还支持各种常见的对比损失函数,如欧氏距离、余弦相似度等,以及其他自定义的损失函数。 总之,PyTorch提供了便捷的工具和库,使得构建和训练孪生神经网络模型变得更加简单和高效。通过其丰富的功能和友好的接口,我们可以快速实现孪生神经网络模型,并在各种匹配或对比任务中取得好的性能。
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值