神经网络学习小记录53——TF2搭建孪生神经网络(Siamese network)比较图片相似性

2023-11-05

学习前言

实现一下TF2版本的孪生神经网络。
在这里插入图片描述

什么是孪生神经网络

简单来说,孪生神经网络(Siamese network)就是“连体的神经网络”,神经网络的“连体”是通过共享权值来实现的,如下图所示。
在这里插入图片描述
所谓权值共享就是当神经网络有两个输入的时候,这两个输入使用的神经网络的权值是共享的(可以理解为使用了同一个神经网络)。

很多时候,我们需要去评判两张图片的相似性,比如比较两张人脸的相似性,我们可以很自然的想到去提取这个图片的特征再进行比较,自然而然的,我们又可以想到利用神经网络进行特征提取

如果使用两个神经网络分别对图片进行特征提取,提取到的特征很有可能不在一个域中,此时我们可以考虑使用一个神经网络进行特征提取再进行比较。这个时候我们就可以理解孪生神经网络为什么要进行权值共享了。

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

代码下载

https://github.com/bubbliiiing/Siamese-tf2

孪生神经网络的实现思路

一、预测部分

1、主干网络介绍

在这里插入图片描述
孪生神经网络的主干特征提取网络的功能是进行特征提取,各种神经网络都可以适用,本文使用的神经网络是VGG16。
关于VGG的介绍大家可以看我的另外一篇博客https://blog.csdn.net/weixin_44791964/article/details/102779878
在这里插入图片描述
这是一个VGG被用到烂的图,但确实很好的反应了VGG的结构:
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 os
import numpy as np
from tensorflow.keras.layers import Input,Dense,Conv2D
from tensorflow.keras.layers import MaxPooling2D,Flatten,Lambda
from tensorflow.keras.models import Model
from PIL import Image

class 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 = inputs
        x = 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 os
import numpy as np
import tensorflow.keras.backend as K
from PIL import Image
from nets.vgg import VGG16
from tensorflow.keras.layers import Input,Dense,Conv2D
from tensorflow.keras.layers import MaxPooling2D,Flatten,Lambda
from tensorflow.keras.models import Model
 
def 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

二、训练部分

1、数据集的格式

本文所使用的数据集为Omniglot数据集。
其包含来自 50不同字母(语言)的1623 个不同手写字符。每一个字符都是由 20个不同的人通过亚马逊的 Mechanical Turk 在线绘制的。

相当于每一个字符有20张图片,然后存在1623个不同的手写字符,我们需要利用神经网络进行学习,去区分这1623个不同的手写字符,比较输入进来的字符的相似性。

本博客中数据存放格式有三级:

- image_background
	- Alphabet_of_the_Magi
		- character01
			- 0709_01.png
			- 0709_02.png
			- ……
		- character02
		- character03
		- ……
	- Anglo-Saxon_Futhorc
	- ……

最后一级的文件夹用于分辨不同的字体,同一个文件夹里面的图片属于同一文字。在不同文件夹里面存放的图片属于不同文字。
在这里插入图片描述
在这里插入图片描述
上两个图为.\images_background\Alphabet_of_the_Magi\character01里的两幅图。它们两个属于同一个字。
在这里插入图片描述
上一个图为.\images_background\Alphabet_of_the_Magi\character02里的一幅图。它和上面另两幅图不属于同一个字。

2、Loss计算

对于孪生神经网络而言,其具有两个输入。

当两个输入指向同一个类型的图片时,此时标签为1。

当两个输入指向不同类型的图片时,此时标签为0。

然后将网络的输出结果和真实标签进行交叉熵运算,就可以作为最终的loss了。

本文所使用的Loss为binary_crossentropy。

当我们输入如下两个字体的时候,我们希望网络的输出为1。
在这里插入图片描述
在这里插入图片描述
我们会将预测结果和1求交叉熵。

当我们输入如下两个字体的时候,我们希望网络的输出为0。
在这里插入图片描述
在这里插入图片描述
我们会将预测结果和0求交叉熵。

训练自己的孪生神经网络

1、训练本文所使用的Omniglot例子

在这里插入图片描述
下载数据集,放在根目录下的dataset文件夹下。
在这里插入图片描述
运行train.py开始训练。
在这里插入图片描述

2、训练自己相似性比较的模型

如果大家想要训练自己的数据集,可以将数据集按照如下格式进行摆放。
在这里插入图片描述
每一个chapter里面放同类型的图片。
之后将train.py当中的train_own_data设置成True,即可开始训练。
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

神经网络学习小记录53——TF2搭建孪生神经网络(Siamese network)比较图片相似性 的相关文章

