介紹
CNN中有權(quán)重共享的概念,是一張圖片中的多個(gè)區(qū)域共享同一個(gè)卷積核的參數(shù)乎澄。與前者不同突硝,這里討論的是權(quán)重共享網(wǎng)絡(luò),即有多個(gè)不同的輸入置济,經(jīng)過具有相同參數(shù)的一個(gè)網(wǎng)絡(luò)解恰,得到兩個(gè)不同的結(jié)果。
有一類網(wǎng)絡(luò)叫孿生網(wǎng)絡(luò)(如MatchNet)就具有權(quán)重共享的特性浙于。這種網(wǎng)絡(luò)可以用來衡量?jī)蓚€(gè)樣本的相似性护盈,用于判定兩個(gè)樣本是不是同一個(gè)類。在人臉識(shí)別羞酗、簽名識(shí)別腐宋、語(yǔ)言識(shí)別任務(wù)中有一些應(yīng)用。
keras實(shí)現(xiàn)孿生網(wǎng)絡(luò)的方式很簡(jiǎn)單檀轨,只要將需要共享的地方組成一個(gè)Model胸竞。在后續(xù)網(wǎng)絡(luò)調(diào)用Model即可。最后整個(gè)網(wǎng)絡(luò)再組成一個(gè)Model裤园。相當(dāng)于整體Model包含共享的Model撤师。。拧揽。Model套Model
keras官方文檔示例
下面ClassFilerNet1是共享權(quán)重的網(wǎng)絡(luò)剃盾,最后summary的參數(shù)量是4萬(wàn)多腺占;ClassFilerNet2沒有共享權(quán)重,summary的參數(shù)量是9萬(wàn)多痒谴。
共享的部分是conv2d-conv2d-maxpooling2d-flatten
第一個(gè)網(wǎng)絡(luò)將共享的部分組成了vision_model衰伯,后續(xù)像Layer一樣函數(shù)式調(diào)用即可。
第二個(gè)網(wǎng)絡(luò)重新創(chuàng)建了不同的Layer积蔚,沒有組成一個(gè)Model意鲸,所以參數(shù)會(huì)增加。
import keras
from keras.layers import Conv2D, MaxPooling2D, Input, Dense, Flatten
from keras.models import Model
def ClassiFilerNet1():
# First, define the vision modules
digit_input = Input(shape=(27, 27, 1))
x = Conv2D(64, (3, 3))(digit_input)
x = Conv2D(64, (3, 3))(x)
x = MaxPooling2D((2, 2))(x)
out = Flatten()(x)
vision_model = Model(digit_input, out)
# Then define the tell-digits-apart model
digit_a = Input(shape=(27, 27, 1))
digit_b = Input(shape=(27, 27, 1))
# The vision model will be shared, weights and all
out_a = vision_model(digit_a)
out_b = vision_model(digit_b)
concatenated = keras.layers.concatenate([out_a, out_b])
out = Dense(1, activation='sigmoid')(concatenated)
classification_model = Model([digit_a, digit_b], out)
return classification_model
def ClassiFilerNet2():
digit_a = Input(shape=(27, 27, 1))
x = Conv2D(64, (3, 3))(digit_a)
x = Conv2D(64, (3, 3))(x)
x = MaxPooling2D((2, 2))(x)
out1 = Flatten()(x)
digit_b = Input(shape=(27, 27, 1))
x = Conv2D(64, (3, 3))(digit_b)
x = Conv2D(64, (3, 3))(x)
x = MaxPooling2D((2, 2))(x)
out2 = Flatten()(x)
concatenated = keras.layers.concatenate([out1, out2])
out = Dense(1, activation='sigmoid')(concatenated)
classification_model = Model([digit_a, digit_b], out)
return classification_model
MatchNet 出自這里
代碼是直接粘貼過來的尽爆,實(shí)際上核心用法看keras官方文檔最簡(jiǎn)單也最直觀怎顾。粘貼過來只是做個(gè)記錄。
MatchNet包含兩塊:FeatureExtract漱贱,Classification槐雾。
FeatureExtract部分,對(duì)于多個(gè)輸入應(yīng)該采用相同的權(quán)重進(jìn)行處理幅狮,需要用到共享權(quán)重募强。
Classification對(duì)提取的特征進(jìn)行分類,判別是不是同一類崇摄。
下面第一段代碼是非共享權(quán)重擎值,參數(shù)量為4.8M;第二段是共享權(quán)重逐抑,參數(shù)量為3.4M鸠儿。
可以放到tensorboard查看網(wǎng)絡(luò)結(jié)構(gòu),有一些差異厕氨。
from keras.models import Sequential
from keras.layers import merge, Conv2D, MaxPool2D, Activation, Dense, concatenate, Flatten
from keras.layers import Input
from keras.models import Model
from keras.utils import np_utils
import tensorflow as tf
import keras
from keras.datasets import mnist
import numpy as np
from keras.utils import np_utils
from keras.callbacks import EarlyStopping, ModelCheckpoint, TensorBoard, ReduceLROnPlateau
from keras.utils.vis_utils import plot_model
# ---------------------函數(shù)功能區(qū)-------------------------
def FeatureNetwork():
"""生成特征提取網(wǎng)絡(luò)"""
"""這是根據(jù)捆交,MNIST數(shù)據(jù)調(diào)整的網(wǎng)絡(luò)結(jié)構(gòu),下面注釋掉的部分是腐巢,原始的Matchnet網(wǎng)絡(luò)中feature network結(jié)構(gòu)"""
inp = Input(shape = (28, 28, 1), name='FeatureNet_ImageInput')
models = Conv2D(filters=24, kernel_size=(3, 3), strides=1, padding='same')(inp)
models = Activation('relu')(models)
models = MaxPool2D(pool_size=(3, 3))(models)
models = Conv2D(filters=64, kernel_size=(3, 3), strides=1, padding='same')(models)
# models = MaxPool2D(pool_size=(3, 3), strides=(2, 2))(models)
models = Activation('relu')(models)
models = Conv2D(filters=96, kernel_size=(3, 3), strides=1, padding='valid')(models)
models = Activation('relu')(models)
models = Conv2D(filters=96, kernel_size=(3, 3), strides=1, padding='valid')(models)
models = Activation('relu')(models)
models = Flatten()(models)
models = Dense(512)(models)
models = Activation('relu')(models)
model = Model(inputs=inp, outputs=models)
return model
def ClassiFilerNet(): # add classifier Net
"""生成度量網(wǎng)絡(luò)和決策網(wǎng)絡(luò),其實(shí)maychnet是兩個(gè)網(wǎng)絡(luò)結(jié)構(gòu)玄括,一個(gè)是特征提取層(孿生)冯丙,一個(gè)度量層+匹配層(統(tǒng)稱為決策層)"""
input1 = FeatureNetwork() # 孿生網(wǎng)絡(luò)中的一個(gè)特征提取
input2 = FeatureNetwork() # 孿生網(wǎng)絡(luò)中的另一個(gè)特征提取
for layer in input2.layers: # 這個(gè)for循環(huán)一定要加,否則網(wǎng)絡(luò)重名會(huì)出錯(cuò)遭京。
layer.name = layer.name + str("_2")
inp1 = input1.input
inp2 = input2.input
merge_layers = concatenate([input1.output, input2.output]) # 進(jìn)行融合胃惜,使用的是默認(rèn)的sum,即簡(jiǎn)單的相加
fc1 = Dense(1024, activation='relu')(merge_layers)
fc2 = Dense(1024, activation='relu')(fc1)
fc3 = Dense(2, activation='softmax')(fc2)
class_models = Model(inputs=[inp1, inp2], outputs=[fc3])
print("1111")
return class_models
from keras.models import Sequential
from keras.layers import merge, Conv2D, MaxPool2D, Activation, Dense, concatenate, Flatten
from keras.layers import Input
from keras.models import Model
from keras.utils import np_utils
import tensorflow as tf
import keras
from keras.datasets import mnist
import numpy as np
from keras.utils import np_utils
from keras.callbacks import EarlyStopping, ModelCheckpoint, TensorBoard, ReduceLROnPlateau
from keras.utils.vis_utils import plot_model
# ----------------函數(shù)功能區(qū)-----------------------
def FeatureNetwork():
"""生成特征提取網(wǎng)絡(luò)"""
"""這是根據(jù)哪雕,MNIST數(shù)據(jù)調(diào)整的網(wǎng)絡(luò)結(jié)構(gòu)船殉,下面注釋掉的部分是,原始的Matchnet網(wǎng)絡(luò)中feature network結(jié)構(gòu)"""
inp = Input(shape = (28, 28, 1), name='FeatureNet_ImageInput')
models = Conv2D(filters=24, kernel_size=(3, 3), strides=1, padding='same')(inp)
models = Activation('relu')(models)
models = MaxPool2D(pool_size=(3, 3))(models)
models = Conv2D(filters=64, kernel_size=(3, 3), strides=1, padding='same')(models)
# models = MaxPool2D(pool_size=(3, 3), strides=(2, 2))(models)
models = Activation('relu')(models)
models = Conv2D(filters=96, kernel_size=(3, 3), strides=1, padding='valid')(models)
models = Activation('relu')(models)
models = Conv2D(filters=96, kernel_size=(3, 3), strides=1, padding='valid')(models)
models = Activation('relu')(models)
# models = Conv2D(64, kernel_size=(3, 3), strides=2, padding='valid')(models)
# models = Activation('relu')(models)
# models = MaxPool2D(pool_size=(3, 3), strides=(2, 2))(models)
models = Flatten()(models)
models = Dense(512)(models)
models = Activation('relu')(models)
model = Model(inputs=inp, outputs=models)
return model
def ClassiFilerNet(reuse=True): # add classifier Net
"""生成度量網(wǎng)絡(luò)和決策網(wǎng)絡(luò)斯嚎,其實(shí)maychnet是兩個(gè)網(wǎng)絡(luò)結(jié)構(gòu)利虫,一個(gè)是特征提取層(孿生)挨厚,一個(gè)度量層+匹配層(統(tǒng)稱為決策層)"""
if reuse:
inp = Input(shape=(28, 28, 1), name='FeatureNet_ImageInput')
models = Conv2D(filters=24, kernel_size=(3, 3), strides=1, padding='same')(inp)
models = Activation('relu')(models)
models = MaxPool2D(pool_size=(3, 3))(models)
models = Conv2D(filters=64, kernel_size=(3, 3), strides=1, padding='same')(models)
# models = MaxPool2D(pool_size=(3, 3), strides=(2, 2))(models)
models = Activation('relu')(models)
models = Conv2D(filters=96, kernel_size=(3, 3), strides=1, padding='valid')(models)
models = Activation('relu')(models)
models = Conv2D(filters=96, kernel_size=(3, 3), strides=1, padding='valid')(models)
models = Activation('relu')(models)
# models = Conv2D(64, kernel_size=(3, 3), strides=2, padding='valid')(models)
# models = Activation('relu')(models)
# models = MaxPool2D(pool_size=(3, 3), strides=(2, 2))(models)
models = Flatten()(models)
models = Dense(512)(models)
models = Activation('relu')(models)
model = Model(inputs=inp, outputs=models)
inp1 = Input(shape=(28, 28, 1)) # 創(chuàng)建輸入
inp2 = Input(shape=(28, 28, 1)) # 創(chuàng)建輸入2
model_1 = model(inp1) # 孿生網(wǎng)絡(luò)中的一個(gè)特征提取分支
model_2 = model(inp2) # 孿生網(wǎng)絡(luò)中的另一個(gè)特征提取分支
merge_layers = concatenate([model_1, model_2]) # 進(jìn)行融合,使用的是默認(rèn)的sum糠惫,即簡(jiǎn)單的相加
else:
input1 = FeatureNetwork() # 孿生網(wǎng)絡(luò)中的一個(gè)特征提取
input2 = FeatureNetwork() # 孿生網(wǎng)絡(luò)中的另一個(gè)特征提取
for layer in input2.layers: # 這個(gè)for循環(huán)一定要加疫剃,否則網(wǎng)絡(luò)重名會(huì)出錯(cuò)。
layer.name = layer.name + str("_2")
inp1 = input1.input
inp2 = input2.input
merge_layers = concatenate([input1.output, input2.output]) # 進(jìn)行融合硼讽,使用的是默認(rèn)的sum巢价,即簡(jiǎn)單的相加
fc1 = Dense(1024, activation='relu')(merge_layers)
fc2 = Dense(1024, activation='relu')(fc1)
fc3 = Dense(2, activation='softmax')(fc2)
class_models = Model(inputs=[inp1, inp2], outputs=[fc3])
print("22222")
return class_models