如何更改Keras示例代码model.fit到生成器的方式?

如何更改Keras示例代码model.fit到生成器的方式?,keras,lstm,Keras,Lstm,我试图用Keras实现CNN+RNN+LSTM结构(1) 我发现了一个相关的Keras 如何将model.fit正确转换为model.fit\u生成器 原始代码: from keras.models import Sequential from keras.layers import Activation, MaxPooling2D, Dropout, LSTM, Flatten, Merge, TimeDistributed import numpy as np from keras.la

我试图用Keras实现CNN+RNN+LSTM结构(1)

我发现了一个相关的Keras

如何将model.fit正确转换为model.fit\u生成器

原始代码:

from keras.models import Sequential
from keras.layers import Activation, MaxPooling2D, Dropout, LSTM, Flatten, Merge, TimeDistributed
import numpy as np

from keras.layers import Concatenate

from keras.layers.convolutional import Conv2D

# Generate fake data
# Assumed to be 1730 grayscale video frames
x_data = np.random.random((1730, 1, 8, 10))

sequence_lengths = None


Izda=Sequential()
Izda.add(TimeDistributed(Conv2D(40,(3,3),padding='same'), input_shape=(sequence_lengths, 1,8,10)))
Izda.add(Activation('relu'))
Izda.add(TimeDistributed(MaxPooling2D(data_format="channels_first", pool_size=(2, 2))))
Izda.add(Dropout(0.2))

Dcha=Sequential()
Dcha.add(TimeDistributed(Conv2D(40,(3,3),padding='same'), input_shape=(sequence_lengths, 1,8,10)))
Dcha.add(Activation('relu'))
Dcha.add(TimeDistributed(MaxPooling2D(data_format="channels_first", pool_size=(2, 2))))
Dcha.add(Dropout(0.2))

Frt=Sequential()
Frt.add(TimeDistributed(Conv2D(40,(3,3),padding='same'), input_shape=(sequence_lengths, 1,8,10)))
Frt.add(Activation('relu'))
Frt.add(TimeDistributed(MaxPooling2D(data_format="channels_first", pool_size=(2, 2))))
Frt.add(Dropout(0.2))

merged=Merge([Izda, Dcha,Frt], mode='concat', concat_axis=2)
#merged=Concatenate()([Izda, Dcha, Frt], axis=2)
# Output from merge is (batch_size, sequence_length, 120, 4, 5)
# We want to get this down to (batch_size, sequence_length, 120*4*5)

model=Sequential()
model.add(merged)
model.add(TimeDistributed(Flatten()))
model.add(LSTM(240, return_sequences=True))

model.compile(loss='mse', optimizer='adam')
model.summary()
修改后:

from keras.models import Sequential
from keras.layers import Activation, MaxPooling2D, Dropout, LSTM, Flatten, Merge, TimeDistributed
import numpy as np

from keras.layers import Concatenate

from keras.layers.convolutional import Conv2D

# Generate fake data
# Assumed to be 1730 grayscale video frames
x_data = np.random.random((1730, 1, 8, 10))

sequence_lengths = None

def defModel():

    model=Sequential()
    model.add(TimeDistributed(Conv2D(40,(3,3),padding='same'), input_shape=(sequence_lengths, 1,8,10)))
    model.add(Activation('relu'))
    model.add(TimeDistributed(MaxPooling2D(data_format="channels_first", pool_size=(2, 2))))
    model.add(Dropout(0.2))

    model.add(TimeDistributed(Flatten()))
    model.add(LSTM(240, return_sequences=True))

    model.compile(loss='mse', optimizer='adam')
    model.summary()
    return model


def gen():
    for i in range(1730):
        x_train = np.random.random((1, 8, 10))
        y_train = np.ones((15, 240))
        yield (x_train, y_train)

def main():
    model = defModel()

    # Slice our long, single sequence up into shorter sequeunces of images
    # Let's make 50 examples of 15 frame videos
    x_train = []
    seq_len = 15
    for i in range(50):
        x_train.append(x_data[i*5:i*5+seq_len, :, :, :])
    x_train = np.asarray(x_train, dtype='float32')
    print(x_train.shape)
    # >> (50, 15, 1, 8, 10)

    model.fit_generator(
        generator = gen(),
        steps_per_epoch = 1,
        epochs = 2)



if __name__ == "__main__":
    main()
如何解决因修改而产生的此错误

ValueError:检查输入时出错:应为 time_分配_1_输入为5维,但得到的数组为 形状(1,8,10)

(1) 王绍,克拉克,R.,文,H.,和三角洲,N.(2017)。DeepVO:使用深度递归卷积神经网络实现端到端视觉里程测量。IEEE机器人和自动化国际会议记录,2043-2050年

