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

如何仅针对单词而非句子使用BERT获取词向量嵌入?

用原生BERT生成名词向量的解决方案

你提到的SentenceTransformer确实是封装好的工具,但原生BERT也能直接生成可用的单词向量,核心是要正确处理分词后的输入,并从模型输出中提取合适的向量表示。下面是具体步骤和代码:

核心思路

BERT的Tokenizer负责将文本转换为模型可接受的输入格式(token ID、attention mask等),但真正的语义向量是模型处理这些输入后输出的隐藏层状态。对于单个名词,通常有两种常用的向量提取方式:

  • 取[CLS] token的向量:BERT输入的第一个token,是整个序列的聚合表示
  • 取所有非特殊token的平均向量:处理名词被拆分为subword的情况(比如"happiness"可能被拆为"happy"和"##ness"),平均后更贴近单词本身的语义

完整代码示例

from transformers import BertTokenizer, BertModel
import torch

# 加载预训练BERT模型和分词器
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')
model.eval()  # 切换到评估模式,避免梯度更新

# 你的名词列表
words = ["apple", "banana", "computer", "unhappiness"]
word_embeddings = []

# 关闭梯度计算,节省内存和计算资源
with torch.no_grad():
    for word in words:
        # 分词:生成模型所需的输入张量,自动添加[CLS]和[SEP]
        inputs = tokenizer(
            word,
            return_tensors="pt",
            padding=True,
            truncation=True
        )
        
        # 传入模型,获取输出
        outputs = model(**inputs)
        # last_hidden_state的形状是 (batch_size, sequence_length, hidden_size)
        
        # 方案1:提取[CLS] token的向量(第一个位置)
        cls_emb = outputs.last_hidden_state[:, 0, :].squeeze().numpy().tolist()
        
        # 方案2:提取所有非特殊token的平均向量(推荐用于subword拆分的情况)
        token_ids = inputs["input_ids"][0]
        # 过滤掉[CLS]和[SEP]的token ID
        valid_token_indices = [
            idx for idx, tid in enumerate(token_ids)
            if tid not in [tokenizer.cls_token_id, tokenizer.sep_token_id]
        ]
        valid_embeddings = outputs.last_hidden_state[0, valid_token_indices, :]
        avg_emb = torch.mean(valid_embeddings, dim=0).numpy().tolist()
        
        # 选择一种向量添加到结果列表,这里用平均向量
        word_embeddings.append(avg_emb)

# 现在word_embeddings就是可直接用于后续任务的向量列表

关键问题解释

  1. Tokenizer的作用:Tokenizer只是文本到模型输入的转换器,输出的input_ids、attention_mask等是模型的输入参数,不是语义向量,必须传入BERT模型才能得到向量。
  2. 为什么SentenceTransformer可以直接用:它是在预训练语言模型(比如BERT、MPNet)基础上做了微调,专门优化了句子/短语的向量生成任务,所以encode方法直接封装了输入处理和向量提取的逻辑。
  3. 批量处理优化:如果你的名词列表很大,可以将所有单词一次性传入分词器,批量处理能大幅提高效率,示例如下:
# 批量处理示例
inputs = tokenizer(words, return_tensors="pt", padding=True, truncation=True)
with torch.no_grad():
    outputs = model(**inputs)
# 批量提取平均向量
batch_avg_embs = []
for i in range(len(words)):
    token_ids = inputs["input_ids"][i]
    valid_indices = [idx for idx, tid in enumerate(token_ids) if tid not in [tokenizer.cls_token_id, tokenizer.sep_token_id]]
    valid_embs = outputs.last_hidden_state[i, valid_indices, :]
    avg_emb = torch.mean(valid_embs, dim=0).numpy().tolist()
    batch_avg_embs.append(avg_emb)

额外建议

  • 根据任务选择预训练模型:比如需要大小写敏感的场景用bert-base-cased,追求更好效果用bert-large-uncased(但计算量更大)。
  • 如果需要更贴合特定领域的向量,可以用领域预训练的BERT模型(比如医疗领域的biobert-base-cased-v1.1)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 02:35:09