Keras Conv2D和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维的(无,79、63、32)。因此,我调整了输出的形状,使其为(None,32,79 * 63),并且是LSTM层的正确尺寸数(尽管我认为这是在后台进行的……)。然后,该模型将编译而没有错误(如果我不进行重塑,则会引发尺寸错误)。

因为训练数据的每个元素每个样本只有1个时间点,所以我不在卷积层上使用Timedistributed(经过大量研究,看来这就是解决方案)。但是,我相信对于输出层而言,所有样本都聚集在一起,因此存在的时间点与样本数一样多,并且将使用Timedistributed。如果这样做,则会出现以下错误

回溯(最近通话最近): 第104行中的文件“ C:\ seqn_pred \ read_images_dataset.py” model.fit(train_x,train_y,历元= 10,batch_size = 1,详细= 1) 适合的文件“ c:\ users \ l \ anaconda3 \ lib \ site-packages \ keras \ engine \ training.py”,行950 batch_size =批量大小) _standardize_user_data中的文件“ c:\ users \ l \ anaconda3 \ lib \ site-packages \ keras \ engine \ training.py”,行787 exception_prefix ='目标') 文件“ c:\ users \ l \ anaconda3 \ lib \ site-packages \ keras \ engine \ training_utils.py”,第137行,位于standardize_input_data中 str(数据形状)) ValueError:检查目标时出错:预期time_distributed_62具有形状(32,1),但形状为(128,160)的数组

搜索了关于stackoverflow的所有相关帖子,并尝试了所有相关的“解决方案”,但均未成功。当我尝试做单位= 160 * 128时,形状(32,160 * 128)与(128,160)再次存在问题。此外,我尝试将目标数据的形状重塑为1008x(160 * 128)x1(因为Timedistributed需要3d数据并展平每个目标),以获得另一个错误

ValueError:检查目标时出错:预期time_distributed_64具有形状(32,20480),但数组具有形状(20480,1)

我也试图在没有Timedistributed的情况下运行最后一层,但是仍然收到关于目标形状的错误

ValueError:检查目标时出错:预期density_1具有形状(32,1),但形状为(160,128)的数组

主要问题是卷积和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,1))))
#model.add(Timedistributed(MaxPooling2D(pool_size = (3,3))))
#model.add(Timedistributed(Dropout(0.30)))
#model.add(Timedistributed(Flatten()))
model.add(Conv2D(filters = 32,input_shape = (n,1)))
model.add(MaxPooling2D(pool_size = (2,2)))
model.add(Dropout(0.30))
model.add(Reshape((32,-1)))
model.add(LSTM(units = 20,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,32)        0         
_________________________________________________________________
reshape_13 (Reshape)         (None,32,4977)          0         
_________________________________________________________________
lstm_57 (LSTM)               (None,20)            399840    
_________________________________________________________________
dropout_94 (Dropout)         (None,20)            0         
_________________________________________________________________
dense_44 (Dense)             (None,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)))