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

如何将Keras多输入自编码器的Embedding输出改为(1000000,20)

解决双输入序列Embedding形状问题(从(1000000,50,20)到(1000000,20))

你的问题核心在于当前模型结构中,每个时间步都生成了一个20维向量,而你需要的是整个序列对应一个20维的全局Embedding。这是因为你在LSTM层中设置了return_sequences=True,导致LSTM输出每个时间步的隐藏状态,后续的全连接层也会对每个时间步单独处理,最终得到的journey_embeddings是序列级别的逐时间步输出。

下面提供两种可行的解决方案,你可以根据自己的需求选择:


方案1:修改LSTM层,只输出最后一个时间步的状态

这种方案让LSTM直接输出序列最后一个时间步的隐藏状态,从根源上得到全局的特征表示,后续的全连接层自然会生成每个样本对应的单个Embedding向量。

修改步骤:

  1. 把两个LSTM层的return_sequences=True改为return_sequences=False:
# Input 1: LSTM(修改return_sequences参数)
input_1c = LSTM(10, return_sequences=False)(input_1b)

# Input 2: LSTM(修改return_sequences参数)
input_2c = LSTM(10, return_sequences=False)(input_2b)
  1. 拼接后的特征形状会变成(None, 20)(两个LSTM各输出10维,拼接后共20维),后续的Dense层处理后,journey_embeddings的形状就是(None, 20):
# Concatenation layer here
x = keras.layers.concatenate([input_1c, input_2c])
x2 = Dense(40, activation='relu')(x)
x3 = Dense(20, activation='relu', name="journey_embeddings")(x2)
  1. 调整自编码器输出分支的结构:因为现在x3是全局Embedding,需要用RepeatVector把它扩展为序列形状,才能重建每个时间步的输入:
# 重建Input 1的分支(修改后)
xl = RepeatVector(max_seq_length)(x3)
xf = TimeDistributed(Dense(20, activation='relu'))(xl)
xf1 = TimeDistributed(Dense(50, activation='relu'))(xf)
xf2 = TimeDistributed(Dense(num_unique_event_symbols, activation='linear'))(xf1)

# 重建Input 2的分支(修改后)
xd = RepeatVector(max_seq_length)(x3)
xd2 = TimeDistributed(Dense(1, activation='linear'))(xd)

方案2:添加全局池化层,聚合时间步特征

如果你希望保留LSTM对整个序列的逐时间步建模能力(比如需要捕捉序列的动态变化),可以在现有x3层之后添加全局池化层,把50个时间步的20维向量聚合为一个20维的全局Embedding。

修改步骤:

  1. 在x3之后添加全局平均池化或全局最大池化层,并重命名journey_embeddings到这个池化层:
x3 = Dense(20, activation='relu')(x2)
# 添加全局平均池化,将(None,50,20)转换为(None,20)
journey_embeddings = GlobalAveragePooling1D(name="journey_embeddings")(x3)
  1. 调整自编码器输出分支的输入:输出分支需要基于逐时间步的x3来重建输入,而不是池化后的全局Embedding:
# Re-create the inputs
xl = Lambda(lambda x: x, output_shape=lambda s:s)(x3)  # 仍使用逐时间步的x3
xf = Flatten()(xl)
xf1 = Dense(20, activation='relu')(xf)
xf2 = Dense(50, activation='relu')(xf1)

xd = Lambda(lambda x: x, output_shape=lambda s:s)(x3)  # 同样使用x3
xd2 = TimeDistributed(Dense(1, activation='linear'))(xd)
  1. 提取Embedding时,直接获取journey_embeddings层的输出即可,此时形状就是(1000000, 20):
layer_name = 'journey_embeddings'
intermediate_layer_model = Model(inputs=model.input, outputs=model.get_layer(layer_name).output)
intermediate_output = intermediate_layer_model.predict([X1,X2])

方案选择建议

  • 如果你更关注序列的最终状态(比如用户的最终行为),选择方案1,结构更简洁,计算量更小。
  • 如果你需要捕捉序列的全局趋势(比如整个时间序列的模式),选择方案2,能保留更多序列动态信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:23:22