Python:如何解决为预测未来帧序列而开发的变分自动编码器卷积模型的低精度问题?

Python: How to solve the low accuracy of a Variational Autoencoder Convolutional Model developed to predict a sequence of future frames?

我目前正在开发降水单元位移预测模型。我已将其作为实现变分卷积自动编码器的模型(附上模型代码)。总之,该模型接收到 5 张图像的序列,并且必须预测以下 5 张图像。该架构由编码器和解码器 (Conv Transpose) 中的五个卷积层组成,这些层可大大减小图像尺寸并学习空间细节。在编码器和解码器之间承载 ConvLSTM 层以学习时间序列。我正在 Python 中使用 tensorflow 和 keras 进行处理。

数据由"images"个400x400像素的测雨雷达组成,背景较暗,画面中央有雨点。帧与帧之间的时间为5分钟,雷达配置。进一步处理后,训练数据在 0 和 1 之间缩放,并采用 numpy 格式(用于处理矩阵)。我的训练数据最终具有 [序列数,每个序列的图像数,高度,宽度,通道 = 1] 的形式。

Sequence of precipitation Images

序列由:5 个输入和 5 个目标组成,其中有 2111 个雷达图像序列(我知道我没有太多数据 :( 用于训练),80% 已用于训练和20% 用于验证。 详情:

  1. train_input = [1688, 5, 400, 400, 1]
  2. train_target = [1688, 5, 400, 400, 1]
  3. valid_input = [423, 5, 400, 400, 1]
  4. valid_target = [423, 5, 400, 400, 1]

问题是我训练了我的模型,得到的值精度很差。大约 8e-05。我已经训练了 400 个纪元,该值保持或围绕上述值。此外,当我拍摄 5 张图像序列来预测接下来的 5 张图像时,我得到的结果非常糟糕(甚至没有在中心形成 "spots" 的小阵型,代表下雨)。我已经尝试减少编码器和解码器中的层数,除了优化器 [adam, nadam, adadelta],我还尝试使用激活函数 [relu, elu]。在预测图像和准确值方面,我还没有获得任何有利可图的结果。

Loss and Accuracy during Training

我是深度学习主题的初学者,我很喜欢它,但是我找不到解决这个问题的方法。我怀疑我的模型架构不对。除此之外,我应该寻找更好的优化器或激活函数来提高准确度值和预测图像。作为最后的解决方案,也许将 400x400 像素的图像剪切到降水所在的中心区域。虽然我会丢失训练数据。

感谢您能帮助我解决这个问题,也许可以给我一些组织架构模型的想法,或者组织去训练数据的想法。 最好的问候。

    # Encoder

    seq = Sequential()

    seq.add(Input(shape=(5, 400, 400,1)))

    seq.add(Conv3D(filters=32, kernel_size=(11, 11, 5), strides=3,
                   padding='same', activation ='relu'))
    seq.add(BatchNormalization())

    seq.add(Conv3D(filters=32, kernel_size=(9, 9, 32), strides=2,
                   padding='same', activation ='relu'))
    seq.add(BatchNormalization())

    seq.add(Conv3D(filters=64, kernel_size=(7, 7, 32), strides=2,
                   padding='same', activation ='relu'))
    seq.add(BatchNormalization())

    seq.add(Conv3D(filters=64, kernel_size=(5, 5, 64), strides=2,
                   padding='same', activation ='relu'))
    seq.add(BatchNormalization())

    seq.add(Conv3D(filters=32, kernel_size=(3, 3, 64), strides=3,
                   padding='same', activation ='relu'))
    seq.add(BatchNormalization())

    # ConvLSTM Layers

    seq.add(ConvLSTM2D(filters=40, kernel_size=(3, 3),
    input_shape=(None, 6, 6, 32),
    padding='same', return_sequences=True))
    seq.add(BatchNormalization())

    seq.add(ConvLSTM2D(filters=40, kernel_size=(3, 3),
    padding='same', return_sequences=True))
    seq.add(BatchNormalization())

    seq.add(ConvLSTM2D(filters=40, kernel_size=(3, 3),
    padding='same', return_sequences=True))
    seq.add(BatchNormalization())

    seq.add(ConvLSTM2D(filters=40, kernel_size=(3, 3),
    padding='same', return_sequences=True))
    seq.add(BatchNormalization())

    seq.add(Conv3D(filters=32, kernel_size=(3, 3, 3),
    activation='relu',
    padding='same', data_format='channels_last'))

    # Decoder

    seq.add(Conv3DTranspose(filters=32, kernel_size=(3, 3, 64), strides=(2,3,3),
                                      input_shape=(1, 6, 6, 32),
                                      padding='same', activation ='relu'))
    seq.add(BatchNormalization())

    seq.add(Conv3DTranspose(filters=64, kernel_size=(5, 5, 64), strides=(3,2,2),
                                      padding='same', activation ='relu'))
    seq.add(BatchNormalization())

    seq.add(Conv3DTranspose(filters=64, kernel_size=(7, 7, 32), strides=(1,2,2),
                                      padding='same', activation ='relu'))
    seq.add(BatchNormalization())

    seq.add(Conv3DTranspose(filters=32, kernel_size=(9, 9, 32), strides=(1,2,2),
                                      padding='same', activation ='relu'))
    seq.add(BatchNormalization())

    seq.add(Conv3DTranspose(filters=1, kernel_size=(11, 11, 5), strides=(1,3,3),
                                      padding='same', activation ='relu'))
    seq.add(BatchNormalization())

    seq.add(Cropping3D(cropping = (0,16,16)))

    seq.add(Cropping3D(cropping = ((0,-5),(0,0),(0,0))))

    seq.compile(loss='mean_squared_error', optimizer='adadelta', metrics=['accuracy'])

您希望在出现回归问题时使用的指标是 mse(mean_squared_error) 或 mae (mean_absolute_error)。

您可能希望在开始时使用 mse,因为它比 mae 惩罚更大的错误。

您只需要稍微更改一下编译模型的代码。

seq.compile(loss='mean_squared_error', optimizer='adadelta', metrics=['mse','mae'])

通过这种方式,您可以在训练期间监控 msemae 指标。