Keras實(shí)現(xiàn)將兩個(gè)模型連接到一起
神經(jīng)網(wǎng)絡(luò)玩得越久就越會嘗試一些網(wǎng)絡(luò)結(jié)構(gòu)上的大改動。
先說意圖
有兩個(gè)模型:模型A和模型B。模型A的輸出可以連接B的輸入。將兩個(gè)小模型連接成一個(gè)大模型,A-B,既可以同時(shí)訓(xùn)練又可以分離訓(xùn)練。
流行的算法里經(jīng)常有這么關(guān)系的兩個(gè)模型,對GAN來說,生成器和判別器就是這樣子;對VAE來說,編碼器和解碼器就是這樣子;對目標(biāo)檢測網(wǎng)絡(luò)來說,backbone和整體也是可以拆分的。所以,應(yīng)用范圍還是挺廣的。
實(shí)現(xiàn)方法
首先說明,我的實(shí)現(xiàn)方法不一定是最佳方法。也是實(shí)在沒有借鑒到比較好的方法,所以才自己手動寫了一個(gè)。
第一步,我們有現(xiàn)成的兩個(gè)模型A和B;我們想把A的輸出連到B的輸入,組成一個(gè)整體C。
第二步, 重構(gòu)新模型C;我的方法是:讀出A和B各有哪些layer,然后一層一層重新搭成C。
可以看一個(gè)自編碼器的代碼(本人所編寫):
class AE:
def __init__(self, dim, img_dim, batch_size):
self.dim = dim
self.img_dim = img_dim
self.batch_size = batch_size
self.encoder = self.encoder_construct()
self.decoder = self.decoder_construct()
def encoder_construct(self):
x_in = Input(shape=(self.img_dim, self.img_dim, 3))
x = x_in
x = Conv2D(self.dim // 16, kernel_size=(5, 5), strides=(2, 2), padding='SAME')(x)
x = BatchNormalization()(x)
x = LeakyReLU(0.2)(x)
x = Conv2D(self.dim // 8, kernel_size=(5, 5), strides=(2, 2), padding='SAME')(x)
x = BatchNormalization()(x)
x = LeakyReLU(0.2)(x)
x = Conv2D(self.dim // 4, kernel_size=(5, 5), strides=(2, 2), padding='SAME')(x)
x = BatchNormalization()(x)
x = LeakyReLU(0.2)(x)
x = Conv2D(self.dim // 2, kernel_size=(5, 5), strides=(2, 2), padding='SAME')(x)
x = BatchNormalization()(x)
x = LeakyReLU(0.2)(x)
x = Conv2D(self.dim, kernel_size=(5, 5), strides=(2, 2), padding='SAME')(x)
x = BatchNormalization()(x)
x = LeakyReLU(0.2)(x)
x = GlobalAveragePooling2D()(x)
encoder = Model(x_in, x)
return encoder
def decoder_construct(self):
map_size = K.int_shape(self.encoder.layers[-2].output)[1:-1]
# print(type(map_size))
z_in = Input(shape=K.int_shape(self.encoder.output)[1:])
z = z_in
z_dim = self.dim
z = Dense(np.prod(map_size) * z_dim)(z)
z = Reshape(map_size + (z_dim,))(z)
z = Conv2DTranspose(z_dim // 2, kernel_size=(5, 5), strides=(2, 2), padding='SAME')(z)
z = BatchNormalization()(z)
z = Activation('relu')(z)
z = Conv2DTranspose(z_dim // 4, kernel_size=(5, 5), strides=(2, 2), padding='SAME')(z)
z = BatchNormalization()(z)
z = Activation('relu')(z)
z = Conv2DTranspose(z_dim // 8, kernel_size=(5, 5), strides=(2, 2), padding='SAME')(z)
z = BatchNormalization()(z)
z = Activation('relu')(z)
z = Conv2DTranspose(z_dim // 16, kernel_size=(5, 5), strides=(2, 2), padding='SAME')(z)
z = BatchNormalization()(z)
z = Activation('relu')(z)
z = Conv2DTranspose(3, kernel_size=(5, 5), strides=(2, 2), padding='SAME')(z)
z = Activation('tanh')(z)
decoder = Model(z_in, z)
return decoder
def build_ae(self):
input_x = Input(shape=(self.img_dim, self.img_dim, 3))
x = input_x
for i in range(1, len(self.encoder.layers)):
x = self.encoder.layers[i](x)
for j in range(1, len(self.decoder.layers)):
x = self.decoder.layers[j](x)
y = x
auto_encoder = Model(input_x, y)
return auto_encoder
模型A就是這里的encoder,模型B就是這里的decoder。所以,連接的精髓在build_ae()函數(shù),直接用for循環(huán)讀出各層,然后一層一層重新構(gòu)造新的模型,從而實(shí)現(xiàn)連接效果。因?yàn)閗eras也是基于圖的框架,這個(gè)操作并不會很費(fèi)時(shí),因?yàn)闆]有實(shí)際地計(jì)算。
補(bǔ)充知識:keras得到每層的系數(shù)
使用keras搭建好一個(gè)模型,訓(xùn)練好,怎么得到每層的系數(shù)呢:
weights = np.array(model.get_weights()) print(weights) print(weights[0].shape) print(weights[1].shape)
這樣系數(shù)就被存放到一個(gè)np中了。
以上這篇Keras實(shí)現(xiàn)將兩個(gè)模型連接到一起就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
tkinter動態(tài)顯示時(shí)間的兩種實(shí)現(xiàn)方法
這篇文章主要介紹了tkinter動態(tài)顯示時(shí)間的兩種實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01
python 時(shí)間的訪問和轉(zhuǎn)換 time示例小結(jié)
Python 的 time 模塊提供了各種與時(shí)間處理相關(guān)的功能,包括獲取當(dāng)前時(shí)間、操作日期/時(shí)間以及執(zhí)行與時(shí)間相關(guān)的各種其它功能,這篇文章主要介紹了python 時(shí)間的訪問和轉(zhuǎn)換 time,需要的朋友可以參考下2024-05-05
Django之使用celery和NGINX生成靜態(tài)頁面實(shí)現(xiàn)性能優(yōu)化
這篇文章主要介紹了Django之使用celery和NGINX生成靜態(tài)頁面實(shí)現(xiàn)性能優(yōu)化,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
matplotlib基礎(chǔ)繪圖命令之imshow的使用
這篇文章主要介紹了matplotlib基礎(chǔ)繪圖命令之imshow的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
Python中單引號、雙引號和三引號具體的用法及注意點(diǎn)
這篇文章主要給大家介紹了關(guān)于Python中單引號、雙引號和三引號具體的用法及注意點(diǎn)的相關(guān)資料,Python中單引號、雙引號、三引號中使用常常困惑,想弄明白這三者相同點(diǎn)和不同點(diǎn),需要的朋友可以參考下2023-07-07