更新:连接CNN和LSTM作为示例代码 出错 ValueError:检查目标时出错:预期lstm_1有3个维度,但得到了形状为(4,3)的数组

更新2 目标是通过CNN提取图像特征,然后将3幅图像中的3个特征组合起来,并输入LSTM

目标 模型 发电机 然后我仍然得到了错误:

ValueError:检查目标时出错:预期lstm_1有3个维度,但得到了形状为(1,3)的数组


问题是一个简单的形状不匹配问题

您定义了
input\u shape=(sequence\u length,1,8,10)
,因此您的模型需要五个维度作为输入:
(batch\u size,sequence\u length,1,8,10)

所有您需要的是使您的发电机输出正确的形状与5维

def gen():
    x_data = np.random.random((numberOfVideos, videoLength, 1, 8, 10))
    y_data = np.ones((numberOfVideos, videoLength, 240))

    for video in range(numberOfVideos):
        x_train = x_data[video:video+1]
        y_train = y_data[video:video+1]
        yield (x_train, y_train)

问题是一个简单的形状不匹配问题

您定义了
input\u shape=(sequence\u length,1,8,10)
,因此您的模型需要五个维度作为输入:
(batch\u size,sequence\u length,1,8,10)

所有您需要的是使您的发电机输出正确的形状与5维

def gen():
    x_data = np.random.random((numberOfVideos, videoLength, 1, 8, 10))
    y_data = np.ones((numberOfVideos, videoLength, 240))

    for video in range(numberOfVideos):
        x_train = x_data[video:video+1]
        y_train = y_data[video:video+1]
        yield (x_train, y_train)

以下是CNNLSTM使用生成器的工作示例:

以下是CNNLSTM使用生成器的工作示例:

上述解决方案解决了错误!在将示例代码修改为类似DeepVO的结构之后,我遇到了另一个错误。(详细内容见原始问题的更新部分。)Fattern函数是否输出一个可能与LSTM匹配的向量?该错误与“目标”(模型的最终输出)有关。您的LSTM具有
return\u sequences=True
,因此它输出
(批、长度、输出\u特性)
。但您的数据似乎只有
(批处理、输出功能)
。要么数据错误,要么您需要删除
返回\u序列
以仅输出
(批处理,功能)
“但是得到了形状为(4,3)的数组”超出了我的预期。压扁层后张量的尺寸不应该被压缩到(n)吗?为什么我仍然得到(n,m)维?这是
y\u train
。但是在展平后你得到
(批次、长度、特征)
,因为它是时间分布的。如果它是单独的,您将获得
(批处理,功能)
。上面的解决方案解决了错误!在将示例代码修改为类似DeepVO的结构之后,我遇到了另一个错误。(详细内容见原始问题的更新部分。)Fattern函数是否输出一个可能与LSTM匹配的向量?该错误与“目标”(模型的最终输出)有关。您的LSTM具有
return\u sequences=True
,因此它输出
(批、长度、输出\u特性)
。但您的数据似乎只有
(批处理、输出功能)
。要么数据错误,要么您需要删除
返回\u序列
以仅输出
(批处理,功能)
“但是得到了形状为(4,3)的数组”超出了我的预期。压扁层后张量的尺寸不应该被压缩到(n)吗?为什么我仍然得到(n,m)维?这是
y\u train
。但是在展平后你得到
(批次、长度、特征)
,因为它是时间分布的。如果它是单独的,您将获得
(批处理,功能)
model = Sequential()
model.add(TimeDistributed(Conv2D(16, (7, 7), padding='same'),input_shape=(None, 540, 960, 1)))
model.add(Activation('relu'))

model.add(TimeDistributed(Conv2D(32, (5, 5), padding='same')))
model.add(Activation('relu'))

model.add(TimeDistributed(Flatten()))
model.add(LSTM(num_classes, return_sequences=True))

model.compile(loss='mean_squared_error', optimizer='adam')
a = readIMG(filenames[start])  # (540, 960, 1)
b = readIMG(filenames[start + 1])  # (540, 960, 1)
c = readIMG(filenames[start + 2])  # (540, 960, 1)
x_train = np.array([[a, b, c]])  # (1, 3, 540, 960, 1)
def gen():
    x_data = np.random.random((numberOfVideos, videoLength, 1, 8, 10))
    y_data = np.ones((numberOfVideos, videoLength, 240))

    for video in range(numberOfVideos):
        x_train = x_data[video:video+1]
        y_train = y_data[video:video+1]
        yield (x_train, y_train)