欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Keras搭建孿生神經(jīng)網(wǎng)絡(luò)Siamese?network比較圖片相似性

 更新時間:2022年05月07日 14:59:47   作者:Bubbliiiing  
這篇文章主要為大家介紹了Keras搭建孿生神經(jīng)網(wǎng)絡(luò)Siamese?network比較圖片相似性,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

什么是孿生神經(jīng)網(wǎng)絡(luò)

最近學(xué)習(xí)了一下如何比較兩張圖片的相似性,用到了孿生神經(jīng)網(wǎng)絡(luò),一起來學(xué)習(xí)一下。

簡單來說,孿生神經(jīng)網(wǎng)絡(luò)(Siamese network)就是“連體的神經(jīng)網(wǎng)絡(luò)”,神經(jīng)網(wǎng)絡(luò)的“連體”是通過共享權(quán)值來實(shí)現(xiàn)的,如下圖所示。

所謂權(quán)值共享就是當(dāng)神經(jīng)網(wǎng)絡(luò)有兩個輸入的時候,這兩個輸入使用的神經(jīng)網(wǎng)絡(luò)的權(quán)值是共享的(可以理解為使用了同一個神經(jīng)網(wǎng)絡(luò))。

很多時候,我們需要去評判兩張圖片的相似性,比如比較兩張人臉的相似性,我們可以很自然的想到去提取這個圖片的特征再進(jìn)行比較,自然而然的,我們又可以想到利用神經(jīng)網(wǎng)絡(luò)進(jìn)行特征提取。

如果使用兩個神經(jīng)網(wǎng)絡(luò)分別對圖片進(jìn)行特征提取,提取到的特征很有可能不在一個域中,此時我們可以考慮使用一個神經(jīng)網(wǎng)絡(luò)進(jìn)行特征提取再進(jìn)行比較。

這個時候我們就可以理解孿生神經(jīng)網(wǎng)絡(luò)為什么要進(jìn)行權(quán)值共享了。

孿生神經(jīng)網(wǎng)絡(luò)有兩個輸入(Input1 and Input2),利用神經(jīng)網(wǎng)絡(luò)將輸入映射到新的空間,形成輸入在新的空間中的表示。通過Loss的計算,評價兩個輸入的相似度。

代碼下載

孿生神經(jīng)網(wǎng)絡(luò)的實(shí)現(xiàn)思路

一、預(yù)測部分

1、主干網(wǎng)絡(luò)介紹

孿生神經(jīng)網(wǎng)絡(luò)的主干特征提取網(wǎng)絡(luò)的功能是進(jìn)行特征提取,各種神經(jīng)網(wǎng)絡(luò)都可以適用,本文使用的神經(jīng)網(wǎng)絡(luò)是VGG16。關(guān)于VGG的介紹大家可以看我的另外一篇博客

http://www.dbjr.com.cn/article/246968.htm

這是一個VGG被用到爛的圖,但確實(shí)很好的反應(yīng)了VGG的結(jié)構(gòu):

1、一張原始圖片被resize到指定大小,本文使用105x105。

2、conv1包括兩次[3,3]卷積網(wǎng)絡(luò),一次2X2最大池化,輸出的特征層為64通道。

3、conv2包括兩次[3,3]卷積網(wǎng)絡(luò),一次2X2最大池化,輸出的特征層為128通道。

4、conv3包括三次[3,3]卷積網(wǎng)絡(luò),一次2X2最大池化,輸出的特征層為256通道。

5、conv4包括三次[3,3]卷積網(wǎng)絡(luò),一次2X2最大池化,輸出的特征層為512通道。

6、conv5包括三次[3,3]卷積網(wǎng)絡(luò),一次2X2最大池化,輸出的特征層為512通道。

實(shí)現(xiàn)代碼為:

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 SGD
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、比較網(wǎng)絡(luò)

在獲得主干特征提取網(wǎng)絡(luò)之后,我們可以獲取到一個多維特征,我們可以使用flatten的方式將其平鋪到一維上,這個時候我們就可以獲得兩個輸入的一維向量了

將這兩個一維向量進(jìn)行相減,再進(jìn)行絕對值求和,相當(dāng)于求取了兩個特征向量插值的L1范數(shù)。也就相當(dāng)于求取了兩個一維向量的距離。

然后對這個距離再進(jìn)行兩次全連接,第二次全連接到一個神經(jīng)元上,對這個神經(jīng)元的結(jié)果取sigmoid,使其值在0-1之間,代表兩個輸入圖片的相似程度。

實(shí)現(xiàn)代碼如下:

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 VGG16
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

二、訓(xùn)練部分

1、數(shù)據(jù)集的格式

本文所使用的數(shù)據(jù)集為Omniglot數(shù)據(jù)集。

其包含來自 50不同字母(語言)的1623 個不同手寫字符。

每一個字符都是由 20個不同的人通過亞馬遜的 Mechanical Turk 在線繪制的。

相當(dāng)于每一個字符有20張圖片,然后存在1623個不同的手寫字符,我們需要利用神經(jīng)網(wǎng)絡(luò)進(jìn)行學(xué)習(xí),去區(qū)分這1623個不同的手寫字符,比較輸入進(jìn)來的字符的相似性。

本博客中數(shù)據(jù)存放格式有三級:

- 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計算

對于孿生神經(jīng)網(wǎng)絡(luò)而言,其具有兩個輸入。

當(dāng)兩個輸入指向同一個類型的圖片時,此時標(biāo)簽為1。

當(dāng)兩個輸入指向不同類型的圖片時,此時標(biāo)簽為0。

然后將網(wǎng)絡(luò)的輸出結(jié)果和真實(shí)標(biāo)簽進(jìn)行交叉熵運(yùn)算,就可以作為最終的loss了。

本文所使用的Loss為binary_crossentropy。

當(dāng)我們輸入如下兩個字體的時候,我們希望網(wǎng)絡(luò)的輸出為1。

我們會將預(yù)測結(jié)果和1求交叉熵。

當(dāng)我們輸入如下兩個字體的時候,我們希望網(wǎng)絡(luò)的輸出為0。

我們會將預(yù)測結(jié)果和0求交叉熵。

訓(xùn)練自己的孿生神經(jīng)網(wǎng)絡(luò)

1、訓(xùn)練本文所使用的Omniglot例子

下載數(shù)據(jù)集,放在根目錄下的dataset文件夾下。

運(yùn)行train.py開始訓(xùn)練。

2、訓(xùn)練自己相似性比較的模型

如果大家想要訓(xùn)練自己的數(shù)據(jù)集,可以將數(shù)據(jù)集按照如下格式進(jìn)行擺放。

每一個chapter里面放同類型的圖片。

之后將train.py當(dāng)中的train_own_data設(shè)置成True,即可開始訓(xùn)練。

以上就是Keras搭建孿生神經(jīng)網(wǎng)絡(luò)Siamese network比較圖片相似性的詳細(xì)內(nèi)容,更多關(guān)于Keras孿生神經(jīng)網(wǎng)絡(luò)比較圖片的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論