Transformer 模型非常慢并且不能很好地预测

数据挖掘 机器学习 Python 深度学习 喀拉斯 变压器
2022-03-14 23:56:24

在使用 LSTM 工作至今,我创建了我的第一个变压器模型。我为多变量时间序列预测创建了它——我有 10 种不同的气象特征(温度、湿度、风速、污染浓度 ao),我试图用它们来预测空气污染的时间序列(24 个连续值/小时)。所以我的输入具有形状X.shape = (75575, 168, 10)- 75575 个时间序列,每个序列包含 168 个每小时条目/向量,每个向量包含 10 个气象特征。我的输出具有形状y.shape = (75575, 24)- 75575 个序列,每个序列包含 24 个连续小时的空气污染浓度值。

我以keras 官方网站上的一个例子作为模型。它是为分类问题而创建的,我只取出了softmax激活,在最后一个密集层中,我将神经元的数量设置为 24,我希望它会起作用。我跑步和训练,但它并没有比我在同一个问题上使用的 LSTM 做得更好,更重要的是 - 它非常慢 - 4 分钟/时代。下面我附上模型,我想知道:

I) 我在模型中做错了吗?可以提高准确性或速度吗?是否有可能我需要更改代码的其他部分才能处理回归,而不是分类问题?

II)此外,变压器可以完全解决我这种类型的多变量问题(10 个特征输入,1 个特征输出)还是变压器只适用于单变量问题?肿瘤坏死因子

def build_transformer_model(input_shape, head_size, num_heads, ff_dim, num_transformer_blocks, mlp_units, dropout=0, mlp_dropout=0):

    inputs = keras.Input(shape=input_shape)
    x = inputs
    for _ in range(num_transformer_blocks):

        # Normalization and Attention
        x = layers.LayerNormalization(epsilon=1e-6)(x)
        x = layers.MultiHeadAttention(
            key_dim=head_size, num_heads=num_heads, dropout=dropout
        )(x, x)
        x = layers.Dropout(dropout)(x)
        res = x + inputs

        # Feed Forward Part
        x = layers.LayerNormalization(epsilon=1e-6)(res)
        x = layers.Conv1D(filters=ff_dim, kernel_size=1, activation="relu")(x)
        x = layers.Dropout(dropout)(x)
        x = layers.Conv1D(filters=inputs.shape[-1], kernel_size=1)(x)
        x = x + res

    x = layers.GlobalAveragePooling1D(data_format="channels_first")(x)
    for dim in mlp_units:
        x = layers.Dense(dim, activation="relu")(x)
        x = layers.Dropout(mlp_dropout)(x)
    x = layers.Dense(24)(x)
    return keras.Model(inputs, x)

model_tr = build_transformer_model(input_shape=(window_size, X_train.shape[2]), head_size=256, num_heads=4, ff_dim=4, num_transformer_blocks=4, mlp_units=[128], mlp_dropout=0.4, dropout=0.25)
model_tr.compile(loss="mse",optimizer='adam') 
m_tr_history = model_tr.fit(x=X_train, y=y_train, validation_split=0.25, batch_size=64, epochs=10, callbacks=[modelsave_cb])
1个回答

这段代码让我感到惊讶的部分与您链接到的教程相匹配,但它们的性能似乎很差。他们val_loss在(最好的)时代105是0.3232而在RNN 教程中,他们的最佳成绩val_loss为 0.0895(epoch 376)。

令我惊讶的一点是Conv1D(filters=4, kernel_size=1)用作前馈网络。我看了几次链接到这篇文章的来源,或者一些理由/解释,但没有发现任何东西。

更正常的,对于 Transformer 来说,是一个简单的全连接网络。例如,这个 keras 教程是这样的:

  self.ffn = keras.Sequential(
      [layers.Dense(ff_dim, activation="relu"), layers.Dense(embed_dim),]
      )

然后用作:

  out1 = self.layernorm1(inputs + attn_output)
  ffn_output = self.ffn(out1)
  ffn_output = self.dropout2(ffn_output, training=training)

通常ff_dim是 的 4 倍embed_dim我已经尝试使用较小的乘数进行实验,但我认为您希望它至少是 2 倍。

顺便说一句,我很难弄清楚你embed_dim是什么;但也许只有 10 个?在这种情况下,ahead_dim为 256 是不合适的。(例如,如果 embed_dim 为 256,您可能有 4 个大小为 64 的头。)

退后一步,您描述数据的方式听起来可以用 NLP 术语重新表述,因为您有一批 75575 个句子,每个句子正好有 168 个标记在 NLP 中,token 是一串 unicode 字符,嵌入层会将它们转换为例如 256 个浮点值,通常每个值随机初始化为大致 -1 到 +1,但随后可以学习;而您有一组 10 个浮点 (?) 功能,尚未标准化为那种范围 (?)。

总而言之,我首先会遵循一个教程,该教程显示它对 RNN 进行了改进;其次,我将研究数据表示。