【问题标题】:Multi-feature causal CNN - Keras implementation多特征因果 CNN - Keras 实现
【发布时间】:2019-09-14 23:24:33
【问题描述】:

我目前正在使用基本的 LSTM 进行回归预测,并且我想实现一个因果 CNN,因为它的计算效率应该更高。

我正在努力弄清楚如何重塑我当前的数据以适应因果 CNN 单元格并表示相同的数据/时间步长关系以及应设置的扩张率。

我当前的数据是这种形状:(number of examples, lookback, features),这是我现在使用的 LSTM NN 的一个基本示例。

lookback = 20   #  height -- timeseries
n_features = 5  #  width  -- features at each timestep

# Build an LSTM to perform regression on time series input/output data
model = Sequential()
model.add(LSTM(units=256, return_sequences=True, input_shape=(lookback, n_features)))
model.add(Activation('elu'))

model.add(LSTM(units=256, return_sequences=True))
model.add(Activation('elu'))

model.add(LSTM(units=256))
model.add(Activation('elu'))

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

model.compile(optimizer='adam', loss='mean_squared_error')

model.fit(X_train, y_train,
          epochs=50, batch_size=64,
          validation_data=(X_val, y_val),
          verbose=1, shuffle=True)

prediction = model.predict(X_test)

然后我根据 Keras 文档创建了一个新的 CNN 模型(尽管不是因果关系,因为 'causal' 填充只是 Conv1D 的一个选项,而不是 Conv2D,根据 Keras 文档。如果我理解正确,通过具有多个功能,我需要使用Conv2D,而不是Conv1D,但是如果我设置Conv2D(padding='causal'),我会收到以下错误-Invalid padding: causal)

无论如何,我还能够使用(number of examples, lookback, features, 1) 的新形状拟合数据并使用Conv2D 层运行以下模型:

lookback = 20   #  height -- timeseries
n_features = 5  #  width  -- features at each timestep

 model = Sequential()
            model.add(Conv2D(128, 3, activation='elu', input_shape=(lookback, n_features, 1)))
model.add(MaxPool2D())
model.add(Conv2D(128, 3, activation='elu'))
model.add(MaxPool2D())
model.add(Flatten())
model.add(Dense(1, activation='linear'))

model.compile(optimizer='adam', loss='mean_squared_error')

model.fit(X_train, y_train,
          epochs=50, batch_size=64,
          validation_data=(X_val, y_val),
          verbose=1, shuffle=True)

prediction = model.predict(X_test)

但是,据我了解,这不会将数据作为因果传播,而只是将整个集合 (lookback, features, 1) 作为图像传播。

有什么方法可以重塑我的数据以适应Conv1D(padding='causal') 层,具有多个功能,或者以某种方式运行与Conv2D 相同的数据和输入形状,并使用'causal' 填充?

