类语义相似时,如何提升文本相似度匹配与分类性能?
FAQ同主题细粒度匹配优化方案
一、嵌入层优化:跳出全局语义陷阱
- 改用专门优化句对相似度的预训练模型:比如sentence-transformers的all-MiniLM-L6-v2,这类模型通过对比学习训练,针对同主题下的细粒度语义区分做了优化,比通用BERT的CLS向量更适配FAQ匹配场景,无需微调即可直接使用。
- 替换CLS向量为加权token嵌入聚合:原代码仅用CLS token,它容易被全局主题信息主导。可以计算所有token嵌入的加权平均,权重采用模型输出的注意力权重或TF-IDF权重,突出疑问词、核心动词这类关键信息的作用。
二、相似度分数的差异化处理
- Min-Max归一化分数:把所有FAQ的相似度分数映射到0-1区间,放大最优解和其他解的差距,避免因整体分数偏高导致阈值难以设置。
- 增加相对差异判断:除了绝对阈值,加入“最优分数与次优分数的差值”条件,比如只有当两者差值大于0.08时才返回匹配,否则弃权。这样能过滤掉多个FAQ相似度接近的模糊情况,提升匹配准确性。
三、规则辅助过滤:先缩小匹配范围
- 疑问词类型过滤:提取用户输入和FAQ的疑问词(是什么/如何/为什么),先筛选出疑问类型一致的FAQ,再计算相似度。比如用户问“如何预防X”,直接排除所有问“X是什么”的FAQ,减少无效计算的同时提升匹配精度。
- 核心实体匹配:提取输入和FAQ中的核心实体,优先保留实体一致的FAQ,再做语义相似度计算,进一步缩小候选范围。
四、优化后的代码示例
示例1:使用Sentence-Transformers模型+分数归一化
from sentence_transformers import SentenceTransformer, util import numpy as np def mapping(user_input: str, abstain_threshold: float, language_model='all-MiniLM-L6-v2', faqs_file='faqs.txt'): # 加载针对句相似度优化的预训练模型 model = SentenceTransformer(language_model) # 读取FAQ列表 with open(faqs_file, 'r') as f: faqs = [line.strip() for line in f] # 生成句向量 user_emb = model.encode(user_input, convert_to_tensor=True) faq_embs = model.encode(faqs, convert_to_tensor=True) # 计算余弦相似度 cos_scores = util.cos_sim(user_emb, faq_embs)[0].cpu().numpy() # 对分数做Min-Max归一化,放大差异 normalized_scores = (cos_scores - cos_scores.min()) / (cos_scores.max() - cos_scores.min() + 1e-6) # 获取最优和次优分数 sorted_indices = np.argsort(cos_scores)[::-1] max_score = cos_scores[sorted_indices[0]] second_max_score = cos_scores[sorted_indices[1]] if len(faqs) > 1 else 0 # 双重判断:绝对阈值 + 相对差异 if max_score >= abstain_threshold and (max_score - second_max_score) >= 0.08: return faqs[sorted_indices[0]] else: return None
示例2:增加疑问词规则过滤(兼容原模型)
from transformers import AutoTokenizer, AutoModel import torch import numpy as np from sklearn.metrics.pairwise import cosine_similarity import spacy # 加载英文分词与词性标注模型 nlp = spacy.load("en_core_web_sm") def get_question_category(text): doc = nlp(text.lower()) for token in doc: # 匹配疑问词对应的词性 if token.tag_ in ("WDT", "WP", "WRB"): if token.text in ["what", "who", "which"]: return "definition" elif token.text in ["how", "way", "method"]: return "procedure" elif token.text in ["why", "reason", "cause"]: return "explanation" return "other" def mapping(user_input: str, abstain_threshold: float, language_model='distilbert-base-uncased', faqs_file='faqs.txt'): # 加载模型和分词器 tokenizer = AutoTokenizer.from_pretrained(language_model) model = AutoModel.from_pretrained(language_model) # 读取FAQ列表 with open(faqs_file, 'r') as f: faqs = [line.strip() for line in f] # 先过滤同类型的FAQ user_category = get_question_category(user_input) filtered_faqs = [] original_indices = [] for idx, faq in enumerate(faqs): if get_question_category(faq) == user_category: filtered_faqs.append(faq) original_indices.append(idx) # 如果没有同类型FAQ,保留全部 if not filtered_faqs: filtered_faqs = faqs original_indices = list(range(len(faqs))) # 分词与张量转换(原逻辑,仅针对过滤后的FAQ) user_input_tokens = tokenizer.encode(user_input, add_special_tokens=True) faq_tokens = [tokenizer.encode(faq, add_special_tokens=True) for faq in filtered_faqs] max_len = max(len(tokens) for tokens in faq_tokens + [user_input_tokens]) user_input_tokens = user_input_tokens + [0] * (max_len - len(user_input_tokens)) faq_tokens = [tokens + [0] * (max_len - len(tokens)) for tokens in faq_tokens] user_input_tensor = torch.tensor(user_input_tokens).unsqueeze(0) faq_tensors = [torch.tensor(tokens).unsqueeze(0) for tokens in faq_tokens] # 生成嵌入 with torch.no_grad(): user_input_embedding = model(user_input_tensor)[0][:, 0, :] faq_transformer_embeddings = [model(faq_tensor)[0][:, 0, :] for faq_tensor in faq_tensors] # 计算相似度 faq_similarity_scores = [] for faq_emb in faq_transformer_embeddings: similarity = cosine_similarity(user_input_embedding, faq_emb)[0][0] faq_similarity_scores.append(similarity) # 找到最优匹配 max_score_index = np.argmax(faq_similarity_scores) max_score = faq_similarity_scores[max_score_index] best_match = faqs[original_indices[max_score_index]] # 阈值判断(可增加相对差异条件) if max_score >= abstain_threshold: return best_match else: return None
内容的提问来源于stack exchange,提问作者cookie1986
相关产品推荐
相关产品推荐

