Keras将两个模型连接到一起

神经网络玩得越久就越会尝试一些网络结构上的大改动。

先说意图

有两个模型:模型A和模型B。模型A的输出可以连接B的输入。将两个小模型连接成一个大模型,A-B,既可以同时训练又可以分离训练

流行的算法里经常有这么关系的两个模型,对GAN来说,生成器和判别器就是这样子;对VAE来说,编码器和解码器就是这样子;对目标检测网络来说,backbone和整体也是可以拆分的。所以,应用范围还是挺广的。


实现方法

首先说明,我的实现方法不一定是最佳方法。也是实在没有借鉴到比较好的方法,所以才自己手动写了一个。

第一步,我们有现成的两个模型A和B;我们想把A的输出连到B的输入,组成一个整体C。

第二步, 重构新模型C;我的方法是:读出A和B各有哪些layer,然后一层一层重新搭成C

可以看一个自编码器的代码(本人所编写):

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()函数,直接用for循环读出各层,然后一层一层重新构造新的模型,从而实现连接效果。因为keras也是基于图的框架,这个操作并不会很费时,因为没有实际地计算。

仅供参考。

  • 12
    点赞
  • 82
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
连接两个深度模型的代码实现通常需要考虑两个模型的具体结构和数据的传递方式。以下是一些常见的实现方法: 1. 共享层连接 ``` # 定义第一个模型 model_1 = keras.models.Sequential([ keras.layers.Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(28, 28, 1)), keras.layers.MaxPooling2D(pool_size=(2, 2)), keras.layers.Flatten(), keras.layers.Dense(128, activation='relu') ]) # 定义共享层 shared_layer = keras.layers.Dense(64, activation='relu') # 定义第二个模型,使用共享层连接到第一个模型 input_layer = keras.layers.Input(shape=(128,)) shared_output = shared_layer(input_layer) model_2_output = keras.layers.Dense(10, activation='softmax')(shared_output) model_2 = keras.models.Model(inputs=input_layer, outputs=model_2_output) # 连接两个模型 model_1_output = model_1.layers[-1].output # 获取第一个模型的输出 shared_output = shared_layer(model_1_output) # 使用共享层连接 model_2_output = model_2(shared_output) # 获取第二个模型的输出 final_model = keras.models.Model(inputs=model_1.input, outputs=model_2_output) ``` 2. 集成学习连接 ``` # 定义第一个模型 model_1 = keras.models.Sequential([ keras.layers.Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(28, 28, 1)), keras.layers.MaxPooling2D(pool_size=(2, 2)), keras.layers.Flatten(), keras.layers.Dense(128, activation='relu') ]) # 定义第二个模型 model_2 = keras.models.Sequential([ keras.layers.Dense(64, activation='relu', input_shape=(128,)), keras.layers.Dense(10, activation='softmax') ]) # 连接两个模型进行集成学习 input_layer = keras.layers.Input(shape=(28, 28, 1)) model_1_output = model_1(input_layer) model_2_output = model_2(model_1_output) final_model = keras.models.Model(inputs=input_layer, outputs=model_2_output) ``` 以上代码仅供参考,具体的实现方法需要根据具体需求进行调整和修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木盏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值