keras實現(xiàn)權(quán)重共享網(wǎng)絡(luò)

介紹

CNN中有權(quán)重共享的概念,是一張圖片中的多個區(qū)域共享同一個卷積核的參數(shù)。與前者不同,這里討論的是權(quán)重共享網(wǎng)絡(luò),即有多個不同的輸入,經(jīng)過具有相同參數(shù)的一個網(wǎng)絡(luò),得到兩個不同的結(jié)果。
有一類網(wǎng)絡(luò)叫孿生網(wǎng)絡(luò)(如MatchNet)就具有權(quán)重共享的特性。這種網(wǎng)絡(luò)可以用來衡量兩個樣本的相似性,用于判定兩個樣本是不是同一個類。在人臉識別、簽名識別、語言識別任務(wù)中有一些應(yīng)用。
keras實現(xiàn)孿生網(wǎng)絡(luò)的方式很簡單,只要將需要共享的地方組成一個Model。在后續(xù)網(wǎng)絡(luò)調(diào)用Model即可。最后整個網(wǎng)絡(luò)再組成一個Model。相當(dāng)于整體Model包含共享的Model。。。Model套Model

keras官方文檔示例

下面ClassFilerNet1是共享權(quán)重的網(wǎng)絡(luò),最后summary的參數(shù)量是4萬多;ClassFilerNet2沒有共享權(quán)重,summary的參數(shù)量是9萬多。
共享的部分是conv2d-conv2d-maxpooling2d-flatten
第一個網(wǎng)絡(luò)將共享的部分組成了vision_model,后續(xù)像Layer一樣函數(shù)式調(diào)用即可。
第二個網(wǎng)絡(luò)重新創(chuàng)建了不同的Layer,沒有組成一個Model,所以參數(shù)會增加。

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 出自這里

代碼是直接粘貼過來的,實際上核心用法看keras官方文檔最簡單也最直觀。粘貼過來只是做個記錄。
MatchNet包含兩塊:FeatureExtract,Classification。
FeatureExtract部分,對于多個輸入應(yīng)該采用相同的權(quán)重進(jìn)行處理,需要用到共享權(quán)重。
Classification對提取的特征進(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ò),其實maychnet是兩個網(wǎng)絡(luò)結(jié)構(gòu),一個是特征提取層(孿生),一個度量層+匹配層(統(tǒng)稱為決策層)"""
    input1 = FeatureNetwork()                     # 孿生網(wǎng)絡(luò)中的一個特征提取
    input2 = FeatureNetwork()                     # 孿生網(wǎng)絡(luò)中的另一個特征提取
    for layer in input2.layers:                   # 這個for循環(huán)一定要加,否則網(wǎng)絡(luò)重名會出錯。
        layer.name = layer.name + str("_2")
    inp1 = input1.input
    inp2 = input2.input
    merge_layers = concatenate([input1.output, input2.output])        # 進(jìn)行融合,使用的是默認(rèn)的sum,即簡單的相加
    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ò),其實maychnet是兩個網(wǎng)絡(luò)結(jié)構(gòu),一個是特征提取層(孿生),一個度量層+匹配層(統(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ò)中的一個特征提取分支
        model_2 = model(inp2)  # 孿生網(wǎng)絡(luò)中的另一個特征提取分支
        merge_layers = concatenate([model_1, model_2])  # 進(jìn)行融合,使用的是默認(rèn)的sum,即簡單的相加

    else:
        input1 = FeatureNetwork()                     # 孿生網(wǎng)絡(luò)中的一個特征提取
        input2 = FeatureNetwork()                     # 孿生網(wǎng)絡(luò)中的另一個特征提取
        for layer in input2.layers:                   # 這個for循環(huán)一定要加,否則網(wǎng)絡(luò)重名會出錯。
            layer.name = layer.name + str("_2")
        inp1 = input1.input
        inp2 = input2.input
        merge_layers = concatenate([input1.output, input2.output])        # 進(jìn)行融合,使用的是默認(rèn)的sum,即簡單的相加
    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
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容