← 返回信息流
技术博客InfoQ 中文·2019/12/19

如何通过几行 Python 代码,使用BERT进行词嵌入?

速览

BERT作为强大的预训练语言模型,能生成高质量的词嵌入以支持语义搜索等NLP任务。作者Anirudh_S展示了利用Python库轻松配置并运行BERT模型的方法。该方法通过极简代码实现单词向量化,降低了使用深度学习模型进行自然语言处理的门槛。

AI 深度解读

深度解读:如何通过几行 Python 代码,使用 BERT 进行词嵌入?

背景

在自然语言处理(NLP)领域,将文本转化为计算机可理解的数值向量(即词嵌入,Word Embeddings)是几乎所有下游任务的基础。传统的词嵌入方法(如 Word2Vec 或 GloVe)虽然高效,但存在一个显著缺陷:它们生成的向量是静态的。这意味着同一个词在不同的语境下(例如“苹果”指代水果还是公司)拥有相同的向量表示,无法捕捉语义的多义性。

BERT(Bidirectional Encoder Representations from Transformers)的出现改变了这一格局。作为由 Google 提出的预训练语言模型,BERT 能够生成上下文相关的动态词嵌入。然而,对于许多开发者而言,BERT 模型庞大、部署复杂,往往让人望而却步。本文旨在展示如何仅通过几行 Python 代码,利用现成的库快速调用 BERT 生成高质量的词嵌入,从而降低技术门槛,让开发者能够迅速将这一强大能力应用到实际项目中。

核心内容

要实现使用 BERT 进行词嵌入,核心在于利用 Hugging Face 提供的 transformers 库。该库封装了复杂的模型架构,使得开发者无需手动处理 Transformer 的内部机制即可获取嵌入向量。

1. 环境准备与模型加载

首先,需要安装必要的 Python 库,主要是 transformerstorch(PyTorch)。代码的核心第一步是加载预训练的 BERT 模型及其对应的分词器(Tokenizer)。通常选择 bert-base-uncased 作为基础模型,它适用于大多数通用英文场景。

from transformers import BertTokenizer, BertModel
import torch

# 加载预训练的 BERT 分词器和模型
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')

2. 文本预处理

BERT 对输入有特定的格式要求。在将文本送入模型之前,必须使用分词器将其转换为模型可接受的输入格式。这包括将文本分割为子词(Subwords),添加特殊的 [CLS][SEP] 标记,并生成注意力掩码(Attention Mask)以区分有效词和填充词。

text = "Hello, BERT!"
inputs = tokenizer(text, return_tensors='pt', padding=True, truncation=True, max_length=512)

3. 获取嵌入向量

调用模型进行前向传播。BERT 的输出通常包含最后一层所有隐藏状态(hidden states)。为了获得单个句子的嵌入,通常有两种策略:

  • [CLS] 标记的输出:这是最常用的方法,[CLS] 位置的向量被认为包含了整个序列的聚合语义信息。
  • 平均池化(Average Pooling):对所有非填充词的隐藏状态进行平均,有时能提供更平滑的语义表示。
with torch.no_grad():
    outputs = model(**inputs)

# 获取最后一层的隐藏状态
last_hidden_states = outputs.last_hidden_state

# 方法一:取 [CLS] 标记的向量 (batch_size, seq_len, hidden_size)
# 取第一个 token (即 [CLS]) 的向量
sentence_embedding = last_hidden_states[:, 0, :]

4. 归一化与使用

生成的嵌入向量通常需要进行 L2 归一化,以便在后续任务(如相似度计算、聚类或分类)中使用余弦相似度等指标。归一化后的向量可以直接用于计算两个句子或单词之间的语义距离。

sentence_embedding = torch.nn.functional.normalize(sentence_embedding, p=2, dim=1)

通过上述步骤,开发者仅需短短十几行代码,即可将任意文本转化为高维、富含上下文语义的 BERT 嵌入向量。

关键要点

  • 动态语义捕捉:与静态嵌入不同,BERT 生成的嵌入向量会根据上下文动态变化,能够准确区分多义词在不同语境下的含义。
  • Hugging Face Transformers 库:该库是连接开发者与预训练模型(如 BERT)的桥梁,极大简化了模型加载、分词和推理的过程,是实现“几行代码”的关键。
  • 输入预处理至关重要:必须严格遵循 BERT 的输入格式要求,包括添加特殊标记([CLS], [SEP])和处理填充(Padding),否则模型输出将无效。
  • 嵌入提取策略:虽然取 [CLS] 向量是最常见的做法,但在某些特定任务中,对隐藏状态进行平均池化或加权池化可能能获得更好的性能。
  • 归一化的必要性:在计算向量相似度之前,对嵌入向量进行 L2 归一化是标准操作,能确保余弦相似度计算的准确性。
  • 资源消耗考量:虽然代码简洁,但 BERT 模型本身较大,推理过程需要一定的 GPU 或 CPU 资源。对于大规模实时应用,可能需要考虑模型量化或蒸馏技术。

意义与影响

1. 降低 NLP 技术门槛

本文展示的方法证明了强大的预训练语言模型不再需要深厚的深度学习背景或庞大的算力集群才能使用。通过封装良好的 API,初级开发者甚至非 AI 专家也能快速集成 SOTA(State-of-the-Art)的语义理解能力,加速了 AI 技术在各行各业的应用落地。

2. 提升语义理解精度

在许多实际业务场景中,如搜索引擎、推荐系统、情感分析和问答系统,对文本语义的细微差别捕捉至关重要。BERT 嵌入提供的上下文感知能力,显著提升了这些系统在复杂语境下的表现,减少了因歧义导致的错误理解。

3. 推动标准化工作流

使用标准化的嵌入向量使得不同来源、不同格式的文本数据可以在统一的向量空间中进行比较和融合。这为构建统一的知识图谱、跨模态检索以及多语言处理奠定了数据基础。

4. 启发后续技术演进

这种“轻量级调用强大模型”的模式,不仅适用于 BERT,也适用于后续的 RoBERTa、DistilBERT 以及大语言模型(LLMs)。它确立了一种高效利用预训练资源进行下游任务开发的范式,鼓励开发者在现有基础模型之上进行创新,而非从零开始训练。

总之,通过几行 Python 代码使用 BERT 进行词嵌入,不仅是技术操作的简化,更是 NLP 技术民主化进程的一个缩影。它让语义理解这一核心 AI 能力变得触手可及,为构建更智能、更懂用户的应用程序提供了强有力的工具支撑。

查看原文 →infoq.cn