### Keras自定义层每次接收相同的输入形状

我在Keras中编写OctConv卷积层,扩展了Keras的层,编写的代码如下。

import keras.backend as Kfrom keras.layers import Layer, UpSampling2D, Add, Concatenate, Conv2D, Conv2DTransposeclass OCTCONV_LAYER(Layer):    def __init__(self,            filters=16,            kernel_size=(3, 3),            strides=(2, 2),            dilation_rate=(1, 1),            padding='same',            alpha_in=0.6,            alpha_out=0.6,            **kwargs        ):        self.filters = filters        self.kernel_size = kernel_size        self.strides = strides        self.padding = padding        self.alpha_in = alpha_in        self.alpha_out = alpha_out        if dilation_rate[0] > 1:            self.strides = (1, 1)        self.dilation_rate = dilation_rate        super(OCTCONV_LAYER, self).__init__(**kwargs)    def build(self, input_shape):        print('INPUT_SHAPE : {}'.format(input_shape))        op_channels = self.filters        low_op_channels = int(op_channels*self.alpha_out)        high_op_channels = op_channels-low_op_channels        inp_channels = input_shape[-1]        low_inp_channels = int(inp_channels*self.alpha_in)        high_inp_channels = inp_channels-low_inp_channels        self.h_2_l = self.add_weight(            name='hl',            shape=self.kernel_size + (high_inp_channels, low_op_channels),            initializer='he_normal'        )        self.h_2_h = self.add_weight(            name='hh',            shape=self.kernel_size + (high_inp_channels, high_op_channels),            initializer='he_normal'        )        self.l_2_h = self.add_weight(            name='lh',            shape=self.kernel_size + (low_inp_channels, high_op_channels),            initializer='he_normal'        )        self.l_2_l = self.add_weight(            name='ll',            shape=self.kernel_size + (low_inp_channels, low_op_channels),            initializer='he_normal'        )        print('High 2 low : {}'.format(self.h_2_l.shape))        print('High 2 high : {}'.format(self.h_2_h.shape))        print('Low 2 high : {}'.format(self.l_2_h.shape))        print('Low 2 low : {}'.format(self.l_2_l.shape))        super(OCTCONV_LAYER, self).build(input_shape)    def call(self, x):        inp_channels = int(x.shape[-1])        low_inp_channels = int(inp_channels*self.alpha_in)        high_inp_channels = inp_channels-low_inp_channels        high_inp = x[:,:,:, :high_inp_channels]        print('High input shape : {}'.format(high_inp.shape))        low_inp = x[:,:,:, high_inp_channels:]        low_inp = K.pool2d(low_inp, (2, 2), strides=(2, 2), pool_mode='avg')        print('Low input shape : {}'.format(low_inp.shape))        out_high_high = K.conv2d(high_inp, self.h_2_h, strides=(2, 2), padding='same')        print('OUT HIGH HIGH shape : {}'.format(out_high_high.shape))        out_low_high = UpSampling2D((2, 2))(K.conv2d(low_inp, self.l_2_h, strides=(2, 2), padding='same'))        print('OUT LOW HIGH shape : {}'.format(out_low_high.shape))        out_low_low = K.conv2d(low_inp, self.l_2_l, strides=(2, 2), padding='same')        print('OUT LOW LOW shape : {}'.format(out_low_low.shape))        out_high_low = K.pool2d(high_inp, (2, 2), strides=(2, 2), pool_mode='avg')        out_high_low = K.conv2d(out_high_low, self.h_2_l, strides=(2, 2), padding='same')        print('OUT HIGH LOW shape : {}'.format(out_high_low.shape))        out_high = Add()([out_high_high, out_low_high])        print('OUT HIGH shape : {}'.format(out_high.shape))        out_low = Add()([out_low_low, out_high_low])        out_low = UpSampling2D((2, 2))(out_low)        print('OUT LOW shape : {}'.format(out_low.shape))        out_final = K.concatenate([out_high, out_low], axis=-1)        print('OUT SHAPE : {}'.format(out_final.shape))        out_final._keras_shape = self.compute_output_shape(out_final.shape)        return out_final    def compute_output_shape(self, inp_shape):        return inp_shape

为了创建层,我使用以下代码来创建模型

from keras.layers import Inputinp = Input(shape=(224, 224, 3))x = OCTCONV_LAYER(filters=16)(inp)x = OCTCONV_LAYER()(x)...

控制台上的输出是,

enter image description here

如您所见,最后一层的输入形状与输入层相同,而第一个OctConv层的输出形状不是输入形状。代码有什么问题吗?我是不是遗漏了什么?


回答:

您的代码可能没问题。似乎存在与K.conv2d相关的问题,如这个回答中观察到的那样。一个解决方法是从tensorflow导入keras(例如,将所有keras导入更改为tensorflow.keras)。

然后您需要进行以下更改:

low_inp_channels = int(int(inp_channels) * self.alpha_in)high_inp_channels = int(inp_channels) - low_inp_channels

在这种情况下,第二个OCTCONV_LAYER的输入维度与第一个OCTCONV_LAYER的输出维度相对应。经过之前的更改,结果是:

第一层

INPUT_SHAPE : (?, 224, 224, 3)High 2 low : (3, 3, 2, 9)High 2 high : (3, 3, 2, 7)Low 2 high : (3, 3, 1, 7)Low 2 low : (3, 3, 1, 9)High input shape : (?, 224, 224, 2)Low input shape : (?, 112, 112, 1)OUT HIGH HIGH shape : (?, 112, 112, 7)OUT LOW HIGH shape : (?, 112, 112, 7)OUT LOW LOW shape : (?, 56, 56, 9)OUT HIGH LOW shape : (?, 56, 56, 9)OUT HIGH shape : (?, 112, 112, 7)OUT LOW shape : (?, 112, 112, 9)OUT SHAPE : (?, 112, 112, 16)

第二层

INPUT_SHAPE : (?, 112, 112, 16)High 2 low : (3, 3, 7, 9)High 2 high : (3, 3, 7, 7)Low 2 high : (3, 3, 9, 7)Low 2 low : (3, 3, 9, 9)High input shape : (?, 112, 112, 7)Low input shape : (?, 56, 56, 9)OUT HIGH HIGH shape : (?, 56, 56, 7)OUT LOW HIGH shape : (?, 56, 56, 7)OUT LOW LOW shape : (?, 28, 28, 9)OUT HIGH LOW shape : (?, 28, 28, 9)OUT HIGH shape : (?, 56, 56, 7)OUT LOW shape : (?, 56, 56, 9)OUT SHAPE : (?, 56, 56, 16)

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注