You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keras LSTM分类器目标形状匹配失败问题求助

问题分析与解决

核心错误原因

  1. 目标变量结构不匹配:输入X是按walk分组后的序列数据,形状为(3, 5, 2)(3个walk序列,每个最长5个时间步,2个特征),但错误地将y_onehot强行reshape为(3,12),和模型输出形状(当前模型默认输出单步结果(1,3))完全不兼容。
  2. 代码冗余与变量冲突:代码中重复定义y变量,中间备选编码逻辑存在语法错误(如未定义的y_wals、max_length),且覆盖了后续分组的y,导致数据混乱。
  3. 模型结构不符合需求:需要预测每个时间步的value,但当前LSTM层默认return_sequences=False,只会输出整个序列的最后一个时间步结果,无法满足逐时间步预测的需求。

修正后的完整代码

import pandas as pd
import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, LSTM, Masking, TimeDistributed
from tensorflow.keras.utils import np_utils, pad_sequences
from sklearn.preprocessing import LabelEncoder

# 读取数据
df = pd.DataFrame({
                   'value': ['A',  'A',  'A',  'C',  'C',   'C', 'C',  'C', 'B', 'B', 'B',  'B'],
                   'X1':    [1.2,  1.5,  0.91, 3.5,  0.2,   2.7, 2.2,  0.91, 3.5, 0.2, 0.91, 2.4],
                   'X2':    [2.4,  0.82, 2.1,  0.4,  4.4,   3.5, 0.2,  2.7,  2.2, 4.2, 3.4,  0.9],
                   'walk': ['d', 'd',   'd',  'sa', 'sa', 'sa', 'sa', 'sa', 'p', 'p', 'p', 'p'], 
                   'time':  [1,    2,    3,    1,    2,     3,   4,    5,     1,   2,   3,    4]})

# 设置参数
TIME_STEPS = max(df.groupby(['walk'])['time'].count())
NUM_FEATURES = 2  # X特征数量
CLASSES = df['value'].unique()
NUM_CLASSES = len(CLASSES)

# 按walk分组生成输入输出序列
X = []
y_raw = []
for walk, group in df.groupby('walk'):
    x_walk = group[['X1', 'X2']].values
    y_walk = group['value'].values
    X.append(x_walk)
    y_raw.append(y_walk)

# 对输入序列补零到最大长度
X = pad_sequences(X, maxlen=TIME_STEPS, dtype='float32', padding='post', value=0.0)

# 编码目标变量并补全到对应序列长度
encoder = LabelEncoder()
encoder.fit(df['value'])
# 对每个walk的y序列编码,然后补全到TIME_STEPS长度,再转为one-hot
y_encoded = []
for seq in y_raw:
    encoded_seq = encoder.transform(seq)
    # 补全序列,用-1标记补位(后续会忽略)
    padded_seq = pad_sequences([encoded_seq], maxlen=TIME_STEPS, padding='post', value=-1)[0]
    y_encoded.append(padded_seq)

# 转为one-hot编码,补位的-1转为全0(不参与损失计算)
y_onehot = []
for seq in y_encoded:
    onehot_seq = []
    for val in seq:
        if val == -1:
            onehot_seq.append(np.zeros(NUM_CLASSES))
        else:
            onehot_seq.append(np_utils.to_categorical(val, NUM_CLASSES))
    y_onehot.append(onehot_seq)
y_onehot = np.array(y_onehot, dtype='float32')

# 定义模型:需要逐时间步输出,所以LSTM设置return_sequences=True,用TimeDistributed包装Dense
model = Sequential()
model.add(Masking(mask_value=0.0, input_shape=(TIME_STEPS, NUM_FEATURES)))
model.add(LSTM(units=50, return_sequences=True))
model.add(TimeDistributed(Dense(NUM_CLASSES, activation='softmax')))
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
print(model.summary())

# 拟合模型,此时X形状(3,5,2),y_onehot形状(3,5,3),完全匹配
model.fit(X, y_onehot, epochs=100, batch_size=1, verbose=2)

关键修正点说明

  • 统一数据结构:输入X和目标y_onehot都按walk序列组织,形状分别为(样本数, 时间步数, 特征数)和(样本数, 时间步数, 类别数),保证维度匹配。
  • 补位处理:对目标序列的补位用-1标记,转为one-hot时设为全0,结合Masking层忽略补位的损失计算。
  • 模型调整:将LSTM的return_sequences设为True,并使用TimeDistributed包装Dense层,实现每个时间步输出对应类别的预测结果。

内容的提问来源于stack exchange,提问作者Noque

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 14:05:00