Siamese Network(孪生神经网络)详解

 Siamese和Chinese有点像。Siam是古时候泰国的称呼,中文译作暹罗。Siamese也就是“暹罗”人或“泰国”人。Siamese在英语中是“孪生”、“连体”的意思,这是为什么呢?十九世纪泰国出生了一对连体婴儿,当时的医学技术无法使两人分离出来,于是两人顽强地生活了一生,1829年被英国商人发现,进入马戏团,在全世界各地表演,1839年他们访问美国北卡罗莱那州后来成为“玲玲马戏团” 的台柱,最后成为美国公民。1843年4月13日跟英国一对姐妹结婚,恩生了10个小孩,昌生了12个,姐妹吵架时,兄弟就要轮流到每个老婆家住三天。1874年恩因肺病去世,另一位不久也去世,两人均于63岁离开人间。两人的肝至今仍保存在费城的马特博物馆内。从此之后“暹罗双胞胎”(Siamesetwins)就成了连体人的代名词,也因为这对双胞胎让全世界都重视到这项特殊疾病。

简单来说,孪生神经网络(Siamese network)就是“连体的神经网络”,神经网络的“连体”是通过共享权值来实现的。所谓权值共享就是当神经网络有两个输入的时候,这两个输入使用的神经网络的权值是共享的(可以理解为使用了同一个神经网络)。很多时候,我们需要去评判两张图片的相似性,比如比较两张人脸的相似性,我们可以很自然的想到去提取这个图片的特征再进行比较,自然而然的,我们又可以想到利用神经网络进行特征提取。
如果使用两个神经网络分别对图片进行特征提取,提取到的特征很有可能不在一个域中,此时我们可以考虑使用一个神经网络进行特征提取再进行比较。这个时候我们就可以理解孪生神经网络为什么要进行权值共享了。

孪生神经网络有两个输入(Input1 and Input2),利用神经网络将输入映射到新的空间,形成输入在新的空间中的表示。通过Loss的计算,评价两个输入的相似度。

一、背景

在人脸识别中,存在所谓的one-shot问题。举例来说,就是对公司员工进行人脸识别,每个员工只给你一张照片(训练集样本少),并且员工会离职、入职(每次变动都要重新训练模型)。有这样的问题存在,就没办法直接训练模型来解决这样的分类问题了。为了解决one-shot问题,我们会训练一个模型来输出给定两张图像的相似度,所以模型学习得到的是similarity函数。哪些模型能通过学习得到similarity函数呢?Siamese网络就是这样的一种模型。

二、问题类型

主要解决以下两类分类问题:

第一类,分类数量较少,每一类的数据量较多,比如ImageNet、VOC等。这种分类问题可以使用神经网络或者SVM解决,只要事先知道了所有的类。
第二类,分类数量较多(或者说无法确认具体数量),每一类的数据量较少,比如人脸识别、人脸验证任务。

三、解决方法

将输入映射为一个特征向量,使用两个向量之间的“距离”(L1 Norm)来表示输入之间的差异(图像语义上的差距)。据此设计了Siamese Network。每次需要输入两个样本作为一个样本对计算损失函数。
1)用的softmax只需要输入一个样本。
2)FaceNet中的Triplet Loss需要输入三个样本。
提出了Contrastive Loss用于训练。

四、网络介绍

1、主干网络

孪生神经网络的主干特征提取网络的功能是进行特征提取,各种神经网络都可以适用,eg:VGG16 ,下图能反映VGG16结构特征:


1、一张原始图片被resize到指定大小,本文使用105x105。
2、conv1包括两次[3,3]卷积网络,一次2X2最大池化,输出的特征层为64通道。
3、conv2包括两次[3,3]卷积网络,一次2X2最大池化,输出的特征层为128通道。
4、conv3包括三次[3,3]卷积网络,一次2X2最大池化,输出的特征层为256通道。
5、conv4包括三次[3,3]卷积网络,一次2X2最大池化,输出的特征层为512通道。
6、conv5包括三次[3,3]卷积网络,一次2X2最大池化,输出的特征层为512通道。
实现代码:

