如何使用 CNN+LSTM 的 TimeDistributed?

数据挖掘 喀拉斯 张量流 时间序列 美国有线电视新闻网 lstm
2022-02-14 12:06:44

我正在尝试对大小为 3601x217 像素的 6 类时频域信号(STFT 频谱图)进行分类。假设每个类有 70 个训练样本、20 个验证样本和 10 个测试样本。每个样本都是大小为 3601x217x1(灰度)的 PNG 图像,而在未来我正在考虑将其扩展到 3601x217x4(3 个颜色通道 + alpha)。但现在,我首先关注的是灰度。

在尝试了纯 LSTM 之后,我发现模型很快过拟合(训练准确率 > 90%,但 val_acc 停留在 20%)。ow 我想试试时间分布式 CNN+LSTM。

以下是代码:

img_width, img_height = 3601,217
train_data_dir = 'sensor1/training'
validation_data_dir = 'sensor1/validation'

num_classes = 6
nb_train_samples = 70
nb_validation_samples = 20
epochs = 50
batch_size = 5

if K.image_data_format() == 'channels_first':
    input_shape = (3, img_width, img_height)
else:
    input_shape = (img_width, img_height, 3)

model = Sequential()
model.add(TimeDistributed(Conv2D(16, (3,3), padding='same', strides=(2,2), activation='relu', input_shape = input_shape)))
model.add(TimeDistributed(MaxPooling2D(pool_size=(2, 2))))
model.add(Dropout(0.5))
model.add(TimeDistributed(Conv2D(32, (3,3), padding='same', strides=(2,2), activation='relu')))
model.add(TimeDistributed(MaxPooling2D(pool_size=(2, 2))))
model.add(Dropout(0.5))
model.add(TimeDistributed(Conv2D(64, (3,3), padding='same', strides=(2,2), activation='relu')))
model.add(TimeDistributed(MaxPooling2D(pool_size=(2, 2))))
model.add(Dropout(0.5))
model.add(TimeDistributed(Flatten()))
model.add(LSTM(units=128, return_sequences=False))
model.add(LSTM(units=64, return_sequences=False))
model.add(Dense(32))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

train_datagen = ImageDataGenerator(rescale = 1. / 255)
test_datagen = ImageDataGenerator(rescale = 1. / 255)

train_generator = train_datagen.flow_from_directory(
    train_data_dir, target_size=(img_width, img_height),
    batch_size=batch_size, color_mode='grayscale')

validation_generator = test_datagen.flow_from_directory(
    validation_data_dir, target_size=(img_width, img_height),
    batch_size=batch_size, color_mode='grayscale')

model.fit_generator(
    train_generator, steps_per_epoch=nb_train_samples // batch_size,
    epochs=epochs, callbacks=[plot_losses],
    validation_data=validation_generator,
    validation_steps=nb_validation_samples // batch_size)

代码给出以下错误:

_make_train_function 中的文件“C:\ProgramData\Anaconda3\lib\site-packages\keras\engine\training.py”,第 496 行引发 RuntimeError('您必须在使用之前编译模型。')

RuntimeError:您必须在使用模型之前对其进行编译。

代码有什么问题?我实际上是在调用 model.fit_generator 之前编译了模型:

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
1个回答

您正在指定图层 input_shape内部,这意味着:Conv2Dmodel.add(TimeDistributed(Conv2D(16, (3,3), padding='same', strides=(2,2), activation='relu', input_shape = input_shape)))

相反,你应该写: model.add(TimeDistributed(Conv2D(16, (3,3), padding='same', strides=(2,2), activation='relu'), input_shape = input_shape))

或更清楚地说: model.add(TimeDistributed(Conv2D(...), input_shape=input_shape))

此外,我应该注意到您正在使用 aTimeDistributed和 a Conv2D这意味着你input_shape应该是这样的(timesteps, dim1_size, dim2_size, n_channels)

您正在使用:input_shape=(img_width, img_height, 3)

如果你想img_width使用timesteps你应该使用TimeDistributedConv1D.

总而言之,始终认为一个层为其参数层TimeDistibuted的 i 添加了一个额外的维度。nput_shape

最后,您的第一LSTMreturn_sequences=False将引发错误。你必须给它一个True值。