【问题标题】:How to create a Keras layer to do a 4D convolutions (Conv4D)?如何创建一个 Keras 层来进行 4D 卷积(Conv4D)?
【发布时间】:2020-03-20 21:47:33
【问题描述】:

看来tf.nn.convolution应该可以做4D卷积,但是我一直没能成功创建一个Keras层来使用这个功能。

我曾尝试使用 Keras Lambda 层来包装 tf.nn.convolution 函数,但也许其他人有更好的主意?

我想利用数据的高维结构,因此重塑可能无法捕捉数据集的本质。

【问题讨论】:

    标签: tensorflow keras conv-neural-network convolution


    【解决方案1】:

    超酷的问题。

    这需要一个自定义层(带有可训练的参数)。
    以下接受任意数量的维度,您可以通过kernel_size 进行控制。

    class Conv(Layer):
        def __init__(self, filters, kernel_size, padding='VALID', **kwargs):
            self.filters = filters
            self.kernel_size = kernel_size #must be a tuple!!!!
            self.padding=padding
    
            super(Conv, self).__init__(**kwargs)
    
        #using channels last!!!
        def build(self, input_shape):
            spatialDims = len(self.kernel_size)
            allDims = len(input_shape)
            assert allDims == spatialDims + 2 #spatial dimensions + batch size + channels
    
            kernelShape = self.kernel_size + (input_shape[-1], self.filters)
                #(spatial1, spatial2,...., spatialN, input_channels, output_channels)
    
            biasShape = tuple(1 for _ in range(allDims-1)) + (self.filters,)
    
    
            self.kernel = self.add_weight(name='kernel', 
                                          shape=kernelShape
                                          initializer='uniform',
                                          trainable=True)
            self.bias = self.add_weight(name='bias', 
                                        shape = biasShape, 
                                        initializer='zeros',
                                        trainable=True)
            self.built = True
    
        def call(self, inputs):
            results = tf.nn.convolution(inputs, self.kernel, padding=self.padding)
            return results + self.bias
    
        def compute_output_shape(self, input_shape)
            sizes = input_shape[1:-1]
    
            if self.padding='VALID' or self.padding='valid':
                sizes = [s - kSize + 1 for s, kSize in zip(sizes, self.kernel_size)]
    
            return input_shape[:1] + sizes + (self.filters,)
    

    【讨论】:

    • 不幸的是,我在冠状病毒疯狂开始时就问了这个问题,并且在尝试工作的同时照顾一个年轻人并不容易,所以我无法测试您的解决方案(该项目的目前优先),但我非常感谢您的回答。我只是不想让更多的时间过去而不说谢谢。谢谢!
    • 很好的答案。我也会试一试。您能否举例说明如何将其与 4D 数据一起使用?是否可以像往常一样使用 dropout 和批量标准化,还是必须重新实现它们?
    • @machinery,内核大小必须为 4D。示例:kernel_size = (k1, k2, k3, k4)。您的数据自然必须是 6D(与任何 keras 卷积一样,样本额外 1 个,通道额外 1 个)。 data_shape = (samples, d1, d2, d3, d4, channels)。模型的input_shape,通常忽略batch size必须是5D(无样本)或6D(有样本):input_shape = (d1_or_None, d2_or_None, d3_or_None, d4_or_None, channels)
    • @machinery,您可以像往常一样使用常规 dropout 和批量标准化。对于SpatialDropout,必须重新实现。您可以查看SpatialDropout2D3D 的代码,您可以轻松推断出如何将其扩展到更多D。 github.com/keras-team/keras/blob/…
    • 不幸的是,它不适用于 TF 2.3,其中 tf.nn.convolution 仅处理 Conv1D、Conv2D 或 Conv3D。 (num_spatial_dims (input.shape.ndims - num_batch_dims - 1) must be one of 1, 2 or 3)
    【解决方案2】:

    你说得对,目前对 Tensorflow Conv4D 的支持并不多。 我编写了这个 repo (https://github.com/Vincentx15/Conv4D) 来解决这个问题并包括灵活的跨步和填充。

    它添加了对 Sonnet 的轻量级依赖以使用高级填充,但这应该无缝地融合到 tensorflow 代码中。

    最好的:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多