如何基于T5模型编码、修改句嵌入并解码为文本?
问题描述
我是NLP领域新手,希望对句嵌入执行向量操作(如在给定句子的均匀球内进行嵌入空间随机化)并解码。目前尝试使用T5与Huggingface Transformers,步骤如下:
- 用T5Tokenizer编码文本;
- 通过model.encoder前向传播,取last hidden state作为嵌入(曾尝试.generate,但无法分离编码器与解码器);
- 对嵌入执行所需操作;
- 问题步骤:将嵌入传入model.decoder并通过tokenizer解码。
我在步骤4遇到问题:将步骤3设为无操作时,输出文本与输入不一致。我感觉遗漏了关键环节(比如缺少beam search等生成方法),也不确定步骤2中的嵌入是否正确。请问如何基于T5编码句嵌入、在向量空间修改后解码为生成文本?是否有更合适的模型?
以下是问题代码:
t5_model = transformers.T5ForConditionalGeneration.from_pretrained("t5-large") t5_tok = transformers.T5Tokenizer.from_pretrained("t5-large") text = "Foo bar is typing some words." input_ids = t5_tok(text, return_tensors="pt").input_ids encoder_output_vectors = t5_model.encoder(input_ids, return_dict=True).last_hidden_state # The rest is what I think is problematic: decoder_input_ids = t5_tok("<pad>", return_tensors="pt", add_special_tokens=False).input_ids decoder_output = t5_model.decoder(decoder_input_ids, encoder_hidden_states=encoder_output_vectors) t5_tok.decode(decoder_output.last_hidden_state[0].softmax(0).argmax(1))
解决方案
一、核心问题分析
你的解码逻辑存在两个关键错误:
- T5的解码是自回归生成过程,不能仅传单个
<pad>token就直接硬解码,需要逐步生成每个token并关联编码器输出的注意力信息; - 你取的
last_hidden_state是所有输入token的嵌入,若要句嵌入通常取序列末尾的</s>标记对应的输出,而非整个序列的hidden state。
二、修正后的完整流程
1. 正确获取编码器输出(含句嵌入)
import torch from transformers import T5ForConditionalGeneration, T5Tokenizer t5_model = T5ForConditionalGeneration.from_pretrained("t5-large") t5_tok = T5Tokenizer.from_pretrained("t5-large") text = "Foo bar is typing some words." # 编码文本,添加padding和截断保证格式合规 inputs = t5_tok(text, return_tensors="pt", padding=True, truncation=True) encoder_outputs = t5_model.encoder(**inputs, return_dict=True) # 可选:获取句嵌入(取</s>对应的hidden state) sentence_embedding = encoder_outputs.last_hidden_state[:, -1, :].unsqueeze(1) # 保留所有token的嵌入,这里可添加你的向量操作(比如随机扰动) modified_encoder_hidden = encoder_outputs.last_hidden_state
2. 正确解码生成文本
方法一:用generate方法(推荐,自带搜索策略)
利用模型内置的generate接口,直接传入修改后的编码器输出,支持贪婪搜索、beam search等策略:
# 构造generate所需的encoder_outputs结构 custom_encoder_outputs = (modified_encoder_hidden,) + encoder_outputs[1:] # 调用生成,配置解码参数 generated_ids = t5_model.generate( encoder_outputs=custom_encoder_outputs, decoder_start_token_id=t5_tok.pad_token_id, max_length=50, num_beams=5, # beam search提升生成质量 early_stopping=True ) # 解码并跳过特殊标记 generated_text = t5_tok.decode(generated_ids[0], skip_special_tokens=True) print(generated_text) # 无修改时输出应与输入一致
方法二:手动自回归解码(适合调试)
手动模拟自回归生成过程,逐token预测:
decoder_input_ids = torch.tensor([[t5_tok.pad_token_id]], dtype=torch.long) generated_tokens = [] for _ in range(50): decoder_outputs = t5_model.decoder( input_ids=decoder_input_ids, encoder_hidden_states=modified_encoder_hidden, encoder_attention_mask=inputs["attention_mask"] ) # 取最后一个token的logits预测下一个token next_token_logits = decoder_outputs.last_hidden_state[:, -1, :] next_token_id = torch.argmax(next_token_logits, dim=-1).item() if next_token_id == t5_tok.eos_token_id: break generated_tokens.append(next_token_id) decoder_input_ids = torch.cat([decoder_input_ids, torch.tensor([[next_token_id]])], dim=1) generated_text = t5_tok.decode(generated_tokens, skip_special_tokens=True) print(generated_text)
三、模型选择建议
- T5/BART:这类seq2seq模型是最优选择,encoder-decoder结构天然支持编码-修改嵌入-解码的流程,且有成熟的生成接口;
- Encoder-only模型(如BERT):不适合,这类模型没有解码器,无法直接从嵌入还原文本,需额外训练解码器,成本较高。
内容的提问来源于stack exchange,提问作者jmindel
相关产品推荐
相关产品推荐