import keras
from keras.layers import Input,Dense,Conv2D
from keras.layers import MaxPooling2D,Flatten
from keras.models import Model
import os
import numpy as np
from PIL import Image
from keras.optimizers import SGDclass VGG16:def __init__(self):self.block1_conv1 = Conv2D(64,(3,3),activation = 'relu',padding = 'same',name = 'block1_conv1')self.block1_conv2 = Conv2D(64,(3,3),activation = 'relu',padding = 'same', name = 'block1_conv2')self.block1_pool = MaxPooling2D((2,2), strides = (2,2), name = 'block1_pool')self.block2_conv1 = Conv2D(128,(3,3),activation = 'relu',padding = 'same',name = 'block2_conv1')self.block2_conv2 = Conv2D(128,(3,3),activation = 'relu',padding = 'same',name = 'block2_conv2')self.block2_pool = MaxPooling2D((2,2),strides = (2,2),name = 'block2_pool')self.block3_conv1 = Conv2D(256,(3,3),activation = 'relu',padding = 'same',name = 'block3_conv1')self.block3_conv2 = Conv2D(256,(3,3),activation = 'relu',padding = 'same',name = 'block3_conv2')self.block3_conv3 = Conv2D(256,(3,3),activation = 'relu',padding = 'same',name = 'block3_conv3')self.block3_pool = MaxPooling2D((2,2),strides = (2,2),name = 'block3_pool')self.block4_conv1 = Conv2D(512,(3,3),activation = 'relu',padding = 'same', name = 'block4_conv1')self.block4_conv2 = Conv2D(512,(3,3),activation = 'relu',padding = 'same', name = 'block4_conv2')self.block4_conv3 = Conv2D(512,(3,3),activation = 'relu',padding = 'same', name = 'block4_conv3')self.block4_pool = MaxPooling2D((2,2),strides = (2,2),name = 'block4_pool')# 第五个卷积部分self.block5_conv1 = Conv2D(512,(3,3),activation = 'relu',padding = 'same', name = 'block5_conv1')self.block5_conv2 = Conv2D(512,(3,3),activation = 'relu',padding = 'same', name = 'block5_conv2')self.block5_conv3 = Conv2D(512,(3,3),activation = 'relu',padding = 'same', name = 'block5_conv3')   self.block5_pool = MaxPooling2D((2,2),strides = (2,2),name = 'block5_pool')self.flatten = Flatten(name = 'flatten')def call(self, inputs):x = inputsx = self.block1_conv1(x)x = self.block1_conv2(x)x = self.block1_pool(x)x = self.block2_conv1(x)x = self.block2_conv2(x)x = self.block2_pool(x)x = self.block3_conv1(x)x = self.block3_conv2(x)x = self.block3_conv3(x)x = self.block3_pool(x)x = self.block4_conv1(x)x = self.block4_conv2(x)x = self.block4_conv3(x)x = self.block4_pool(x)x = self.block5_conv1(x)x = self.block5_conv2(x)x = self.block5_conv3(x)x = self.block5_pool(x)outputs = self.flatten(x)return outputs
2、比较网络

在获得主干特征提取网络之后,我们可以获取到一个多维特征,我们可以使用flatten的方式将其平铺到一维上,这个时候我们就可以获得两个输入的一维向量了,再将这两个一维向量进行相减,再进行绝对值求和,相当于求取了两个特征向量插值的L1范数。也就相当于求取了两个一维向量的距离。对这个距离再进行两次全连接,第二次全连接到一个神经元上,对这个神经元的结果取sigmoid,使其值在0-1之间,代表两个输入图片的相似程度。

实现代码如下:

import keras
from keras.layers import Input,Dense,Conv2D
from keras.layers import MaxPooling2D,Flatten,Lambda
from keras.models import Model
import keras.backend as K
import os
import numpy as np
from PIL import Image
from keras.optimizers import SGD
from nets.vgg import VGG16def siamese(input_shape):vgg_model = VGG16()input_image_1 = Input(shape=input_shape)input_image_2 = Input(shape=input_shape)encoded_image_1 = vgg_model.call(input_image_1)encoded_image_2 = vgg_model.call(input_image_2)l1_distance_layer = Lambda(lambda tensors: K.abs(tensors[0] - tensors[1]))l1_distance = l1_distance_layer([encoded_image_1, encoded_image_2])out = Dense(512,activation='relu')(l1_distance)out = Dense(1,activation='sigmoid')(out)model = Model([input_image_1,input_image_2],out)return model

五、网络结构

六、Contrastive Loss损失函数

在孪生神经网络(siamese network)中,其采用的损失函数是contrastive loss,这种损失函数可以有效的处理孪生神经网络中的paired data的关系。contrastive loss的表达式如下:

其中

代表两个样本特征X_{1}X_{2}的欧氏距离(二范数)P 表示样本的特征维数,Y 为两个样本是否匹配的标签,Y=1 代表两个样本相似或者匹配,Y=0 则代表不匹配,m 为设定的阈值,N 为样本个数。

