在 tensorflow 2 中将 keras 功能模型转换为 keras class

Converting keras functional model to keras class in tensorflow 2

我正在尝试将 Keras 功能模型转换为从 tensorflow.keras.models.Model 派生的 class,但我面临 2 个问题。 1. 我需要使用 tensorflow.keras.layers.multiply 乘以 2 层,但它 return 是 ValueError: A merge layer should be called on a list of inputs。 2. 如果我删除这个层,从而使用 classical CNN,它 return 是 tensorflow.python.eager.core._SymbolicException:Inputs to eager execution function cannot be Keras symbolic tensors, but found [<tf.Tensor 'patch:0' shape=(None, 64, 64, 3) dtype=float32>]

我希望得到一些指导来转换我的代码。我正在使用 Python 3.7、TensorFlow 2.0rc2 和 Keras 2.3.0。我定义的 class 如下:

class TestCNN(Model):
    """
      conv1 > conv2 > fc1 > fc2 > alpha * fc2 > Sigmoid > output
    """

    def __init__(self, input_dimension, n_category,**kwargs):
        """
        Instanciator
        :param input_dimension: tuple of int, theoretically (patch_size x patch_size x channels)
        :param n_category: int, the number of categories to classify,
        :param weight_decay: float, weight decay parameter for all the kernel regularizers
        :return: the Keras model
        """

        super(TestCNN, self).__init__(name='testcnn', **kwargs)

        self.input_dimension = input_dimension
        self.n_category = n_category

        self.conv1 = Conv2D(36, activation='relu', name='conv1/relu')
        self.conv1_maxpooling = MaxPooling2D((2, 2), name='conv1/maxpooling')
        self.conv2 = Conv2D(48, activation='relu', name='conv2/relu')
        self.conv2_maxpooling = MaxPooling2D((2, 2), name='conv2/maxpooling')
        self.flatten1 = Flatten(name='flatten1')

        self.fc1 = Dense(512, activation='relu', name='fc1/relu')
        self.fc2 = Dense(512, activation='relu', name='fc2/relu')
        self.alpha = TestLayer(layer_dim=128, name='alpha')
        self.output1 = TestSigmoid(output_dimension=n_category, name='output_layer')

    @tensorflow.function
    def call(self, x):

        x = self.conv1(x)
        x = self.conv1_maxpooling(x)

        x = self.conv2(x)
        x = self.conv2_maxpooling(x)
        x = self.flatten1(x)

        x = self.fc1(x)
        x = self.fc2(x)

        alpha_times_fc2 = multiply([alpha_output, fc2_output], name='alpha_times_fc2')

        return self.output1(alpha_times_fc2)


    def build(self, **kwargs):

        inputs = Input(shape=self.input_dimension, dtype='float32', name='patch')
        outputs = self.call(inputs)
        super(TestCNN, self).__init__(name="TestCNN", inputs=inputs, outputs=outputs, **kwargs)

然后,在我的主循环中,我按如下方式创建实例:

testcnn = TestCNN(input_dimension=input_dimension, n_category=training_set.category_count)

optimizer = tensorflow.keras.optimizers.Adam(
            lr=parameter['training']['adam']['learning_rate'],
            beta_1=parameter['training']['adam']['beta1'],
            beta_2=parameter['training']['adam']['beta2'])

metrics_list = [tensorflow.keras.metrics.TruePositives]

loss_function = tensorflow.keras.losses.categorical_crossentropy
loss_metrics = tensorflow.keras.metrics.Mean()

testcnn.build()
testcnn.summary()

此代码正在提高 tensorflow.python.eager.core._SymbolicException。如果我注释掉一些行和 return 直接 fc2 层的结果,我得到 ValueError.

我在我的模型中评论了 build() 函数,并在我的主脚本中调用它如下:

testcnn.build(input_dimension)
testcnn.compile(optimizer=adam_optimizer, loss=loss_function, metrics=metrics_list)
testcnn.summary()

输入维度是一个列表,格式如下:

input_dimension = (batch_size, image_size, image_size, channels)