如何按顺序堆叠迁移学习模型

How to stack Transfer Learning models in a Sequential

为了构建一个漂亮的架构,我想将迁移学习模型一个接一个地堆叠起来。

我想要堆叠的三个模型是:

所以,我定义了三个模型如下:

model_vgg = tf.keras.applications.VGG16(
    weights='imagenet', 
    include_top=False,
    input_shape=(SIZE, SIZE, 3)
)

model_inc = tf.keras.applications.inception_v3.InceptionV3(
    weights='imagenet', 
    include_top=False,
    input_shape=(SIZE, SIZE, 3)
)

model_res = tf.keras.applications.ResNet50(
    weights='imagenet', 
    include_top=False,
    input_shape=(SIZE, SIZE, 3)
)

Size was set as 100

在此之后,我为每个人设置了trainable=False

现在,我将如何按顺序堆叠这些模型,即我必须进行哪些更改才能使每个模型的输出形状与下一个模型的输入形状相匹配?

model = tf.keras.Sequential([
    
    model_vgg,
    model_inc,
    model_res,
    tf.keras.layers.Flatten()
    
])

由于每个模型都有不同的输出形状,您必须在将每个模型输入到下一个模型之前重新整形,这可能会影响性能:

import tensorflow as tf

SIZE = 100
model_vgg = tf.keras.applications.VGG16(
    weights='imagenet', 
    include_top=False,
    input_shape=(SIZE, SIZE, 3)
)

model_inc = tf.keras.applications.inception_v3.InceptionV3(
    weights='imagenet', 
    include_top=False,
    input_shape=(SIZE, SIZE, 3)
)

model_res = tf.keras.applications.ResNet50(
    weights='imagenet', 
    include_top=False,
    input_shape=(SIZE, SIZE, 3)
)

model_vgg.trainable = False
model_inc.trainable = False
model_res.trainable = False

model = tf.keras.Sequential([
    
    model_vgg,
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(SIZE*SIZE*3),
    tf.keras.layers.Reshape((SIZE, SIZE, 3)),
    model_inc,
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(SIZE*SIZE*3),
    tf.keras.layers.Reshape((SIZE, SIZE, 3)),
    model_res,
    tf.keras.layers.Flatten()
    
])
print(model(tf.random.normal((1, 100, 100, 3))).shape)

您还必须决定是否要在每个 Dense 层上使用非线性激活函数。哦,你也可以像这样使用每个模型的预处理方法:

model = tf.keras.Sequential([
    
    tf.keras.layers.Lambda(lambda x: tf.keras.applications.vgg16.preprocess_input(x)),
    model_vgg,
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(SIZE*SIZE*3),
    tf.keras.layers.Reshape((SIZE, SIZE, 3)),
    tf.keras.layers.Lambda(lambda x: tf.keras.applications.inception_v3.preprocess_input(x)),
    model_inc,
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(SIZE*SIZE*3),
    tf.keras.layers.Reshape((SIZE, SIZE, 3)),
    tf.keras.layers.Lambda(lambda x: tf.keras.applications.resnet50.preprocess_input(x)),
    model_res,
    tf.keras.layers.Flatten()
    
])

我个人的建议是将输入提供给各个模型,然后将输出和 运行 其他下游操作连接起来:

inputs = tf.keras.layers.Input((SIZE, SIZE, 3))
    
vgg = tf.keras.layers.Lambda(lambda x: tf.keras.applications.vgg16.preprocess_input(x))(inputs)
vgg = tf.keras.layers.GlobalAvgPool2D()(model_vgg(vgg))

inc = tf.keras.layers.Lambda(lambda x: tf.keras.applications.inception_v3.preprocess_input(x))(inputs)
inc = tf.keras.layers.GlobalAvgPool2D()(model_inc(inc))

res = tf.keras.layers.Lambda(lambda x: tf.keras.applications.resnet50.preprocess_input(x))(inputs)
res = tf.keras.layers.GlobalAvgPool2D()(model_res(res))

outputs = tf.keras.layers.Concatenate(axis=-1)([vgg, inc, res])
model = tf.keras.Model(inputs, outputs)