【问题标题】:How to define a 2D convolution on tensors with rank greater than 4 in keras/tensorflow如何在 keras/tensorflow 中定义秩大于 4 的张量的 2D 卷积
【发布时间】:2019-11-20 07:17:46
【问题描述】:

我正在尝试找到一种方法来对维度高于 4 的张量执行 2D 卷积,这是 keras.layers.Conv2Dkeras 所需的输入等级。 backend.conv2d。我的意思是,我希望能够使用[batch,<some_other_dimensions>, W, H, C],而不是输入大小为[batch, W, H, C],并且对于那些其他维度基本上以与“批处理”相同的方式处理(例如不受卷积)。不出所料,这会引发错误,因此重塑数组似乎是最直接的解决方案,但是,这样做存在问题(如下所述)。

在重塑时,我弄乱了 Keras 认为的批处理维度,所以我需要使用 keras.backend.reshape,而不是 keras.layers.Reshape em>,这似乎无法访问数据的批处理维度。通过使用 lambda 层和 keras.backend.reshape,我们可以制作大小为 [batch*<some_other_dimensions>,W,H,C] 的输入数组,然后在执行卷积后将它们重新整形。 但是,该层必须能够构成全卷积网络的一部分,该网络可以处理具有未定义 W 和 H(在实例化输入层的形状时设置为 None)的任意图像大小。 因此,我们最终将具有两个未定义空间维度的形状传递给 keras.backend.reshape,它显然不能使用: [batch*<some_other_dimensions>,None,None,C].

当明确声明宽度和高度时,我可以让它工作(正如你在我的代码中看到的那样)。但是,我真的不想牺牲摄取任意大小的空间维度的能力,因为这对我的项目来说很重要。

我能想到的唯一其他选择实际上是定义我自己的自定义层,该层可以处理 2D 卷积的 > 4 维输入。我真的不知道从哪里开始,但如果人们认为这是最可行的路线,建议将是最受欢迎的。或者是否有一个漂亮的 lambda 层可以解决我的问题?

from keras.layers import Input, Conv2D, Lambda
import keras.backend as K
from keras.models import Model


def reshape_then_conv(data_shape):

    input = Input(shape=data_shape)
    #should equal (None, *data_shape) because batch is prepended as None
    print('      INPUT SHAPE: ', input.shape)

    #reshaping input into 4D
    reshaped = Lambda(lambda x: K.reshape(x,(-1, *input.shape[3:])))(input)
    print('    AFTER RESHAPE: ', reshaped.shape)

    #convolve new 4D tensor
    convolved = Conv2D(10,(3,3),strides=2)(reshaped)
    print('AFTER CONVOLUTION: ', convolved.shape)

    #reshaping back but keeping new spatial and channel dimensions from convolution
    reshaped_back = Lambda(lambda x: K.reshape(x,(-1,*input.shape[1:3],*convolved.shape[-3:])))(convolved)
    return Model(inputs=input,outputs=reshaped_back)



#images of size 100,100,3 in 4-by-4 set
layer = reshape_then_conv([4,4,100,100,3])
print('     OUTPUT SHAPE: ', layer.output_shape,'\n')
#images of undefined size in 4-by-4 set
layer = reshape_then_conv([4,4,None,None,3])
print('     OUTPUT SHAPE: ', layer.output_shape)

正如预期的那样,第一次调用“reshape_then_conv”可以正常工作,因为我们明确设置了宽度和高度。然而,第二个例子给出了:

TypeError:无法将类型对象转换为张量。 >内容:(-1,维度(无),维度(无),维度(3))。考虑>将元素转换为支持的类型。

提前感谢您提供的任何见解!

更新

感谢@DMolony 的回答,我将代码重新排列如下...

from keras.layers import Input, Conv2D, Lambda
import keras.backend as K
from keras.models import Model

def reshape_then_conv(data_shape):

    input = Input(shape=data_shape)
    print('      INPUT SHAPE: ', input.shape)
    new_shape = K.concatenate((K.variable([-1],dtype='int32'),K.shape(input)[3:]))
    #reshaping input into 4D
    reshaped = Lambda(lambda x: K.reshape(x,new_shape))(input)
    print('    AFTER RESHAPE: ', reshaped.shape)

    #convolve new 4D tensor
    convolved = Conv2D(10,(3,3),strides=2)(reshaped)
    print('AFTER CONVOLUTION: ', convolved.shape)

    returning_shape = K.concatenate((K.variable([-1],dtype='int32'),K.shape(input)[1:3],K.shape(convolved)[-3:]))
    #reshaping back but keeping new spatial and channel dimensions from convolution
    reshaped_back = Lambda(lambda x: K.reshape(x,returning_shape))(convolved)
    return Model(inputs=input,outputs=reshaped_back)

#images of size 100,100,3 in 4-by-4 set
layer = reshape_then_conv([4,4,100,100,3])
print('     OUTPUT SHAPE: ', layer.output_shape,'\n')
#images of undefined size in 4-by-4 set
layer = reshape_then_conv([4,4,None,None,3])
print('     OUTPUT SHAPE: ', layer.output_shape)

【问题讨论】:

    标签: python tensorflow keras deep-learning computer-vision


    【解决方案1】:

    当重塑而不是使用静态形状时,例如

    input.shape[1:3]  
    

    尝试提供动态形状,例如

    K.shape(input)[1:3]
    

    【讨论】:

    • 非常感谢!你的回答让我走上了正轨。有一些额外的步骤,但这是关键。将 Lambda 重塑层更新为:reshaped = Lambda(lambda x: K.reshape(x, K.concatenate((K.variable([-1],dtype=tf.int32),K.shape(input)[3:]))))(input)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多