将 TensorFlow 2+ 中两个 Conv2D 层的输出相乘

Multiply outputs from two Conv2D layers in TensorFlow 2+

我正在尝试在 TensorFlow(解耦版本)中实现实例分割的 SOLO 架构。

https://arxiv.org/pdf/1912.04488.pdf

现在,我需要计算损失函数,并将第一个 conv2d 层的每个输出图与第二层的输出图相乘。

xi = Conv2D(…)(input) # output is (batch, None, None, 24)
yi = Conv2D(…)(input) # output is (batch, None, None, 24)

我需要将每个输出映射(按元素)xiyi 相乘,以获得 (batch, None, None, 24*24) 的输出。我需要将一个输出特征图(来自第一个 conv2d)与来自第二个 conv2d 层的所有特征图逐元素相乘,依此类推。 这就是为什么 24 * 24

我尝试使用循环执行此操作但出现错误:

OperatorNotAllowedInGraphError: iterating over tf.Tensor is not allowed: 
                                                    AutoGraph did convert this function.

有什么建议可以通过一些 TF2 操作实现这一目标吗?

您可以使用 Multiply 层来执行此操作

multiplied = tensorflow.keras.layers.Multiply()([xi,yi])

该层乘以(按元素)输入列表。
它以张量列表作为输入,所有张量的形状都相同,returns 一个张量(也具有相同的形状)。

它基本上是最后一个维度的外积然后折叠最后2个维度。表达此操作的一种简短方法是使用 tf.repeattf.tile.

#channel_dims is the length of the last dimension, i.e. 24 in your question 
@tf.function
def outerprodflatten(x,y,channel_dims):
  return tf.repeat(x,channel_dims,-1)*tf.tile(y,[1,1,1,channel_dims])

要在函数式 API 中使用它,您还必须定义自定义 keras 层或 lambda 层,即

class Outerprodflatten_layer(tf.keras.layers.Layer):
    def __init__(self, channel_dims):
        self.channel_dims = channel_dims
        super().__init__()

    def call(self, inputs):
        return tf.repeat(inputs[0],self.channel_dims,-1)*tf.tile(inputs[1],[1,1,1,self.channel_dims])

x = Conv2D(…)(input) # output is (batch, None, None, 24)
y = Conv2D(…)(input) # output is (batch, None, None, 24)

out=Outerprodflatten_layer(24)([x,y])