Keras实现将两个模型连接到一起
神经网络玩得越久就越会尝试一些网络结构上的大改动。
先说意图
有两个模型:模型A和模型B。模型A的输出可以连接B的输入。将两个小模型连接成一个大模型,A-B,既可以同时训练又可以分离训练。
流行的算法里经常有这么关系的两个模型,对GAN来说,生成器和判别器就是这样子;对VAE来说,编码器和解码器就是这样子;对目标检测网络来说,backbone和整体也是可以拆分的。所以,应用范围还是挺广的。
实现方法
首先说明,我的实现方法不一定是最佳方法。也是实在没有借鉴到比较好的方法,所以才自己手动写了一个。
第一步,我们有现成的两个模型A和B;我们想把A的输出连到B的输入,组成一个整体C。
第二步,重构新模型C;我的方法是:读出A和B各有哪些layer,然后一层一层重新搭成C。
可以看一个自编码器的代码(本人所编写):
classAE: 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() defencoder_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) returnencoder defdecoder_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) returndecoder defbuild_ae(self): input_x=Input(shape=(self.img_dim,self.img_dim,3)) x=input_x foriinrange(1,len(self.encoder.layers)): x=self.encoder.layers[i](x) forjinrange(1,len(self.decoder.layers)): x=self.decoder.layers[j](x) y=x auto_encoder=Model(input_x,y) returnauto_encoder
模型A就是这里的encoder,模型B就是这里的decoder。所以,连接的精髓在build_ae()函数,直接用for循环读出各层,然后一层一层重新构造新的模型,从而实现连接效果。因为keras也是基于图的框架,这个操作并不会很费时,因为没有实际地计算。
补充知识:keras得到每层的系数
使用keras搭建好一个模型,训练好,怎么得到每层的系数呢:
weights=np.array(model.get_weights()) print(weights) print(weights[0].shape) print(weights[1].shape)
这样系数就被存放到一个np中了。
以上这篇Keras实现将两个模型连接到一起就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。