如何在 Keras 中获取图层的输出形状?

Posted

技术标签:

【中文标题】如何在 Keras 中获取图层的输出形状?【英文标题】:How to get the output shape of a layer in Keras? 【发布时间】:2018-09-06 16:55:19 【问题描述】:

我在 Keras 中有以下代码(基本上我正在修改此代码以供我使用)并且我收到此错误:

'ValueError: 检查目标时出错:预期 conv3d_3 有 5 个维度,但得到了形状为 (10, 4096) 的数组'

代码:

from keras.models import Sequential
from keras.layers.convolutional import Conv3D
from keras.layers.convolutional_recurrent import ConvLSTM2D
from keras.layers.normalization import BatchNormalization
import numpy as np
import pylab as plt
from keras import layers

# We create a layer which take as input movies of shape
# (n_frames, width, height, channels) and returns a movie
# of identical shape.

model = Sequential()
model.add(ConvLSTM2D(filters=40, kernel_size=(3, 3),
                   input_shape=(None, 64, 64, 1),
                   padding='same', return_sequences=True))
model.add(BatchNormalization())

model.add(ConvLSTM2D(filters=40, kernel_size=(3, 3),
                   padding='same', return_sequences=True))
model.add(BatchNormalization())

model.add(ConvLSTM2D(filters=40, kernel_size=(3, 3),
                   padding='same', return_sequences=True))
model.add(BatchNormalization())

model.add(ConvLSTM2D(filters=40, kernel_size=(3, 3),
                   padding='same', return_sequences=True))
model.add(BatchNormalization())

model.add(Conv3D(filters=1, kernel_size=(3, 3, 3),
               activation='sigmoid',
               padding='same', data_format='channels_last'))
model.compile(loss='binary_crossentropy', optimizer='adadelta')

我输入的数据格式如下:[1, 10, 64, 64, 1]。 所以我想知道我错在哪里以及如何查看每一层的 output_shape。

【问题讨论】:

【参考方案1】:

您可以通过layer.output_shape获取图层的输出形状。

for layer in model.layers:
    print(layer.output_shape)

给你:

(None, None, 64, 64, 40)
(None, None, 64, 64, 40)
(None, None, 64, 64, 40)
(None, None, 64, 64, 40)
(None, None, 64, 64, 40)
(None, None, 64, 64, 40)
(None, None, 64, 64, 40)
(None, None, 64, 64, 40)
(None, None, 64, 64, 1)

或者,您可以使用model.summary 漂亮地打印模型:

model.summary()

以漂亮的格式为您提供有关每个层的参数数量和输出形状以及整体模型结构的详细信息:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv_lst_m2d_1 (ConvLSTM2D)  (None, None, 64, 64, 40)  59200     
_________________________________________________________________
batch_normalization_1 (Batch (None, None, 64, 64, 40)  160       
_________________________________________________________________
conv_lst_m2d_2 (ConvLSTM2D)  (None, None, 64, 64, 40)  115360    
_________________________________________________________________
batch_normalization_2 (Batch (None, None, 64, 64, 40)  160       
_________________________________________________________________
conv_lst_m2d_3 (ConvLSTM2D)  (None, None, 64, 64, 40)  115360    
_________________________________________________________________
batch_normalization_3 (Batch (None, None, 64, 64, 40)  160       
_________________________________________________________________
conv_lst_m2d_4 (ConvLSTM2D)  (None, None, 64, 64, 40)  115360    
_________________________________________________________________
batch_normalization_4 (Batch (None, None, 64, 64, 40)  160       
_________________________________________________________________
conv3d_1 (Conv3D)            (None, None, 64, 64, 1)   1081      
=================================================================
Total params: 407,001
Trainable params: 406,681
Non-trainable params: 320
_________________________________________________________________

如果您只想访问特定层的信息,可以在构造该层时使用name 参数,然后像这样调用:

...
model.add(ConvLSTM2D(..., name='conv3d_0'))
...

model.get_layer('conv3d_0')

编辑: 作为参考,它始终与layer.output_shape 相同,请不要实际为此使用 Lambda 或自定义层。但是您可以使用Lambda 层来回显传递张量的形状。

...
def print_tensor_shape(x):
    print(x.shape)
    return x
model.add(Lambda(print_tensor_shape))
...

或者写一个自定义层,在call()上打印张量的形状。

class echo_layer(Layer):
...
    def call(self, x):
        print(x.shape)
        return x
...

model.add(echo_layer())

【讨论】:

我知道'model.summary()"和'layer.output_shape',其实我的意思是在输入数据后我想看看输出形状,换句话说,我不知道为什么我收到提到的错误:'ValueError:检查目标时出错:预期 conv3d_3 有 5 个维度,但得到了形状为 (10, 4096) 的数组' @MaryamRahmaniMoghaddam 你能再检查一下y 的形状吗,我在拟合x.shape = y.shape = (1, 10, 64, 64, 1) 时无法重现错误。通过查看错误 (10, 4096)。看起来您的输入或y 以某种方式变平了。如果是您的y,您可能需要重塑或更改模型的输出形状。 你是对的。我的“y”格式不正确。但现在我收到此错误“AttributeError:'ProgbarLogger'对象没有属性'log_values'”。您是否也遇到此错误? @MaryamRahmaniMoghaddam 不,我没有,但似乎与进度条相关的错误通常与训练/测试拆分和适合的验证参数有关(我没有给出)。检查this github thread 是否有类似错误。 @Vincent Param # 列表示该层的权重和其他可调整(在使用反向传播训练期间)参数。例如,简单密集层中的参数数量将计算为params = weights = output_size * (input_size + 1),其中 +1 是偏差。 ConvLSTM2D 层计算起来有点复杂。有时这些参数是静态的,或者在这种情况下(BatchNormalization 层)没有使用反向传播训练更新,而是使用使用方差和均值的统计方法进行更新,因此下面是 320 个不可训练的参数。

以上是关于如何在 Keras 中获取图层的输出形状?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过keras获得每个图层的输出值?

Keras - 获得训练层的权重

Keras:如何在编译期间输入形状未知时创建带权重的自定义图层?

如何在 Keras 中建模卷积循环网络 (CRNN)

Keras 密集层输出形状

AE如何让形状图层随另一层做运动效果