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

如何为Encoder-Decoder模型格式化Ragged Tensor?训练报错解决

解决Seq2Seq模型标签形状不匹配问题

问题核心

训练时触发ValueError: Shapes (None, None) and (None, None, 1220) are incompatible,根源有两点:

  • 模型输出为三维张量(batch_size, seq_len, target_vocab_size),对应categorical_crossentropy要求的one-hot格式
  • 预处理后的target_out是二维整数索引张量(batch_size, seq_len),两者形状不兼容
  • 输入层设置了ragged=True,但预处理中已通过to_tensor()将张量转为密集格式,导致输入输出不匹配

修复步骤

1. 调整损失函数(推荐方案)

无需将标签转为one-hot,直接使用整数索引适配的SparseCategoricalCrossentropy,修改模型编译逻辑:

def create_model(hsize):
    en_input_layer, enc_out, enc_states = encoder(hsize)
    de_input_layer, de_preds = decoder(hsize, enc_states)
    model = Model(inputs=[en_input_layer, de_input_layer], outputs=de_preds)
    model.compile(optimizer='adam', 
                  loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
                  metrics=["acc"])
    return model

注:因为输出层用了softmax激活,所以from_logits=False;若移除softmax,建议设为True以提升数值稳定性

2. 修正输入层的ragged参数

预处理阶段已将ragged张量转为密集张量,因此需要去掉输入层的ragged=True设置:

def encoder(hsize, embed_dim=200):
    # 移除ragged=True
    en_input_layer = Input(shape=(None,), name='encoder_input_layer')
    en_embed = Embedding(context_vectorizer.vocabulary_size()+1, output_dim=embed_dim, name='encoder_embedding_layer')
    en_embed_out = en_embed(en_input_layer)
    en_gru_1 = GRU(hsize, return_sequences=True, return_state=True, name='encoder_gru_layer_1')
    en_gru_1_out, en_gru_states = en_gru_1(en_embed_out)
    return en_input_layer, en_gru_1_out, en_gru_states

def decoder(hsize, encoder_states, embed_dim=200):
    # 移除ragged=True
    de_input_layer = Input(shape=(None,), name='decoder_input_layer')
    de_embed = Embedding(target_vectorizer.vocabulary_size()+1, output_dim=embed_dim, name='decode_embedding_layer')
    de_embed_out = de_embed(de_input_layer)
    de_gru_1 = GRU(hsize, return_sequences=True, name='decoder_gru_layer_1')
    de_gru_1_out = de_gru_1(de_embed_out, initial_state=encoder_states)
    # 修正Dense层维度,匹配Embedding的词汇表大小(包含填充位)
    de_dense = TimeDistributed(Dense(target_vectorizer.vocabulary_size()+1, activation='softmax'), name='time_distributed_output_layer')
    de_preds = de_dense(de_gru_1_out)
    return de_input_layer, de_preds

3. 可选:将标签转为one-hot格式(内存占用较高)

若坚持使用categorical_crossentropy,修改预处理函数对target_out做one-hot编码:

def preprocess_text(context, target):
    context = context_vectorizer(context).to_tensor()
    target = target_vectorizer(target)

    target_in = target[:,:-1].to_tensor()
    target_out = target[:,1:].to_tensor()
    # 转换为one-hot格式,维度匹配词汇表(含填充位)
    target_out = tf.one_hot(target_out, depth=target_vectorizer.vocabulary_size()+1)
    return (context, target_in), target_out

4. 验证数据管道输出

添加代码确认形状匹配:

for (context_batch, target_in_batch), target_out_batch in train_ds.take(1):
    print("Context shape:", context_batch.shape)
    print("Target in shape:", target_in_batch.shape)
    print("Target out shape:", target_out_batch.shape)
  • 用SparseCategoricalCrossentropy时,target_out_batch.shape应为(batch_size, seq_len)
  • 用categorical_crossentropy时,target_out_batch.shape应为(batch_size, seq_len, vocab_size+1)

内容的提问来源于stack exchange,提问作者Krishnang K Dalal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 11:50:04