【问题讨论】:

    标签: python keras deep-learning conv-neural-network lstm


    【解决方案1】:

    我相信对于任意数量的输入特征,您都可以使用 因果填充dilation。这是我建议的解决方案。

    TimeDistributed layer 是这方面的关键。

    来自 Keras 文档:“此包装器将层应用于输入的每个时间切片。输入应至少为 3D,并且索引一的维度将被视为时间维度。”强>

    出于我们的目的,我们希望这一层对每个特征应用“某些东西”,因此我们将特征移动到时间索引,即 1。

    Conv1D documentation 也相关。

    特别是关于通道:“输入中维度的顺序。“channels_last”对应于具有形状(批次、步骤、通道)的输入(Keras 中时间数据的默认格式)”

    from tensorflow.python.keras import Sequential, backend
    from tensorflow.python.keras.layers import GlobalMaxPool1D, Activation, MaxPool1D, Flatten, Conv1D, Reshape, TimeDistributed, InputLayer
    
    backend.clear_session()
    lookback = 20
    n_features = 5
    
    filters = 128
    
    model = Sequential()
    model.add(InputLayer(input_shape=(lookback, n_features, 1)))
    # Causal layers are first applied to the features independently
    model.add(Permute(dims=(2, 1)))  # UPDATE must permute prior to adding new dim and reshap
    model.add(Reshape(target_shape=(n_features, lookback, 1)))
    # After reshape 5 input features are now treated as the temporal layer 
    # for the TimeDistributed layer
    
    # When Conv1D is applied to each input feature, it thinks the shape of the layer is (20, 1)
    # with the default "channels_last", therefore...
    
    # 20 times steps is the temporal dimension
    # 1 is the "channel", the new location for the feature maps
    
    model.add(TimeDistributed(Conv1D(filters, 3, activation="elu", padding="causal", dilation_rate=2**0)))
    # You could add pooling here if you want. 
    # If you want interaction between features AND causal/dilation, then apply later
    model.add(TimeDistributed(Conv1D(filters, 3, activation="elu", padding="causal", dilation_rate=2**1)))
    model.add(TimeDistributed(Conv1D(filters, 3, activation="elu", padding="causal", dilation_rate=2**2)))
    
    
    # Stack feature maps on top of each other so each time step can look at 
    # all features produce earlier
    model.add(Permute(dims=(2, 1, 3)))  # UPDATED to fix issue with reshape
    model.add(Reshape(target_shape=(lookback, n_features * filters)))  # (20 time steps, 5 features * 128 filters)
    # Causal layers are applied to the 5 input features dependently
    model.add(Conv1D(filters, 3, activation="elu", padding="causal", dilation_rate=2**0))
    model.add(MaxPool1D())
    model.add(Conv1D(filters, 3, activation="elu", padding="causal", dilation_rate=2**1))
    model.add(MaxPool1D())
    model.add(Conv1D(filters, 3, activation="elu", padding="causal", dilation_rate=2**2))
    model.add(GlobalMaxPool1D())
    model.add(Dense(units=1, activation='linear'))
    
    model.compile(optimizer='adam', loss='mean_squared_error')
    
    model.summary()
    

    最终模型总结

    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    reshape (Reshape)            (None, 5, 20, 1)          0         
    _________________________________________________________________
    time_distributed (TimeDistri (None, 5, 20, 128)        512       
    _________________________________________________________________
    time_distributed_1 (TimeDist (None, 5, 20, 128)        49280     
    _________________________________________________________________
    time_distributed_2 (TimeDist (None, 5, 20, 128)        49280     
    _________________________________________________________________
    reshape_1 (Reshape)          (None, 20, 640)           0         
    _________________________________________________________________
    conv1d_3 (Conv1D)            (None, 20, 128)           245888    
    _________________________________________________________________
    max_pooling1d (MaxPooling1D) (None, 10, 128)           0         
    _________________________________________________________________
    conv1d_4 (Conv1D)            (None, 10, 128)           49280     
    _________________________________________________________________
    max_pooling1d_1 (MaxPooling1 (None, 5, 128)            0         
    _________________________________________________________________
    conv1d_5 (Conv1D)            (None, 5, 128)            49280     
    _________________________________________________________________
    global_max_pooling1d (Global (None, 128)               0         
    _________________________________________________________________
    dense (Dense)                (None, 1)                 129       
    =================================================================
    Total params: 443,649
    Trainable params: 443,649
    Non-trainable params: 0
    _________________________________________________________________
    

    编辑:

    “为什么你需要重塑和使用 n_features 作为时间层”

    n_features 最初需要在时间层的原因是因为带有扩张和因果填充的 Conv1D 一次只能处理一个特征,并且因为 TimeDistributed 层是如何实现的。

    从他们的文档 “考虑一批 32 个样本,其中每个样本是 10 个 16 维向量的序列。层的批量输入形状是 (32,10,16),而 input_shape ,不包括样本维度,为 (10, 16)。

    然后您可以使用 TimeDistributed 将 Dense 层分别应用于 10 个时间步长中的每一个:"

    通过将 TimeDistributed 层独立应用于每个特征,它可以减少问题的维度,就好像只有一个特征一样(这很容易允许膨胀和因果填充)。有 5 个功能,首先需要分别处理它们。

    • 在您进行修改后,此建议仍然适用。

    • 无论 InputLayer 是包含在第一层还是单独的,在网络方面应该没有区别,因此如果解决了问题,您绝对可以将它放在第一个 CNN 中。

    【讨论】:

    • 我已经启动并运行了模型,但我仍然不清楚输入形状。我不明白你为什么需要重塑和使用 n_features 作为时间层。我可能不清楚我在原始问题中的命名,所以我通过编辑对其进行了更新。如果您能澄清一下您的原始实现在更新后是否仍然正确?此外,如果我使用 InputLayer 和 ModelCheckpoint,我将无法稍后将模型加载回此处的更多错误信息 - github.com/keras-team/keras/issues/10417。不使用 InputLayer 为我解决了这个问题。
    • 我为您的问题写了一篇后续文章,如果您能查看并再次帮助我,我将不胜感激。太感谢了。 stackoverflow.com/q/56728337/9364931
    • 在初始 Reshape 之前应该有一个model.add(Permute(dims=(2, 1))),否则你会无意中从时间和特征维度“洗牌”数据。
    • 因此在第二次 Reshape 之前还缺少一个 model.add(Permute(dims=(2, 1, 3)))
    • @Pedro,我认为你是对的,而 Chris 没有抓住重点。做reshape后,数据被打乱,新特征中的第二个条目成为第二个原始特征的第一个元素,以此类推,完全混在一起。此外,在 Permute 之后我们不需要 reshape,因为顺序或维度已经是 (nfeatures, timesteps, 1)。必须用小例子严格测试它......
    【解决方案2】:

    Conv1D 中使用因果填充是扩张卷积。对于Conv2D,您可以使用Conv2D 类的dilation_rate 参数。您必须为 dilation_rate 分配 2 个整数元组。更多信息可以阅读keras documentationhere

    【讨论】:

    • 谢谢。这解决了我可以对 Conv2D 使用膨胀的问题,但即使在检查了文档之后,我也不清楚如何设置膨胀率来专门复制 LSTM 和lookback=20 的顺序关系,以及我的数据是否正确成形现在甚至能够实现这一目标。
    猜你喜欢
    • 2017-03-12
    • 2019-07-02
    • 1970-01-01
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多