如何使用Keras将3D矩阵缩小为2D矩阵?

时间:2018-04-12 17:34:42

标签: machine-learning computer-vision keras conv-neural-network convolution

我已经构建了一个Keras ConvLSTM神经网络,我想根据一系列10个步骤预测前一帧:

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')

训练:

data_train_x = data_4[0:20, 0:10, :, :, :]
data_train_y = data_4[0:20, 10:11, :, :, :]

model.fit(data_train_x, data_train_y, batch_size=10, epochs=1, 
validation_split=0.05)

我测试了模型:

test_x = np.reshape(data_test_x[2,:,:,:,:], [1,10,64,64,1])
next_frame = model.predict(test_x,batch_size=1, verbose=1, steps=None)

但问题是'next_frame'的形状是:(1,10,64,64,1)但我希望它的形状(1,1,64,64,1)

这是'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

所以我不知道要添加哪个图层,所以我将输出减少到1帧而不是10帧?

2 个答案:

答案 0 :(得分:2)

这是基于最终层中的3D卷积所预期的。例如,如果在三维张量中的Conv2D中有1个滤镜,填充='相同',这意味着它将生成相同高度的 2D 输出宽度(例如,过滤器也隐含地沿深度轴捕获)。

对于四维张量中的3D也是如此,其中它沿着通道尺寸深度轴隐式捕获,导致与输入相同的三维张量(序列索引,高度,宽度)。 / p>

听起来你想要做的是在你的Conv3D层之后添加某种类型的池化步骤,使其在序列维度上变平,例如AveragePooling3D的池化元组为{{1}在第一个非批量维度上进行平均(或根据您的特定网络需求进行修改)。

或者,假设你想要特别" pool"通过仅采用最终序列元素沿着序列维度(例如,代替在序列上平均或最大汇集)。然后,您可以使最终的(10, 1, 1)图层具有ConvLSTM2D,然后在最后一步中进行2D卷积,但这意味着您的最终卷积不会从聚合预测帧序列中获益。可能是特定于应用程序,这是否是一个好主意。

为了确认第一种方法,我补充道:

return_sequences=False

model.add(layers.AveragePooling3D(pool_size=(10, 1, 1), padding='same')) 图层之后,然后制作玩具数据:

Conv3D

然后:

x = np.random.rand(1, 10, 64, 64, 1)

您需要确保将第一个非批量维度中的池大小设置为最大可能序列长度,以确保始终在最终输出形状中获得(1,1,...)。

答案 1 :(得分:1)

作为ely的Conv2DAveragePooling3D解决方案的替代方法,您可以将最后一个ConvLSTM2D层的return_sequence参数设置为True,但可以更改将Conv3D层设置为valid,然后将其kernel_size参数设置为(n_observations - k_steps_to_predict + 1 , 1 , 1)。这样,您就可以更改输出的time_dimension(#frames)。假设观测值的数量是固定的,则可以将其应用于任何直接的k步提前预测。