Transformer模型在多元时间序列数据上拟合不佳的技术咨询
用户问题背景
我已构建LSTM、带Self-Attention的LSTM两种模型,目前正在开发首个Transformer模型,用于多元时间序列的多对一分类任务。
数据为小时级变化数据,包含8个特征(小时、月份、温度、湿度、风速、太阳辐射浓度等),目标是预测建筑能耗值。输入形状为X.shape = (8783, 168, 8)(8783个时间序列,每个序列含168条小时数据,每条数据8个特征);输出形状为Y.shape = (8783,1)(每个序列对应1个建筑能耗值)。
参考Keras官方示例构建模型,将输出转换为类别,n_classes = len(np.unique(Y_train)) = 156,输入输出形状为Input shape (X_train) = (8783, 168, 8) Output shape (Y_train) = (8783,1) n_classes = 156,在softmax激活层设置输出为n_classes,但模型拟合效果很差。
附上模型代码:
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(n_classes, activation="softmax")(x) return keras.Model(inputs, x) model_tr = build_transformer_model(input_shape=(X_train.shape[1], 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.2) model_tr.compile(loss="sparse_categorical_crossentropy", optimizer=keras.optimizers.Adam(learning_rate=0.0001), metrics=["sparse_categorical_accuracy"], ) plot_model(model_tr, to_file='model_plot.png', show_shapes=True, show_layer_names=True) model_tr.summary() m_tr_history = model_tr.fit(x=X_train, y=Y_train, validation_split=0.15, batch_size=64, epochs=100, verbose = 1) model_tr.save('halka_transformer.h5')
咨询问题:
I) 模型架构是否存在问题?代码中是否有需要调整的部分以适配我的任务?
II) Transformer能否处理我这类8特征输入、1特征输出的多元问题,还是仅适用于单变量问题?
问题解答
I) 模型架构问题与调整建议
1. 残差连接逻辑错误
原代码中Transformer块的残差连接直接叠加原始输入inputs,会破坏特征的递进学习:
res = x + inputs # 错误:应该叠加当前块的输入,而非原始输入
正确的残差连接应保存每个块的初始输入作为基准:
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): # 保存当前块的输入作为残差基准 residual = x # 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) x = x + residual # 注意力输出 + 块输入 # Feed Forward Part residual = x # 更新残差基准为注意力后的输出 x = layers.LayerNormalization(epsilon=1e-6)(x) 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 + residual # 前馈输出 + 注意力后的输出 x = layers.GlobalAveragePooling1D()(x) for dim in mlp_units: x = layers.Dense(dim, activation="relu")(x) x = layers.Dropout(mlp_dropout)(x) x = layers.Dense(n_classes, activation="softmax")(x) return keras.Model(inputs, x)
2. 池化层参数错误
GlobalAveragePooling1D设置data_format="channels_first"不符合你的输入结构:你的输入是(时间步, 特征数),默认channels_last才是正确维度,修改后才能正确对时间步做池化。
3. 超参数适配问题
- head_size与特征维度不匹配:输入特征维度为8,
head_size=256过大,建议调整为8/16等与特征维度适配的值,同时保证head_size * num_heads与特征维度兼容(比如head_size=4, num_heads=2)。 - ff_dim过小:
ff_dim=4无法充分提取特征,建议调整为32或64。 - 分类任务合理性验证:156个类别属于多分类,若能耗值是连续数值,转为分类会损失信息,建议优先尝试回归任务(用MSE损失+
Dense(1, activation='linear'))。
4. 输入特征归一化
时间序列特征数值范围差异大,必须先做标准化/归一化:
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() # 展平时间步做归一化,再恢复原形状 X_train_scaled = scaler.fit_transform(X_train.reshape(-1, X_train.shape[-1])).reshape(X_train.shape) X_val_scaled = scaler.transform(X_val.reshape(-1, X_val.shape[-1])).reshape(X_val.shape)
II) Transformer对多元输入的支持
Transformer完全可以处理8特征输入的多元时间序列任务:
- 输入的8个特征会作为每个时间步的特征向量,自注意力机制会同时捕捉不同时间步的所有特征关联,学习特征间的依赖关系。
- 单变量时间序列只是多元的特例(特征维度=1),Transformer在多元任务中表现更具优势,能并行处理所有时间步的特征交互,高效捕捉长距离依赖。
内容的提问来源于stack exchange,提问作者mzu

