NLP进阶:相似度计算与Attention机制解析

一、相似度计算:从基础到进阶

相似度计算是NLP任务的核心基础,广泛应用于文本匹配、信息检索、推荐系统等场景。其核心目标是通过量化文本间的语义关联程度,为后续任务提供决策依据。

1.1 传统相似度方法

  • 词重叠相似度:基于词袋模型(Bag-of-Words)的Jaccard系数和余弦相似度,通过统计词共现频率衡量相似性。例如,计算两句话的词集合交集与并集的比例:

    1. def jaccard_similarity(text1, text2):
    2. set1 = set(text1.split())
    3. set2 = set(text2.split())
    4. intersection = len(set1 & set2)
    5. union = len(set1 | set2)
    6. return intersection / union if union > 0 else 0

    局限性:无法捕捉语义顺序和上下文关联,例如“苹果公司”与“公司苹果”会被误判为完全相似。

  • TF-IDF加权余弦相似度:通过词频-逆文档频率(TF-IDF)加权,降低高频无意义词(如“的”“是”)的权重。实现时需构建语料库的IDF字典:

    1. from sklearn.feature_extraction.text import TfidfVectorizer
    2. corpus = ["文本1内容", "文本2内容"]
    3. vectorizer = TfidfVectorizer()
    4. tfidf_matrix = vectorizer.fit_transform(corpus)
    5. similarity = (tfidf_matrix[0] * tfidf_matrix[1].T).toarray()[0][0]

    适用场景:短文本匹配、文档去重,但对长文本的语义理解能力有限。

1.2 深度语义相似度(DSSM)

基于深度学习的DSSM模型通过多层神经网络将文本映射到低维语义空间,直接计算向量间的余弦相似度。其典型结构包括:

  • 输入层:将文本转换为词向量或字符级向量。
  • 隐藏层:使用全连接或卷积网络提取特征。
  • 输出层:生成语义向量并计算相似度。

优势:可捕捉上下文语义,适用于长文本匹配。例如在问答系统中,通过DSSM计算问题与候选答案的相似度,筛选最优回答。

1.3 预训练模型下的相似度计算

BERT等预训练模型通过[CLS]标记的输出向量表示整句语义,结合余弦相似度或曼哈顿距离计算相似度:

  1. from transformers import BertModel, BertTokenizer
  2. import torch
  3. tokenizer = BertTokenizer.from_pretrained("bert-base-chinese")
  4. model = BertModel.from_pretrained("bert-base-chinese")
  5. text1 = "自然语言处理"
  6. text2 = "NLP技术"
  7. inputs1 = tokenizer(text1, return_tensors="pt", padding=True, truncation=True)
  8. inputs2 = tokenizer(text2, return_tensors="pt", padding=True, truncation=True)
  9. with torch.no_grad():
  10. outputs1 = model(**inputs1)
  11. outputs2 = model(**inputs2)
  12. cls_vector1 = outputs1.last_hidden_state[:, 0, :]
  13. cls_vector2 = outputs2.last_hidden_state[:, 0, :]
  14. similarity = torch.cosine_similarity(cls_vector1, cls_vector2, dim=1).item()

最佳实践:需结合任务微调模型,避免直接使用通用预训练参数导致语义偏差。

二、Attention机制:从基础到变体

Attention机制通过动态分配权重,使模型聚焦于关键信息,已成为NLP模型的标配组件。

2.1 基础Attention机制

  • 加性Attention:通过前馈神经网络计算查询(Query)与键(Key)的相似度,再经Softmax归一化得到权重:

    1. score(Q, K) = W^T * tanh(W_q Q + W_k K)
    2. attention_weight = Softmax(score)
    3. context_vector = attention_weight * V

    适用场景:需要非线性变换捕捉复杂关系的任务,如机器翻译中的长句对齐。

  • 点积Attention:直接计算Q与K的点积,再通过缩放因子(√d_k)避免梯度消失:

    1. score(Q, K) = Q^T K / d_k
    2. attention_weight = Softmax(score)

    优势:计算效率高,适合大规模并行化,是Transformer的核心组件。

