Tensorflow 2.0 模型子类化

Tensorflow 2.0 Model subclassing

我制作了这个将 resnet 合并到模型中的函数。它运行良好,我可以保存它。 我的问题是我无法加载它,因为它需要调用函数。我不确定如何将其变成 class。尝试在底部。一些指示会有所帮助。

def build_network():

    inp = Input(shape=(256,256,3))

    resnet = tf.keras.applications.ResNet152V2(
        include_top=False, weights='imagenet', input_tensor=None,
        input_shape=(256,256,3), pooling=None, classes=1000

    )
    # classifier_activation='softmax'
    x = resnet(inp)
    x = GlobalAveragePooling2D()(x)
    x = Dropout(0.3)(x)
    x = Dense(9, activation='softmax')(x)
    model = tf.keras.Model(inputs=inp,outputs = x)
    opt = tf.keras.optimizers.SGD(momentum=0.9)

    # optimizer = 'adam',
    model.compile(loss='categorical_crossentropy',
                    optimizer = opt,
                    metrics=['accuracy'])

    model.summary()

    return model

class Resnet(tf.keras.Model):

    def __init__(self, num_classes=9):
        super(Resnet, self).__init__()
        self.block_1 = tf.keras.applications.ResNet152V2(
            include_top=False, weights='imagenet', input_tensor=None,
            input_shape=(256,256,3), pooling=None, classes=1000)
        self.global_pool = layers.GlobalAveragePooling2D()
        self.dropout = Dropout(0.3)
        self.classifier = Dense(num_classes, activation = 'softmax')

    def call(self, inputs):
        x = self.block_1(inputs)
        x = self.global_pool(x)
        x = self.dropout(x)
        x = self.classifier(x)
        return tf.keras.Model(inputs = inputs, outputs = x)

使用子类 API 实际上会使您的模型不可序列化(参见 "Limitations section in the "What are Symbolic and Imperative APIs in TensorFlow 2.0? " blogpost):

Imperative models are also more difficult to inspect, copy, or clone.

For example, model.save(), model.get_config(), and clone_model do not work for subclassed models. Likewise, model.summary() only gives you a list of layers (and doesn’t provide information on how they’re connected, since that’s not accessible).

编辑:从 Tensorflow 2.4 开始,可以将 save_traces 参数传递给 model.save 以序列化使用子类 API 构建的模型。参见 https://www.tensorflow.org/guide/keras/save_and_serialize#how_savedmodel_handles_custom_objects

这里有一个简单的例子来说明如何做到这一点:

import tensorflow as tf
from tensorflow.keras.layers import (Dense, Dropout, GlobalAveragePooling2D,
                                     Input)


def build_network():
    inp = Input(shape=(256, 256, 3))
    resnet = tf.keras.applications.ResNet152V2(include_top=False,
                                               weights="imagenet",
                                               input_tensor=None,
                                               input_shape=(256, 256, 3),
                                               pooling=None,
                                               classes=1000)
    # classifier_activation="softmax"
    x = resnet(inp)
    x = GlobalAveragePooling2D()(x)
    x = Dropout(0.3)(x)
    x = Dense(9, activation="softmax")(x)
    model = tf.keras.Model(inputs=inp, outputs=x)
    # optimizer = "adam",
    opt = tf.keras.optimizers.SGD(momentum=0.9)
    model.compile(loss="categorical_crossentropy",
                  optimizer=opt,
                  metrics=["accuracy"])
    model.summary()
    return model


if __name__ == "__main__":
    model = build_network()
    model.summary()
    # Save
    model.save("my_model.h5")
    # Load
    loaded_model = tf.keras.models.load_model("my_model.h5")
    loaded_model.summary()

要从 build_network 函数加载保存的模型,请使用 tf.keras.models.load_model