要使用自定义 Transformer 模型生成句子嵌入,您首先需要加载模型和分词器,处理输入文本,并从模型中提取隐藏状态。与预训练的 Sentence Transformer 不同,自定义模型需要手动处理分词、推理和池化,才能将 token 级别的输出转换为句子嵌入。这涉及到使用诸如 Hugging Face Transformers 等库来访问模型架构和实用程序,然后进行后处理步骤,以将 token 表示聚合为每个句子的单个向量。
首先使用 Transformers 库中的 AutoModel
和 AutoTokenizer
加载您的自定义模型及其对应的分词器。例如,如果您的模型保存在本地,请使用 model = AutoModel.from_pretrained("path/to/model")
和 tokenizer = AutoTokenizer.from_pretrained("path/to/tokenizer")
。使用 tokenizer(text, padding=True, truncation=True, return_tensors="pt")
对输入句子进行分词,以生成输入 ID 和注意力掩码。这些张量通过 outputs = model(**tokens)
传递给模型,该函数返回隐藏状态。默认情况下,使用最后一层的隐藏状态(通过 outputs.last_hidden_state
访问),但您可以根据您的模型设计自定义此设置。
下一步是将 token 级别的嵌入池化为句子嵌入。一种常见的方法是平均池化,即平均 token 向量,同时忽略填充 token。例如,计算 attention_mask = tokens["attention_mask"].unsqueeze(-1).float()
和 sum_embeddings = torch.sum(outputs.last_hidden_state * attention_mask, dim=1)
。将其除以 torch.clamp(attention_mask.sum(dim=1), min=1e-9)
以获得平均池化嵌入。您也可以尝试其他策略,例如采用 [CLS] token 的嵌入或最大池化。最后,使用 L2 归一化(例如,torch.nn.functional.normalize
)对嵌入进行归一化,以确保下游任务(如相似性比较)的一致比例。
在实践中,将此逻辑封装到一个可重用的函数中。例如,创建一个 encode
方法,该方法接受句子列表,分批处理它们,并返回归一化的嵌入。确保您的自定义模型针对句子级别任务(例如,使用对比损失)进行了微调,以产生有意义的嵌入。如果性能至关重要,请优化批处理和设备放置(例如,使用 .to("cuda")
将张量移动到 GPU)。这种方法提供了灵活性,但需要仔细测试以匹配专用句子嵌入模型的质量。