在Keras中实施因果CNN以进行多元时间序列预测

时间:2019-06-23 23:10:59

标签: python tensorflow keras time-series conv-neural-network

这个问题是我先前在这里提出的问题的后续问题:Multi-feature causal CNN - Keras implementation,但是,有很多事情我不清楚,我认为这值得提出一个新问题。这里讨论的模型是根据上面提到的帖子中公认的答案建立的。

我正在尝试对10个具有5个特征的序列的多元时间序列数据应用因果CNN模型。

lookback, features = 10, 5
  • 应该将过滤器和内核设置为什么?

    • 过滤器和内核对网络有何影响?
    • 这些只是任意数量吗-即ANN层中的神经元数量?
    • 或者它们会影响网络解释时间步长的方式吗?
  • 应将膨胀设置为什么?

    • 这仅仅是一个任意数字还是代表模型的lookback
filters = 32
kernel = 5
dilations = 5
dilation_rates = [2 ** i for i in range(dilations)]

model = Sequential()
model.add(InputLayer(input_shape=(lookback, features)))
model.add(Reshape(target_shape=(features, lookback, 1), input_shape=(lookback, features)))

根据前面提到的答案,需要根据以下逻辑对输入进行重塑:

  • Reshape之后,将5个输入要素视为TimeDistributed层的时间层
  • 将Conv1D应用于每个输入要素时,它认为层的形状为(10,1)

  • 具有默认的“ channels_last”,因此...

  • 10个时间步是时间维度
  • 1是“通道”,是要素地图的新位置
# Add causal layers
for dilation_rate in dilation_rates:
    model.add(TimeDistributed(Conv1D(filters=filters,
                              kernel_size=kernel,
                              padding='causal',
                              dilation_rate=dilation_rate,
                              activation='elu')))

根据上述答案,需要根据以下逻辑对模型进行重塑:

  • 堆栈特征相互映射,因此每个时间步都可以查看较早产生的所有特征-(10个时间步,5个特征* 32个过滤器)

接下来,因果层现在将分别应用于5个输入要素。

  • 为什么最初要单独应用它们?
  • 为什么现在要对其进行依赖性应用?
model.add(Reshape(target_shape=(lookback, features * filters)))

next_dilations = 3
dilation_rates = [2 ** i for i in range(next_dilations)]
for dilation_rate in dilation_rates:
    model.add(Conv1D(filters=filters,
                     kernel_size=kernel,
                     padding='causal',
                     dilation_rate=dilation_rate,
                     activation='elu'))
    model.add(MaxPool1D())

model.add(Flatten())
model.add(Dense(units=1, activation='linear'))

model.summary()

摘要

  • 过滤器和内核应设置为什么?
    • 它们将对网络如何解释时间步长产生影响吗?
  • 应该设置哪些膨胀来表示回溯10?

  • 为什么最初单独应用因果层?

  • 为什么它们在重塑后会被依赖地应用?
    • 为什么不从一开始就依赖它们?

================================================ ==========================

完整代码

lookback, features = 10, 5

filters = 32
kernel = 5
dilations = 5
dilation_rates = [2 ** i for i in range(dilations)]

model = Sequential()
model.add(InputLayer(input_shape=(lookback, features)))
model.add(Reshape(target_shape=(features, lookback, 1), input_shape=(lookback, features)))

# Add causal layers
for dilation_rate in dilation_rates:
    model.add(TimeDistributed(Conv1D(filters=filters,
                              kernel_size=kernel,
                              padding='causal',
                              dilation_rate=dilation_rate,
                              activation='elu')))


model.add(Reshape(target_shape=(lookback, features * filters)))

next_dilations = 3
dilation_rates = [2 ** i for i in range(next_dilations)]
for dilation_rate in dilation_rates:
    model.add(Conv1D(filters=filters,
                     kernel_size=kernel,
                     padding='causal',
                     dilation_rate=dilation_rate,
                     activation='elu'))
    model.add(MaxPool1D())

model.add(Flatten())
model.add(Dense(units=1, activation='linear'))

model.summary()

================================================ ==========================

编辑:

丹尼尔,谢谢您的回答。

问题:

如果您可以“精确”地解释数据的结构方式,原始数据是什么以及如何将其转换为输入形状(如果您具有独立的序列)以及创建滑动Windows等。可以更好地了解此过程。