观察上述的contrastive loss的表达式可以发现,这种损失函数可以很好的表达成对样本的匹配程度,也能够很好用于训练提取特征的模型。

①当 Y=1(即样本相似时),损失函数只剩下

即当样本不相似时,其特征空间的欧式距离反而小的话,损失值会变大,这也正好符号我们的要求。
②当 Y=0 (即样本不相似时),损失函数为

即当样本不相似时,其特征空间的欧式距离反而小的话,损失值会变大,这也正好符号我们的要求。
注意这里设置了一个阈值margin,表示我们只考虑不相似特征欧式距离在0~margin之间的,当距离超过margin的,则把其loss看做为0(即不相似的特征离的很远,其loss应该是很低的;而对于相似的特征反而离的很远,我们就需要增加其loss,从而不断更新成对样本的匹配程度)]

七、延伸

triplet loss 是深度学习的一种损失函数,主要是用于训练差异性小的样本,比如人脸等;其次在训练目标是得到样本的embedding任务中,triplet loss 也经常使用,比如文本、图片的embedding。

Siamese network是双胞胎连体,三胞胎连体叫Triplet network,论文是《Deep metric learning using Triplet network》,输入是三个,一个正例+两个负例,或者一个负例+两个正例,训练的目标是让相同类别间的距离尽可能的小,让不同类别间的距离尽可能的大。如果能把四胞胎整出来就好了。下图为三胞胎的图解:

