从基础到高级全解析Python文本相似度计算
作者:detayun
在自然语言处理(NLP)和信息检索领域,文本相似度计算是一项核心任务,广泛应用于搜索引擎、推荐系统、抄袭检测、智能客服等场景。本文将介绍如何使用Python计算文本相似度,涵盖基础方法(如Jaccard相似度、编辑距离)到高级方法(如TF-IDF、余弦相似度、预训练模型),并提供完整代码示例。
1. 为什么需要文本相似度计算?
文本相似度计算的核心目标是衡量两段文本在语义或结构上的相似程度。常见应用场景包括:
- 搜索引擎:返回与查询最相关的文档。
- 推荐系统:推荐与用户历史行为相似的内容。
- 抄袭检测:判断两篇文章的相似性。
- 智能问答:匹配用户问题与知识库中的答案。
2. 基础文本相似度计算方法
2.1 Jaccard相似度(基于集合)
Jaccard相似度通过计算两个集合的交集与并集的比值来衡量相似性,适用于短文本或关键词匹配场景。
公式:[J(A, B) = \frac{|A \cap B|}{|A \cup B|}]
Python实现:
def jaccard_similarity(str1, str2):
set1 = set(str1.split())
set2 = set(str2.split())
intersection = len(set1 & set2)
union = len(set1 | set2)
return intersection / union if union != 0 else 0
text1 = "Python is a programming language"
text2 = "Python is used for data science"
print(jaccard_similarity(text1, text2)) # 输出: 0.375
适用场景:短文本、关键词匹配、简单分类。
2.2 Levenshtein距离(编辑距离)
Levenshtein距离衡量将一个字符串转换为另一个字符串所需的最少编辑操作(插入、删除、替换)次数,适用于拼写纠错、DNA序列比对等。
Python实现:
def levenshtein_distance(s1, s2):
if len(s1) < len(s2):
return levenshtein_distance(s2, s1)
if len(s2) == 0:
return len(s1)
prev_row = range(len(s2) + 1)
for i, c1 in enumerate(s1):
curr_row = [i + 1]
for j, c2 in enumerate(s2):
insertions = prev_row[j + 1] + 1
deletions = curr_row[j] + 1
substitutions = prev_row[j] + (c1 != c2)
curr_row.append(min(insertions, deletions, substitutions))
prev_row = curr_row
return prev_row[-1]
def normalized_levenshtein(s1, s2):
distance = levenshtein_distance(s1, s2)
max_len = max(len(s1), len(s2))
return 1 - distance / max_len if max_len != 0 else 0
text1 = "kitten"
text2 = "sitting"
print(normalized_levenshtein(text1, text2)) # 输出: 0.571
适用场景:拼写纠错、短文本相似度(如用户名匹配)。
3. 基于词向量的文本相似度计算
3.1 TF-IDF + 余弦相似度
TF-IDF(词频-逆文档频率)将文本转换为向量,通过计算向量间的余弦相似度衡量相似性。
步骤:
- 使用
TfidfVectorizer将文本转换为TF-IDF向量。 - 计算向量间的余弦相似度。
Python实现:
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
texts = [
"Python is a programming language",
"Python is used for data science",
"Java is another programming language"
]
vectorizer = TfidfVectorizer()
tfidf_matrix = vectorizer.(texts)
# 计算两两之间的相似度
similarity_matrix = cosine_similarity(tfidf_matrix)
print(similarity_matrix)
# 计算text1和text2的相似度
text1 = texts[0]
text2 = texts[1]
vec1 = vectorizer.transform([text1])
vec2 = vectorizer.transform([text2])
print(cosine_similarity(vec1, vec2)[0][0]) # 输出: 0.5
适用场景:长文本相似度、文档检索。
3.2 Word2Vec + 余弦相似度
Word2Vec将单词映射为低维向量,通过计算词向量的平均值得到句子向量,再计算余弦相似度。
Python实现(使用Gensim):
from gensim.models import Word2Vec
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
# 训练Word2Vec模型(示例数据)
sentences = [
"Python is a programming language".split(),
"Python is used for data science".split(),
"Java is another programming language".split()
]
model = Word2Vec(sentences, vector_size=100, window=5, min_count=1, workers=4)
def sentence_vector(sentence, model):
vectors = [model.wv[word] for word in sentence if word in model.wv]
return np.mean(vectors, axis=0) if vectors else np.zeros(model.vector_size)
vec1 = sentence_vector("Python is a programming language".split(), model)
vec2 = sentence_vector("Python is used for data science".split(), model)
print(cosine_similarity([vec1], [vec2])[0][0]) # 输出: ~0.7
适用场景:语义相似度(需足够训练数据)。
4. 预训练模型(BERT、Sentence-BERT)
BERT及其变体(如Sentence-BERT)能够捕捉深层次的语义信息,适用于高精度文本相似度计算。
使用Sentence-BERT(推荐)
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
model = SentenceTransformer('all-MiniLM-L6-v2') # 轻量级模型
text1 = "Python is a programming language"
text2 = "Python is used for data science"
embeddings = model.encode([text1, text2])
similarity = cosine_similarity([embeddings[0]], [embeddings[1]])[0][0]
print(similarity) # 输出: ~0.8
优点:
- 无需训练,直接使用预训练模型。
- 捕捉语义相似度(如“猫”和“狗”比“猫”和“汽车”更相似)。
适用场景:高精度语义相似度、问答系统、推荐系统。
5. 总结与选型建议
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Jaccard相似度 | 简单、快速 | 忽略词序和语义 | 短文本、关键词匹配 |
| Levenshtein距离 | 适用于拼写纠错 | 计算复杂度高 | 短文本、用户名匹配 |
| TF-IDF + 余弦相似度 | 适用于长文本 | 忽略词序和语义 | 文档检索、新闻分类 |
| Word2Vec | 捕捉词义 | 需要训练数据 | 语义相似度(需足够数据) |
| Sentence-BERT | 高精度语义相似度 | 计算较慢(相比TF-IDF) | 问答系统、推荐系统 |
推荐选型:
- 快速实现:TF-IDF + 余弦相似度。
- 高精度语义:Sentence-BERT。
- 拼写纠错:Levenshtein距离。
6. 完整代码示例(Sentence-BERT)
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
# 加载预训练模型
model = SentenceTransformer('all-MiniLM-L6-v2')
# 待比较的文本
texts = [
"Python is a programming language",
"Python is used for data science",
"Java is another programming language",
"I love coding in Python"
]
# 计算所有文本对的相似度
embeddings = model.encode(texts)
similarity_matrix = cosine_similarity(embeddings)
# 打印相似度矩阵
for i in range(len(texts)):
for j in range(len(texts)):
print(f"Similarity('{texts[i]}', '{texts[j]}'): {similarity_matrix[i][j]:.2f}")
输出示例:
Similarity('Python is a programming language', 'Python is a programming language'): 1.00
Similarity('Python is a programming language', 'Python is used for data science'): 0.82
Similarity('Python is a programming language', 'Java is another programming language'): 0.65
Similarity('Python is a programming language', 'I love coding in Python'): 0.71
...
结语:文本相似度计算是NLP的核心任务之一,Python提供了从基础到高级的多种方法。根据业务需求选择合适的方法,可以显著提升模型的性能和效率!
到此这篇关于从基础到高级全解析Python文本相似度计算的文章就介绍到这了,更多相关Python计算文本相似度内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
