)
5种Python文本相似度实战从基础算法到深度语义匹配文本相似度计算是自然语言处理中最实用的技术之一。想象一下你正在开发一个智能客服系统需要自动识别用户问题与知识库中已有问题的匹配程度或者你正在构建一个内容推荐引擎希望找到与用户刚阅读文章最相关的其他内容。这些场景的核心都是文本相似度计算。1. 环境准备与数据集在开始之前我们需要准备一个标准数据集来评估不同算法的效果。对于中文文本相似度计算LCQMCLarge-scale Chinese Question Matching Corpus是一个不错的选择它包含超过26万对中文问题对每对都有是否相似的标注。# 安装必要库 !pip install scikit-learn python-Levenshtein gensim sentence-transformers # 下载LCQMC数据集示例 import pandas as pd url https://raw.githubusercontent.com/liuhuanyong/ChineseSemanticKB/master/data/LCQMC_train.csv data pd.read_csv(url, sep\t, names[text1, text2, label]) sample_data data.sample(5) # 随机选取5对示例 print(sample_data)常用评估指标准确率AccuracyF1分数召回率Recall计算时间对于实时系统很重要2. 传统文本相似度方法2.1 TF-IDF与余弦相似度TF-IDF是文本处理中最经典的向量化方法它考虑了词频TF和逆文档频率IDF能够有效降低常见词的权重。from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity texts [我喜欢吃苹果, 苹果公司发布了新产品, 香蕉和苹果都是水果] # 创建TF-IDF向量器 vectorizer TfidfVectorizer() tfidf_matrix vectorizer.fit_transform(texts) # 计算相似度矩阵 similarity_matrix cosine_similarity(tfidf_matrix) print(TF-IDF余弦相似度矩阵:\n, similarity_matrix)适用场景短文本快速匹配如搜索引擎查询、文档去重等。2.2 编辑距离Levenshtein Distance编辑距离衡量两个字符串之间的最小编辑操作次数适用于拼写检查、OCR纠错等场景。from Levenshtein import distance str1 kitten str2 sitting edit_dist distance(str1, str2) max_len max(len(str1), len(str2)) similarity 1 - (edit_dist / max_len) print(f编辑距离: {edit_dist}) print(f标准化相似度: {similarity:.2f})注意编辑距离对字符顺序敏感苹果手机和手机苹果会被认为差异很大。3. 词向量方法3.1 Word2Vec平均词向量Word2Vec能够捕捉词语的语义信息我们可以通过平均词向量来表示整个句子。import gensim.downloader as api import numpy as np # 加载预训练的中文Word2Vec模型 wv api.load(word2vec-google-news-300) # 示例使用英文模型 def sentence_similarity(s1, s2): vec1 np.mean([wv[word] for word in s1.split() if word in wv], axis0) vec2 np.mean([wv[word] for word in s2.split() if word in wv], axis0) return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2)) text1 king queen palace text2 monarch castle print(fWord2Vec相似度: {sentence_similarity(text1, text2):.4f})局限性无法处理OOV词表外词语简单平均会丢失词序信息对多义词处理不佳3.2 使用Sentence-BERT进行语义匹配Sentence-BERTSBERT通过孪生网络结构直接生成句子级别的嵌入表示在语义相似度任务上表现优异。from sentence_transformers import SentenceTransformer, util # 加载预训练的中文SBERT模型 model SentenceTransformer(paraphrase-multilingual-MiniLM-L12-v2) sentences [ 如何重置我的密码, 忘记密码怎么办, 今天的天气真好 ] # 编码所有句子 embeddings model.encode(sentences) # 计算相似度 sim_matrix util.cos_sim(embeddings, embeddings) print(SBERT相似度矩阵:\n, sim_matrix)性能对比方法准确率计算速度内存占用TF-IDF中等快低编辑距离低很快很低Word2Vec中高中等中SBERT高较慢高4. 实战构建文本相似度系统让我们整合这些方法构建一个完整的文本相似度分析流程。class TextSimilarityAnalyzer: def __init__(self, methodsbert): self.method method if method sbert: self.model SentenceTransformer(paraphrase-multilingual-MiniLM-L12-v2) elif method tfidf: self.vectorizer TfidfVectorizer() def fit(self, texts): if self.method tfidf: self.vectorizer.fit(texts) def similarity(self, text1, text2): if self.method sbert: emb1 self.model.encode(text1) emb2 self.model.encode(text2) return util.cos_sim(emb1, emb2).item() elif self.method tfidf: vecs self.vectorizer.transform([text1, text2]) return cosine_similarity(vecs[0], vecs[1])[0][0] elif self.method edit: max_len max(len(text1), len(text2)) return 1 - (distance(text1, text2) / max_len) # 使用示例 analyzer TextSimilarityAnalyzer(methodsbert) text_a 如何开通网上银行 text_b 网上银行怎么申请 print(f相似度得分: {analyzer.similarity(text_a, text_b):.2f})优化技巧对于大规模数据可以先使用TF-IDF快速筛选候选集再用SBERT精细匹配可以组合多种相似度得分进行加权融合对于特定领域可以微调SBERT模型5. 高级应用与挑战5.1 处理长文档相似度对于长文档直接使用上述方法效果可能不佳。常见的解决方案包括分块处理将文档分成段落或句子分别计算相似度后聚合关键信息提取先抽取关键词、主题或摘要再计算相似度层次化方法先粗粒度匹配整体结构再细粒度匹配具体内容# 长文档分块示例 from nltk.tokenize import sent_tokenize def long_doc_similarity(doc1, doc2, model): # 分句 sents1 sent_tokenize(doc1) sents2 sent_tokenize(doc2) # 编码所有句子 emb1 model.encode(sents1) emb2 model.encode(sents2) # 计算所有句子对之间的相似度 sim_matrix util.cos_sim(emb1, emb2) # 取最大相似度作为段落间相似度 max_sims torch.max(sim_matrix, dim1)[0] return torch.mean(max_sims).item()5.2 跨语言相似度计算使用多语言模型如mBERT或XLM-R可以直接计算不同语言文本之间的相似度。# 加载多语言模型 multi_model SentenceTransformer(paraphrase-multilingual-MiniLM-L12-v2) chinese_text 我喜欢编程 english_text I enjoy coding # 计算跨语言相似度 emb1 multi_model.encode(chinese_text) emb2 multi_model.encode(english_text) similarity util.cos_sim(emb1, emb2) print(f中英文本相似度: {similarity.item():.2f})在实际项目中文本相似度的应用远不止于此。我曾经在一个电商项目中使用SBERT结合用户行为数据来优化商品推荐系统将点击率提升了15%。关键在于理解不同算法的特性并根据具体场景选择合适的方案。