Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在keras/tensorflow中定义秩大于4的张量上的二维卷积_Python_Tensorflow_Keras_Deep Learning_Computer Vision - Fatal编程技术网

Python 如何在keras/tensorflow中定义秩大于4的张量上的二维卷积

Python 如何在keras/tensorflow中定义秩大于4的张量上的二维卷积,python,tensorflow,keras,deep-learning,computer-vision,Python,Tensorflow,Keras,Deep Learning,Computer Vision,我正试图找到一种方法来对维度高于4的张量执行2D卷积,这是keras.layers.Conv2D和keras.backend.Conv2D所需的输入秩。我的意思是,我希望能够使用[batch,W,H,C],而不是使用大小[batch,W,H,C],并且对于那些其他维度,基本上以与“batch”相同的方式处理(例如,不受卷积影响)。毫不奇怪,这会引发一个错误,因此重塑阵列似乎是最简单的解决方案,但是,这也存在一些问题(如下所述) 重塑时,我正在处理Keras所看到的批处理维度,因此我需要使用Ker

我正试图找到一种方法来对维度高于4的张量执行2D卷积,这是keras.layers.Conv2D和keras.backend.Conv2D所需的输入秩。我的意思是,我希望能够使用
[batch,W,H,C]
,而不是使用大小
[batch,W,H,C]
,并且对于那些其他维度,基本上以与“batch”相同的方式处理(例如,不受卷积影响)。毫不奇怪,这会引发一个错误,因此重塑阵列似乎是最简单的解决方案,但是,这也存在一些问题(如下所述)

重塑时,我正在处理Keras所看到的批处理维度,因此我需要使用Keras.backend.reforme,而不是Keras.layers.reforme,它似乎无法访问数据的批处理维度。通过使用lambda层和keras.backend.reformate,我们可以制作大小为
[batch*,W,H,C]
的输入数组,然后在执行卷积后再次将其重新整形但是,这一层可以构成完全卷积网络的一部分,这一网络可以处理任意大小的图像,这些图像具有未定义的W和H(在实例化输入层的形状时设置为None)。因此,我们最终将具有两个未定义空间维度的形状传递给keras.backend.reformate,它显然不能使用:
[批处理*,无,无,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)
正如预期的那样,第一次调用'Reformate_then_conv'是有效的,因为我们明确地设置了宽度和高度。然而,第二个例子给出了:

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

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

更新 多亏@dmoloy的回答,我将代码重新排列如下

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)

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

input.shape[1:3]  
K.shape(input)[1:3]
尝试提供动态形状,例如

input.shape[1:3]  
K.shape(input)[1:3]

非常感谢你!你的回答使我走上了正确的道路。还有一些额外的步骤,但这是关键。将Lambda重塑层更新为:
restraped=Lambda(Lambda x:K.restraped(x,K.concatenate((K.variable([-1],dtype=tf.int32),K.shape(input)[3:])))(input)