随机推荐

  • Android:rk3588 kernel单编

    Android12 0不能直接烧写kernel img和resource img Android12 0的kernel img和resource img包含在boot img中 需要使用build sh AK 命令来编译 kernel 编译
  • 【问题解决】Java下载远程服务器资源到本地,本地提供下载服务,解决中文乱码问题

    Java下载远程服务器资源到本地 本地提供下载服务 1 通过远程访问远程URL获取服务资源 从指定URL下载文件并保存到指定目录 param filePath 文件将要保存的目录 param method 请求方法 包括POST和GET p
  • 计算机视觉OpenCV(四):图像梯度处理和边缘检测

    目录 图像梯度处理 1 Sobel算子 2 Scharr算子 3 Laplacian算子 4 不同算子的比较 Canny边缘检测 图像梯度处理 1 Sobel算子 dst cv2 Sobel src ddepth dx dy ksize d
  • windows7 64位机上安装配置CUDA7.5(或8.0)+cudnn5.0操作步骤

    按照官网文档 http docs nvidia com cuda cuda installation guide microsoft windows index html axzz4TpI4c8vf 进行安装 在windows7上安装cud
  • Python中自定义异常

    Python中也有关于异常的处理 导入日志模块 import logging sys 导入logging模块 logger logging getLogger 异常 创建一个logger实例 filehadler logging FileH
  • Spring Security 强制退出指定用户

    应用场景 最近社区总有人发文章带上小广告 严重影响社区氛围 好气 对于这种类型的用户 就该永久拉黑 社区的安全框架使用了 spring security 和 spring session 登录状态 30 天有效 session 信息是存在
  • 聚观早报

    今日要闻 ChatGPT 停止 Plus 付费 李子柒油管广告收益登顶热搜 亚马逊游戏部门百名员工被裁 国内一公司推出太空葬 苹果将在印度国金融中心开设零售店 ChatGPT 停止 Plus 付费 4 月 5 日消息 ChatGPT 目前已
  • 景安服务器可以用小程序吗,原来这些平台都有小程序,你全都用过吗?

    原标题 原来这些平台都有小程序 你全都用过吗 11大平台入局 小程序日活超4 4亿 陶风互联觉得 小程序用数据证明了自己的繁荣与能力 近日 小程序SaaS服务商 即速应用发布的 即速应用2020小程序年中研究分析报告 让我们再窥小程序对于互
  • Java与MySQL时间不一致问题

    文章目录 一 问题情况描述 二 CST时区混乱 1 CST有四种含义 2 什么是时区 三 绝对时间与本地时间 1 绝对时间 2 本地时间 3 时区偏移量 四 MySQL服务端时区 1 system time zone 系统时区 2 time
  • 电路设计中的磁珠作用及如何进行取值!!!!!

    PS 先品尝一下小菜 关于磁珠的使用描述不正确的是 A 磁珠的阻抗频率特性曲线 转换点频率以下 以磁珠体现电阻性 转换点所在频率以上 磁珠体现电感性 电感性的作用是反射噪声 电阻性的作用是吸收噪声并转换成热能 B 磁珠的选择应满足电路噪声的
  • QT生成XML(QXmlStreamWriter或DOM)

    话不多说 直接而看代码 效果可以自己运行看看 记得在Pro文件里加上xml模块 方式一 QXmlStreamWriter QString sXml 存储生成的XML QXmlStreamWriter xswWriter sXml xswWr
  • go语言基础-----20-----TCP网络编程

    1 网络编程介绍 目前主流服务器一般均采用的都是 Non Block I O多路复用 有的也结合了多线程 多进程 不过I O多路复用也给使用者带来了不小的复杂度 以至于后续出现了许多高性能的I O多路复用框架 比如libevent libe
  • No Feign Client for loadBalancing defined.错误

    SpringCloud OpenFeign报错 No Feign Client for loadBalancing defined Did you forget to include spring cloud starter loadbal
  • 《黑马程序员MySQL数据库入门到精通,从mysql安装到mysql高级、mysql优化》学习笔记总目录

    本文是对 黑马程序员MySQL数据库入门到精通 从mysql安装到mysql高级 mysql优化 所有知识点的笔记进行总结分类 学习视频 黑马程序员MySQL 学习时总结的目录笔记以及思维导图和实训 可通过点击以下链接 并输入提取码 M2S
  • 可重入锁的概念及使用场景

    在java中我们听过或者用过的锁有很多种 公平锁 非公平锁 可重入锁 不可重入锁 共享锁 排他锁 乐观锁 悲观锁 偏向锁 轻量级锁 重量级锁 其实这些都是在不同维度或者锁优化角度对锁的一种叫法 我们在程序中用到的也就那么几种 比如synch
  • js定时器单次执行、循环执行

    1 定时器定义 定时器 用以指定在一段特定的时间后执行某段程序 2 定时器应用 设置只执行一次的定时器 window setTimeout send 1000 设置重复执行的定时器 self setInterval send 8 1000
  • 新手购买了服务器怎么进入

    服务器一般是远程控制进行操作使用 通过服务器远程软件填写服务器IP 端口 用户名及其密码或授权文件进行访问 还可分为桌面图形版和命令行窗口版 对于Linux服务器专业人员来说 使用命令行窗口版较多 基本上的控制是使用命令行操作即可 当然啦
  • linux下宽字符文件, Linux上 wfopen(打开宽字符版的文件名和模式)的实现 (**)

    目录 linux下宽字符文件 Linux上wfopen 打开宽字符版的文件名和模式 的实现 https blog csdn net ken2232 article details 130316198 QString toWCharArray
  • 数字基带信号(主要涉及基带编码、传输系统)

    一 数字基带信号 1 数字基带信号 所谓数字基带信号 就是消息代码的电波形 数字基带信号的类型很多 本节以由矩形脉冲构成的基带信号为例 主要研究这些基带信号的时域波形 频谱波形以及功率谱密度波形 remark 信息是非实体 信源的信息必须外
  • 神经网络学习小记录53——TF2搭建孪生神经网络(Siamese network)比较图片相似性

    神经网络学习小记录53 TF2搭建孪生神经网络 Siamese network 比较图片相似性 学习前言 什么是孪生神经网络 代码下载 孪生神经网络的实现思路 一 预测部分 1 主干网络介绍 2 比较网络 二 训练部分 1 数据集的格式 2