答案:

希望我能正确理解您的问题。

每个功能都是时间序列数据的序列数组。它们是独立的,例如它们不是图像,但是它们彼此之间有些相关。

这就是为什么我要使用Wavenet的原因,它非常擅长预测单个时间序列阵列,但是,我的问题要求我使用多个功能。

1 个答案:

答案 0 :(得分:3)

关于给定答案的评论

问题:

  
      
  • 为什么最初要单独应用因果层?
  •   
  • 为什么它们在重塑后会被依赖地应用?      
        
    • 为什么不从一开始就依赖它们?
    •   
  •   

那个答案有点奇怪。我不是专家,但是我看不到需要使用TimeDistributed层保留独立功能。但是我也不能说它是否能带来更好的结果。起初我会说这是不必要的。但是,它可能带来更多的智能,因为它可能看到关系涉及两个要素之间的遥远步骤,而不是仅仅关注“相同步骤”。 (应该对此进行测试)

尽管如此,该方法存在错误

旨在交换回溯和特征尺寸的重塑未达到预期的效果。答案的作者显然想交换轴(保留对特征,回溯的解释),这与重塑不同(将所有内容混合在一起并且数据失去了意义) )

正确的方法将需要实际的轴交换,例如model.add(Permute((2,1)))而不是整形。

所以,我不知道这些答案,但是似乎没有什么可以创造这种需求。 可以肯定的一件事是:您一定会想要依赖部分。如果模型不考虑要素之间的关系,则模型将无法获得原始模型的智能。 (除非您很幸运地拥有完全独立的数据)

现在,解释LSTM与Conv1D之间的关系

可以将LSTMConv1D直接进行比较,并且所使用的形状完全相同,并且实际上意味着相同,只要您使用的是channels_last

也就是说,形状(samples, input_length, features_or_channels)LSTMConv1D的正确形状。实际上,在这种情况下,功能和渠道是完全一样的。变化的是每层在输入长度和计算方面的工作方式。

过滤器和内核的概念

内核是conv层内的整个张量,将其与输入相乘以获得结果。内核包括其空间大小(kernel_size)和filters的数量(输出要素)。以及自动输入过滤器。

没有很多内核,但是有kernel_size。内核大小是每个输出步骤将连接多少个长度的步骤。 (此tutorial非常适合于关于其功能和内核大小的未知2D卷积-想像一下1D图像-尽管本教程没有显示“过滤器”的数量,就像1-filter动画)

filters的数量与features的数量直接相关,它们是完全一样的。

  

应该将过滤器和内核设置为什么?

因此,如果您的LSTM层正在使用units=256,这意味着它将输出256个特征,那么您应该使用filters=256,这意味着卷积将输出256个通道/特征。

但这不是规则,您可能会发现使用更多或更少的过滤器会带来更好的结果,因为这些图层毕竟会做不同的事情。不需要所有层都具有相同数量的过滤器!!在这里,您应该进行参数调整。 进行测试以查看最适合您的目标和数据的数字。

现在,内核大小是无法与LSTM相比的。这是模型中新增的内容。

数字3是很常见的选择。这意味着卷积将需要三个时间步才能产生一个时间步。然后滑动一个步骤,进行三个步骤的另一组操作,以产生下一个步骤,依此类推。

膨胀

膨胀表示卷积滤波器在步骤之间将有多少间隔。

  • 卷积dilation_rate=1连续执行kernel_size步以产生一个步骤。
  • dilation_rate = 2的卷积需要步骤0、2和4来产生一个步骤。然后执行步骤1、3、5以产生下一步,依此类推。
  

应该设置什么膨胀来表示回溯10?

range = 1 + (kernel_size - 1) * dilation_rate

因此,内核大小= 3:

  • Dilation = 0(dilation_rate = 1):内核大小范围为3步
  • Dilation = 1(dilation_rate = 2):内核大小范围为5步
  • Dilation = 2(dilation_rate = 4):内核大小为9步
  • Dilation = 3(dilation_rate = 8):内核大小为17个步长

我对你的问题

如果您可以“精确地”解释数据的结构方式,原始数据是什么以及如何将其转换为输入形状,具有独立序列,创建滑动窗口等可以更好地了解此过程。