Keras Conv2D 的尺寸问题,然后是 LSTM

Dimension Issues with Keras Conv2D followed by LSTM

我正在尝试在 Python 3.5.2 中实现图像序列预测 |我的 windows 10 机器上的 Anaconda 4.2.0(64 位)。我有最新版本的keras和tensorflow。

每张图片都是 160x128。我的训练集是 1008 张图像,大小为 1008x160x128x1。我想用一个卷积层和一个 LSTM 层做一个简单的网络,现在,每个图像都被卷积以提取特征,然后输入 LSTM 以学习时间依赖性。输出应该是 k(在 k=1 以下的情​​况下)预测图像,大小为 160x128。下面是代码以及 model.summary().

我的卷积层的输出是 4 维的 (None, 79, 63, 32)。所以我重塑输出,使其成为 (None, 32, 79*63) 并且是 LSTM 层的正确维数(尽管我认为这是在幕后处理的...)。然后模型编译没有错误(如果我没有做重塑然后抛出尺寸错误)。

因为我训练数据的每个元素每个样本只有1个时间点,所以我没有在卷积层上使用TimeDistributed(经过大量研究,似乎是解决方案)。但是,我相信对于输出层,所有样本都聚集在一起,所以有多少样本就有多少时间点,并且要使用 TimeDistributed。如果我这样做,则会收到以下错误:

Traceback (most recent call last): File "C:\seqn_pred\read_images_dataset.py", line 104, in model.fit(train_x, train_y, epochs = 10, batch_size = 1, verbose = 1) File "c:\users\l\anaconda3\lib\site-packages\keras\engine\training.py", line 950, in fit batch_size=batch_size) File "c:\users\l\anaconda3\lib\site-packages\keras\engine\training.py", line 787, in _standardize_user_data exception_prefix='target') File "c:\users\l\anaconda3\lib\site-packages\keras\engine\training_utils.py", line 137, in standardize_input_data str(data_shape)) ValueError: Error when checking target: expected time_distributed_62 to have shape (32, 1) but got array with shape (128, 160)

我搜索了 Whosebug 上的所有相关帖子,并尝试了所有相关的“解决方案”,但均未成功。当我尝试计算 units = 160*128 时,形状 (32, 160*128) 与 (128, 160) 再次出现问题。此外,我试图将目标数据重塑为 1008x(160*128)x1(因为 TimeDistributed 需要 3-d 数据以及展平每个目标)以获得另一个错误

ValueError: Error when checking target: expected time_distributed_64 to have shape (32, 20480) but got array with shape (20480, 1)

我也尝试过 运行 最后一层没有 TimeDistributed,但我仍然收到关于目标形状的错误。

ValueError: Error when checking target: expected dense_1 to have shape (32, 1) but got array with shape (160, 128)

主要问题是 shape/dimension 卷积层和 LSTM 层之间以及最终的密集层。任何帮助将不胜感激。

train_x, test_x = [D2[i] for i in rand_indx], [D2[i] for i in range(N-1) if i not in rand_indx]
train_y, test_y = [D2[i+1] for i in rand_indx], [D2[i+1] for i in range(N-1) if i not in rand_indx]

train_x = np.array(train_x)
train_x = train_x.reshape(len(train_x), n, m,1)
train_y = np.array(train_y)
train_y = train_y.reshape(train_y.shape[0], train_y.shape[1]*train_y.shape[2], 1)

model = Sequential()
#model.add(TimeDistributed(Conv2D(filters = 32, kernel_size = (3,3), strides = (1,1), activation = 'relu', padding = 'valid', input_shape = (1, n, m, 1))))
#model.add(TimeDistributed(MaxPooling2D(pool_size = (3,3))))
#model.add(TimeDistributed(Dropout(0.30)))
#model.add(TimeDistributed(Flatten()))
model.add(Conv2D(filters = 32, kernel_size = (3,3), strides = (1,1), activation = 'relu', padding = 'valid', input_shape = (n, m, 1)))
model.add(MaxPooling2D(pool_size = (2,2)))
model.add(Dropout(0.30))
model.add(Reshape((32,-1)))
model.add(LSTM(units = 20, activation = 'relu', return_sequences = True))
model.add(Dropout(0.1))
model.add(TimeDistributed(Dense(1, activation = 'relu')))
optim = krs.optimizers.Adam(lr = 0.375)
model.compile(loss = 'mse', optimizer = optim)
model.fit(train_x, train_y, epochs = 10, batch_size = 1, verbose = 1)

model.summary()

Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_73 (Conv2D)           (None, 158, 126, 32)      320       
_________________________________________________________________
max_pooling2d_53 (MaxPooling (None, 79, 63, 32)        0         
_________________________________________________________________
dropout_93 (Dropout)         (None, 79, 63, 32)        0         
_________________________________________________________________
reshape_13 (Reshape)         (None, 32, 4977)          0         
_________________________________________________________________
lstm_57 (LSTM)               (None, 32, 20)            399840    
_________________________________________________________________
dropout_94 (Dropout)         (None, 32, 20)            0         
_________________________________________________________________
dense_44 (Dense)             (None, 32, 1)             21        
=================================================================
Total params: 400,181
Trainable params: 400,181
Non-trainable params: 0
_________________________________________________________________

我对您要在这里实现的目标感到有点困惑。这是我的 2 美分。

输入:(1008、160、128、1)

输出:(1008, 160*128)

如果你有一个单一的输出目标,你不应该在 LSTM 层中使用 return_sequences=True,也不需要 TimeDistributed 层。最后一位需要更改如下。

model.add(Reshape((32,-1)))
model.add(LSTM(units = 20, activation = 'relu'))
model.add(Dropout(0.1))
model.add(Dense(160*128, activation = 'relu'))

如果进行上述更改,您可以使用具有上述输入和输出形状的数据训练模型。

但是,您可能需要考虑一些危险信号。

  • 重塑卷积输出的方式。目的是什么?您是否希望每个通道都成为模型的单独输入,如果是这样,您首先需要交换输入的轴,以便通道维度保持原样。因为你现在这样做的方式(在我看来)向 LSTM 层发送了一些非常随机的东西。这是我提议的更改
model.add(Permute([3,1,2]))
model.add(Dropout(0.30))
model.add(Reshape((32,-1)))