2.2 自注意力(Self-Attention)

自注意力机制中,Q、K、V均来自同一输入序列,通过捕捉序列内元素间的关系生成上下文感知的表示。例如在句子“The cat sat on the mat”中,自注意力可发现“cat”与“mat”的空间关联。

实现步骤

  1. 线性变换生成Q、K、V矩阵。
  2. 计算缩放点积注意力。
  3. 多头注意力并行处理不同子空间信息。
  4. 拼接多头输出并通过线性层融合。

2.3 多头注意力(Multi-Head Attention)

通过将Q、K、V拆分为多个子空间(如8个头),每个头独立计算注意力后拼接,增强模型对不同位置和特征的捕捉能力。例如在文本分类中,不同头可分别关注语法结构、情感词汇等特征。

代码示例

  1. import torch.nn as nn
  2. class MultiHeadAttention(nn.Module):
  3. def __init__(self, embed_dim, num_heads):
  4. super().__init__()
  5. self.embed_dim = embed_dim
  6. self.num_heads = num_heads
  7. self.head_dim = embed_dim // num_heads
  8. self.q_linear = nn.Linear(embed_dim, embed_dim)
  9. self.k_linear = nn.Linear(embed_dim, embed_dim)
  10. self.v_linear = nn.Linear(embed_dim, embed_dim)
  11. self.out_linear = nn.Linear(embed_dim, embed_dim)
  12. def forward(self, query, key, value):
  13. batch_size = query.size(0)
  14. # 线性变换
  15. Q = self.q_linear(query).view(batch_size, -1, self.num_heads, self.head_dim).transpose(1, 2)
  16. K = self.k_linear(key).view(batch_size, -1, self.num_heads, self.head_dim).transpose(1, 2)
  17. V = self.v_linear(value).view(batch_size, -1, self.num_heads, self.head_dim).transpose(1, 2)
  18. # 缩放点积注意力
  19. scores = torch.matmul(Q, K.transpose(-2, -1)) / torch.sqrt(torch.tensor(self.head_dim, dtype=torch.float32))
  20. attention = torch.softmax(scores, dim=-1)
  21. out = torch.matmul(attention, V)
  22. # 拼接多头输出
  23. out = out.transpose(1, 2).contiguous().view(batch_size, -1, self.embed_dim)
  24. return self.out_linear(out)

2.4 层级注意力(Hierarchical Attention)

针对长文档或层次化结构(如段落-句子-词),层级注意力通过两阶段注意力机制分别捕捉局部和全局信息。例如在文档分类中,先对句子内词分配权重,再对文档内句子分配权重。

架构设计

  1. 词级注意力:对句子内词向量加权求和,生成句子表示。
  2. 句子级注意力:对文档内句子表示加权求和,生成文档表示。

三、性能优化与最佳实践

  1. 相似度计算的效率优化

    • 使用近似最近邻(ANN)库(如Faiss)加速大规模文本检索。
    • 对长文本采用分段计算或关键句抽取,减少计算量。
  2. Attention机制的稀疏化

    • 局部注意力:限制注意力范围(如仅关注前后k个词),降低计算复杂度。
    • 块状注意力:将序列划分为块,仅计算块内或块间注意力。
  3. 多模态注意力融合

    • 在图文匹配任务中,设计跨模态注意力机制,使图像区域与文本词动态交互。例如,通过共注意力(Co-Attention)同时更新图像和文本的表示。
  4. 可解释性增强

    • 可视化注意力权重图,分析模型对关键信息的聚焦程度。例如在医疗文本分类中,验证模型是否关注到疾病名称等核心词汇。

四、总结与展望

相似度计算与Attention机制是NLP模型理解语义和捕捉关键信息的核心工具。从传统的词重叠方法到深度语义匹配,从基础Attention到多头、层级变体,技术的演进不断推动着任务精度的提升。未来,随着模型规模的扩大和多模态数据的融合,如何设计更高效、可解释的注意力机制将成为研究重点。开发者可结合具体场景,灵活选择或组合上述方法,构建高性能的NLP系统。