参考文章链接:
孪生神经网络(Siamese Network)详解-CSDN博客
详解Siamese网络-CSDN博客
Siamese network 孪生神经网络--一个简单神奇的结构 - 知乎 (zhihu.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/746769.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端页面渲染机制

前端页面渲染机制是指在 web 开发中,浏览器如何将 HTML、CSS 和 JavaScript 转换为用户可视化的网页界面的过程。这个过程通常包括以下几个主要步骤: 加载 HTML: 首先,浏览器会获取 HTML 文件,并解析其结构。这个过程包括识别 HTM…

MySQL锁—全局锁、表级锁、行级锁详解

MySQL 锁 MySQL的锁按照锁的粒度可以分为全局锁、表级锁和行级锁。 一、全局锁 1. 概念 全局锁,是对整个数据库实例加锁,加锁后整个实例处于只读状态,后续的DML、DDL语句以及已经执行更新操作的事务提交语句都将被阻塞。 2. 应用场景 数据…

软件功能测试内容有哪些?湖南长沙软件测评公司分享

软件功能测试主要是验证软件应用程序的功能,且不管功能是否根据需求规范运行。是通过给出适当的输入值,确定输出并使用预期输出验证实际输出来测试每个功能。也可以看作“黑盒测试”,因为功能测试不用考虑程序内部结构和内部特性,…

MongoDB聚合运算符:$exp

文章目录 语法使用举例 $exp聚合运算符返回自然常数或欧拉数e的幂值&#xff08;次方&#xff09;的结果 语法 { $exp: <exponent> }<exponent>为指数&#xff0c;可以是任何数值表达式。 使用 如果参数为null或引用的字段不存在&#xff0c;$exp返回null&#…

【夏普利值——详细讲解】

夏普利值的介绍 沙普利值是合作博弈理论中的一个概念&#xff0c;由劳埃德-沙普利在1951年提出了这个概念&#xff0c;并因此在2012年获得了诺贝尔经济学奖。对于每个合作博弈&#xff0c;如联邦学习&#xff0c;可以将机构产生的模型的总提升在各个机构上形成一个有效的贡献分…

【iOS ARKit】PhysicsMotionComponent

使用 Physics BodyComponent 组件&#xff0c;通过设置物理参数、物理材质、施加作用力&#xff0c;能完全模拟物体在真实世界中的行为&#xff0c;这种方式的优点是遵循物理学规律、控制精确&#xff0c;但缺点是不直观。使用 PhysicsMotion Component组件则可以通过直接设置速…

Orange3数据预处理(清理特征组件)

清理特征 移除未使用的属性值和无用的属性&#xff0c;并对剩余的值进行排序。 输入 数据: 输入数据集 输出 数据: 过滤后的数据集 命名属性定义有时包含在数据中不出现的值。即使原始数据中没有这种情况&#xff0c;数据过滤、选择示例子集等操作也可能移除…

用python开发一个性能压测框架(超级简单)

用python开发一个性能压测框架&#xff08;超级简单&#xff09; 该框架是一个基础框架&#xff0c;超级简单&#xff0c;已经跑通&#xff0c;可以进行优化扩展 由于工作需要&#xff0c;最近开发了一款python性能压测框架&#xff0c;主要是对后端接口进行多线程压测 主要…

(二十五)Flask之MTVMVC架构模式Demo【重点:原生session使用及易错点!】

目录&#xff1a; 每篇前言&#xff1a;MTV&MVC构建一个基于MTV模式的Demo项目&#xff1a;蹦出一个问题&#xff1a; 每篇前言&#xff1a; &#x1f3c6;&#x1f3c6;作者介绍&#xff1a;【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领…

性能工具部署 - 自动在30多台机器上部署发流工具,并自动配置各自的参数,一键控制所有节点工具的启动、停止、重启

需求1&#xff1a;脚本快速上传文件到制定目录并解压 import paramiko import scp import os import pexpect# SSH连接信息 ssh_host 162.14.xx ssh_port 22 # 默认的SSH端口 ssh_username root # 登录用户名 ssh_password xx # 登录密码 sudo_password xx # 登录密码…

关于Transfomer的思考

为何诞生 在说transformer是什么&#xff0c;有什么优势之类的之前&#xff0c;先谈一谈它因何而诞生。transformer诞生最重要的原因是早先的语言模型&#xff0c;比如RNN&#xff0c;由于其本身的训练机制导致其并行度不高&#xff0c;特别是遇到一些长句子的情况下。其次&…

抖音开放平台第三方开发,实现代小程序备案申请

大家好&#xff0c;我是小悟 抖音小程序备案整体流程总共分为五个环节&#xff1a;备案信息填写、平台初审、工信部短信核验、通管局审核和备案成功。 服务商可以代小程序发起备案申请。在申请小程序备案之前&#xff0c;需要确保小程序基本信息已填写完成、小程序至少存在一个…

硬件笔记(26)---- 高速电路中滤波电容的选取

先要知道电容的等效电路 其中ESL取决于电容的类型和封装&#xff0c;一般用贴片陶瓷电容为例&#xff0c;对于直插式电解电容&#xff0c;他们的ESL很大。按下表&#xff0c;封装越大&#xff0c;ESL越大&#xff0c;但是0612有些例外 0612和1206就是 长短边的区别&#xff0c;…

什么是MVC三层结构

1.MVC&#xff08;三层结构&#xff09; MVC&#xff08;Model-View-Controller&#xff09;是一种常见的软件设计模式&#xff0c;用于将应用程序的逻辑和界面分离成三个不同的组件。每个组件负责特定的任务&#xff0c;从而提高代码的可维护性和可扩展性。 以前的模式。 遇到…

力扣_动态规划3—地下城游戏

题目 恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里&#xff0c;他必须穿过地下城并通过对抗恶魔来拯救公主。 骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻…

一文解读ISO26262安全标准:功能安全管理

一文解读ISO26262安全标准&#xff1a;功能安全管理 1 安全生命周期1.1 概念阶段1.2 产品开发阶段1.3 生产发布后续阶段 2 安全管理的角色和职责3 安全活动的裁剪4 安全活动的评审5 安全活动的评估6 交付物 下文的表中&#xff0c;一些方法的推荐等级说明&#xff1a; “”表示…

【网络安全渗透】常见文件上传漏洞处理与防范

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属的专栏&#xff1a;网络安全渗透 景天的主页&#xff1a;景天科技苑 文章目录 1.文件上传漏洞1.1. 描述1.2. 危害1.3. 有关文件上传的知识1.4…

【兔子机器人】修改GO、车轮电机ID(软件方法、硬件方法)以及修正VMC腿部初始化夹角

一、GO电机修改ID 1、硬件方法 利用上位机直接修改GO电机的id号&#xff1a; 打开调试助手&#xff0c;点击“调试”&#xff0c;查询电机&#xff0c;修改id号&#xff0c;即可。 但先将四个GO电机连接线拔掉&#xff0c;不然会将连接的电机一并修改。 利用24V电源给GO电机…

Java_12 杨辉三角 II

杨辉三角 II 给定一个非负索引 rowIndex&#xff0c;返回「杨辉三角」的第 rowIndex 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: rowIndex 3 输出: [1,3,3,1] 示例 2: 输入: rowIndex 0 输出: [1] 示例 3: 输入: rowIndex 1 输…

【应急响应靶场web2】

文章目录 前言 一、应急响应 1、背景 2、webshell查杀 3、日志排查 1&#xff09;apache日志 2&#xff09;nginx日志 3&#xff09;ftp日志 4、隐藏账户 5、文件筛选 二、漏洞复现 总结 前言 靶场来源&#xff1a;知攻善防实验室 一、应急响应 1、背景 小李在某…