基于TSMixer的时间序列序列分类TensorFlow ValueError问题求助
问题:TSMixer适配时间序列全序列二分类的形状不匹配错误
问题背景
尝试用时间序列预测架构TSMixer完成全序列二分类任务:每个时长5.5秒、128Hz采样(共704个数据点)、含3个特征的序列对应一个类别标签。
数据集生成代码
def _split_window(self, data, label): inputs = data[:, : self.seq_len, :] # 手动设置形状保留静态信息 inputs.set_shape([None, self.seq_len, None]) return inputs, label def _make_dataset(self, data, label, shuffle=True,): data = np.array(data, dtype=np.float32) label = np.array(label, dtype=np.float32) ds = tf.keras.utils.timeseries_dataset_from_array( data=data, targets=label, sequence_length=self.seq_len, sequence_stride=1, shuffle=shuffle, batch_size=self.batch_size ) ds = ds.map(self._split_window) return ds
生成的数据集张量规格:
train data Tensor: <_MapDataset element_spec=(TensorSpec(shape=(None, 704, 3), dtype=tf.float32, name=None), TensorSpec(shape=(None, 1), dtype=tf.float32, name=None))> val data Tensor: <_MapDataset element_spec=(TensorSpec(shape=(None, 704, 3), dtype=tf.float32, name=None), TensorSpec(shape=(None, 1), dtype=tf.float32, name=None))> test data Tensor: <_MapDataset element_spec=(TensorSpec(shape=(None, 704, 3), dtype=tf.float32, name=None), TensorSpec(shape=(None, 1), dtype=tf.float32, name=None))>
模型结构代码
def res_block(inputs, norm_type, activation, dropout, ff_dim): """Residual block of TSMixer.""" norm = ( layers.LayerNormalization if norm_type == 'L' else layers.BatchNormalization ) # Temporal Linear x = norm(axis=-1)(inputs) x = ops.transpose(x, axes=[0, 2, 1]) # [Batch, Channel, Input Length] x = layers.Dense(x.shape[-1], activation=activation)(x) x = ops.transpose(x, axes=[0, 2, 1]) # [Batch, Input Length, Channel] x = layers.Dropout(dropout)(x) res = x + inputs # Feature Linear x = norm(axis=-1)(res) x = layers.Dense(ff_dim, activation=activation)(x) # [Batch, Input Length, FF_Dim] x = layers.Dropout(dropout)(x) x = layers.Dense(inputs.shape[-1])(x) # [Batch, Input Length, Channel] x = layers.Dropout(dropout)(x) return x + res def build_model( input_shape, pred_len, norm_type, activation, n_block, dropout, ff_dim, target_slice, ): """Build TSMixer model.""" inputs = tf.keras.Input(shape=input_shape) x = inputs # [Batch, Input Length, Channel] print('inputs shape: ', x.shape) for _ in range(n_block): x = res_block(x, norm_type, activation, dropout, ff_dim) print('1', x.shape) # 原输出层:逐时间步预测 outputs = layers.Dense(pred_len, activation='sigmoid')(x) # outputs = tf.reduce_mean(outputs, axis=1) print('outputs shape:', outputs.shape) return tf.keras.Model(inputs, outputs)
训练错误信息
inputs shape: (None, 704, 3) ... 1: (None, 704, 3) outputs shape: (None, 704, 1) Epoch 1/3 Traceback (most recent call last): File "/home/maven96/workspace/tsmixer_PR/run.py", line 342, in <module> main() File "/home/maven96/workspace/tsmixer_PR/run.py", line 287, in main history = model.fit( File "/home/maven96/workspace/venv_dir/test_env/lib/python3.10/site-packages/keras/src/utils/traceback_utils.py", line 122, in error_handler raise e.with_traceback(filtered_tb) from None File "/home/maven96/workspace/venv_dir/test_env/lib/python3.10/site-packages/keras/src/backend/tensorflow/nn.py", line 689, in binary_crossentropy raise ValueError( ValueError: Arguments `target` and `output` must have the same shape. Received: target.shape=(None, 1), output.shape=(None, 704)
错误原因
TSMixer原本是为时间序列逐点预测设计的,原模型最后一层layers.Dense(pred_len, activation='sigmoid')(x)会输出形状为(None,704,1)的张量(每个时间步对应一个预测),但我们的任务是全序列分类,标签形状为(None,1)(每个序列对应一个标签),两者形状不匹配导致损失计算报错。
解决思路与修改方案
核心是聚合时序维度的特征,将序列级的特征压缩为样本级的特征,再输出分类结果。具体修改如下:
修改模型构建函数
def build_model( input_shape, norm_type, activation, n_block, dropout, ff_dim, ): """Build TSMixer model for sequence classification.""" inputs = tf.keras.Input(shape=input_shape) x = inputs # [Batch, Input Length, Channel] print('inputs shape: ', x.shape) for _ in range(n_block): x = res_block(x, norm_type, activation, dropout, ff_dim) print('1', x.shape) # 聚合时序维度信息(二选一即可) # 方案1:全局平均池化,自动压缩时序维度,输出(None, 3) x = layers.GlobalAveragePooling1D()(x) # 方案2:手动计算时序维度均值,输出同样为(None,3) # x = tf.reduce_mean(x, axis=1) # 全连接层输出二分类结果,形状为(None,1),与标签匹配 outputs = layers.Dense(1, activation='sigmoid')(x) print('outputs shape:', outputs.shape) # 现在输出形状为(None,1) return tf.keras.Model(inputs, outputs)
其他注意事项
- 调用
build_model时,需移除原有的pred_len和target_slice参数,因为分类任务不需要这两个预测相关的参数。 - 保留原有的残差块和转置逻辑即可,这些是TSMixer的核心结构,不需要修改。
内容的提问来源于stack exchange,提问作者user25407722
相关产品推荐
相关产品推荐

