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

使用中间层输出作为标签训练自编码器遇AttributeError问题求助

解决Keras自编码器训练时'Tensor' object has no attribute 'ndim'错误

你遇到的问题核心很明确:你把计算图中的Keras Tensor对象(ae_input)直接传给了model.fit()的y参数,但这个方法需要的是实际的numpy数组格式的训练数据,而非计算图里的张量节点。Tensor是Keras用来构建模型计算流程的元素,它本身不包含真实的训练数据,自然没有ndim这个numpy数组特有的属性。

下面是两种可行的解决思路,帮你正确完成自编码器的训练:

方法1:提前准备好拼接后的目标数据(最直接)

自编码器的训练目标是重构输入,也就是你拼接后的ae_input对应的真实数据。我们可以先在numpy层面把稠密特征和嵌入层处理后的特征拼接好,作为训练的目标值:

import numpy as np
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Embedding, Flatten, Dense, concatenate

# 先定义嵌入层相关的小模型,用来转换训练数据中的序列特征
sequences = Input(shape=(train_embed.shape[1],))
embed = Embedding(vocab_size, 20, input_length=num_embed_cols)(sequences)
flatten = Flatten()(embed)
embed_process_model = Model(inputs=sequences, outputs=flatten)

# 得到训练数据中序列特征经过嵌入+Flatten后的结果
train_flattened_embed = embed_process_model.predict(train_embed)

# 拼接稠密特征和处理后的嵌入特征,得到自编码器的目标数据y_train
y_train = np.concatenate([train_dense_scaled, train_flattened_embed], axis=1)

# 重新构建完整的自编码器模型
dense = Input(shape=(train_dense_scaled.shape[1],))
sequences_input = Input(shape=(train_embed.shape[1],))
embed_layer = Embedding(vocab_size, 20, input_length=num_embed_cols)(sequences_input)
flatten_layer = Flatten()(embed_layer)
ae_input = concatenate([dense, flatten_layer])

# 编码器部分
e_128 = Dense(units=128, activation='relu', kernel_initializer=initializer)(ae_input)
e_64 = Dense(units=64, activation='relu', kernel_initializer=initializer)(e_128)

# 解码器部分:输出维度要和ae_input一致,才能完成重构
decoded = Dense(units=ae_input.shape[1], activation='relu', kernel_initializer=initializer)(e_64)

model = Model(inputs=[sequences_input, dense], outputs=decoded)
model.compile(loss='mse', optimizer='adam')

# 现在传入正确的numpy数组作为y
model.fit(x=[train_embed, train_dense_scaled], y=y_train, epochs=200, batch_size=128)

方法2:用函数式API构建包含输入目标的模型(更优雅,适合复杂场景)

如果你不想提前处理数据,可以直接构建一个多输出模型,让模型自动关联输入和目标的映射关系:

from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Embedding, Flatten, Dense, concatenate
from tensorflow.keras.losses import MeanSquaredError

dense = Input(shape=(train_dense_scaled.shape[1],))
sequences = Input(shape=(train_embed.shape[1],))
embed = Embedding(vocab_size, 20, input_length=num_embed_cols)(sequences)
flatten = Flatten()(embed)
ae_input = concatenate([dense, flatten])

# 编码器
e_128 = Dense(units=128, activation='relu', kernel_initializer=initializer)(ae_input)
e_64 = Dense(units=64, activation='relu', kernel_initializer=initializer)(e_128)

# 解码器:输出维度匹配ae_input
decoded = Dense(units=ae_input.shape[1], activation='relu', kernel_initializer=initializer)(e_64)

# 自定义损失:直接计算重构结果和原始拼接输入的MSE
def recon_loss(y_true, y_pred):
    return MeanSquaredError()(ae_input, y_pred)

# 构建模型,只输出重构结果,用自定义损失关联原始输入
model = Model(inputs=[sequences, dense], outputs=decoded)
model.compile(loss=recon_loss, optimizer='adam')

# 训练时无需额外传入y,因为损失函数已经关联了ae_input
model.fit(x=[train_embed, train_dense_scaled], epochs=200, batch_size=128)

关键注意点

  • 解码器的输出层维度必须和ae_input的维度完全一致,否则会出现维度不匹配的错误。
  • model.fit()的x和y参数都必须是numpy数组(或TensorFlow Dataset对象),不能是Keras的Tensor节点——Tensor只是计算图的一部分,本身不携带训练数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:13:46