以下是几种基于语义的字符串相似度计算方法,每种方法都会返回0.0到1.0之间的相似度分数(保留一位小数)。
方法1:计算 levenshtein 距离 (基于字符的相似度)
如果需要基于字符的相似度而非语义,可以使用 levenshtein 距离。
先安装模块:
pip install levenshtein
案例代码:
import levenshtein def levenshtein_similarity(text1, text2): # 计算 levenshtein 距离 distance = levenshtein.distance(text1, text2) # 计算相似度并保留一位小数 max_len = max(len(text1), len(text2)) similarity = round(1 - (distance / max_len), 1) if max_len > 0 else 1.0 return similarity # 示例用法 text1 = "kitten" text2 = "sitting" print(levenshtein_similarity(text1, text2)) # 输出为 0.5
方法2:使用sentence-bert预训练模型
sentence transformers 可以将文本转换为语义向量,然后通过余弦相似度计算文本之间的相似度。
使用sentence-bert模型计算语义相似度,需要先安装:
pip install sentence-transformers
案例代码:
from sentence_transformers import sentencetransformer, util import numpy as np def semantic_similarity_sbert(str1, str2): model = sentencetransformer('paraphrase-multilingual-minilm-l12-v2') # 编码句子 embeddings = model.encode([str1, str2]) # 计算余弦相似度 cosine_score = util.cos_sim(embeddings[0], embeddings[1]) # 转换为0-1范围并保留一位小数 similarity = float(np.clip(cosine_score.item(), 0.0, 1.0)) return round(similarity, 1) # 示例 print(semantic_similarity_sbert("我喜欢吃苹果", "我爱吃水果")) # 输出类似: 0.8
方法3:使用spacy进行语义相似度比较
spacy 是一个强大的自然语言处理库,可以通过预训练模型来计算两个文本的语义相似度。
需要先安装:
pip install spacy
英语模型,需要先安装:
python -m spacy download en_core_web_md
中文模型:
python -m spacy download zh_core_web_lg
案例代码:
import spacy def spacy_similarity(text1, text2): # 加载模型 nlp = spacy.load('zh_core_web_lg') doc1 = nlp(text1) doc2 = nlp(text2) # 计算语义相似度并保留一位小数 similarity = round(doc1.similarity(doc2), 1) return similarity # 示例用法 text1 = "the cat sits on the mat." text2 = "a cat is resting on a mat." print(spacy_similarity(text1, text2)) # 输出可能为 0.8
方法4:使用spacy和词向量
使用 word mover’s distance (wmd),wmd 是一种基于词向量的距离度量,可以用来计算文本之间的语义差异,通过转换为相似度。
import spacy import numpy as np def semantic_similarity_spacy(str1, str2): """ 使用spacy的词向量计算语义相似度 """ nlp = spacy.load("zh_core_web_lg") doc1 = nlp(str1) doc2 = nlp(str2) # 计算余弦相似度 similarity = doc1.similarity(doc2) # 确保在0-1范围内并保留一位小数 return round(max(0.0, min(1.0, similarity)), 1) # 示例 print(semantic_similarity_spacy("今天天气很好", "明天的天气不错")) # 输出类似: 0.7
方法5:使用universal sentence encoder (use)
使用google的universal sentence encoder需要先安装:
pip install tensorflow-hub tensorflow-text
注意: 首次使用需要下载模型(约900mb)
import tensorflow_hub as hub import tensorflow_text as text # 必须导入 import numpy as np def semantic_similarity_use(str1, str2): """ """ module = hub.load("https://tfhub.dev/google/universal-sentence-encoder-multilingual/3") # 编码句子 embeddings = module([str1, str2]) # 计算余弦相似度 similarity = np.inner(embeddings[0], embeddings[1]) / ( np.linalg.norm(embeddings[0]) * np.linalg.norm(embeddings[1]) ) # 确保在0-1范围内并保留一位小数 return round(max(0.0, min(1.0, similarity)), 1) # 示例 print(semantic_similarity_use("这只猫很可爱", "那只猫咪非常漂亮")) # 输出类似: 0.8
方法6:使用bert-as-service
使用bert-as-service计算语义相似度
需要先安装:
pip install bert-serving-server bert-serving-client
并下载预训练模型运行服务端
from bert_serving.client import bertclient import numpy as np def semantic_similarity_bert(str1, str2): """ """ bc = bertclient() # 编码句子 embeddings = bc.encode([str1, str2]) # 计算余弦相似度 similarity = np.dot(embeddings[0], embeddings[1]) / ( np.linalg.norm(embeddings[0]) * np.linalg.norm(embeddings[1]) ) # 确保在0-1范围内并保留一位小数 return round(max(0.0, min(1.0, similarity)), 1) # 示例 # print(semantic_similarity_bert("他正在跑步", "他在运动")) # 输出类似: 0.9
方法7:使用tf-idf和余弦相似度(基于词频统计)
这是一种基于词频的相似度计算方法。
from sklearn.feature_extraction.text import tfidfvectorizer from sklearn.metrics.pairwise import cosine_similarity import numpy as np def semantic_similarity_tfidf(str1, str2): """ 使用tf-idf和余弦相似度计算文本相似度 基于词频统计,不是真正的语义相似度,但可以作为基线方法 """ vectorizer = tfidfvectorizer() tfidf_matrix = vectorizer.fit_transform([str1, str2]) # 计算余弦相似度 similarity = cosine_similarity(tfidf_matrix[0:1], tfidf_matrix[1:2])[0][0] # 确保在0-1范围内并保留一位小数 return round(max(0.0, min(1.0, similarity)), 1) # 示例 print(semantic_similarity_tfidf("深度学习", "神经网络")) # 输出类似: 0.6
方法8:博主自创算法
结巴分词、tf-idf的余弦相似度、标准化编辑距离相似度:
import jieba from sklearn.feature_extraction.text import tfidfvectorizer from sklearn.metrics.pairwise import cosine_similarity import levenshtein class semanticsimilarity: def __init__(self): self.vectorizer = tfidfvectorizer() def tokenize(self, text): """中文分词处理""" return ' '.join(jieba.lcut(text)) def tfidf_cosine(self, str1, str2): """基于tf-idf的余弦相似度(0-1)""" corpus = [self.tokenize(str1), self.tokenize(str2)] tfidf = self.vectorizer.fit_transform(corpus) return max(0.0, min(1.0, cosine_similarity(tfidf[0], tfidf[1])[0][0])) def edit_similarity(self, str1, str2): """标准化编辑距离相似度(0-1)""" distance = levenshtein.distance(str1, str2) max_len = max(len(str1), len(str2)) return max(0.0, min(1.0, 1 - (distance / max_len))) if max_len > 0 else 1.0 def combined_similarity(self, str1, str2): """综合语义相似度(保留1位小数)""" tfidf_score = self.tfidf_cosine(str1, str2) edit_score = self.edit_similarity(str1, str2) return round(0.6 * tfidf_score + 0.4 * edit_score, 1) if __name__ == '__main__': ss = semanticsimilarity() str1 = "第十八条 【商标代理】外国人或者外国企业在中国申请商标注册和办理其他商标事宜的,应当委托国家认可的具有商标代理资格的组织代理。" str2 = "第十八条 申请商标注册或者办理其他商标事宜,可以自行办理,也可以委托依法设立的商标代理机构办理。" print(f"相似度: {ss.combined_similarity(str1, str2)}")
综合比较
- levenshtein:基于字符的相似度而非语义,简单快速,但不是真正的语义相似度
- sentence-bert:轻量级,效果好,支持多语言,推荐使用
- spacy:中等大小,适合英文,中文需要大模型
- tf-idf:简单快速,但不是真正的语义相似度
- use:google官方模型,效果好但模型较大
- bert-as-service:需要额外服务,适合生产环境
- 博主自创算法:结合了结巴分词、tf-idf的余弦相似度、标准化编辑距离,效果好,运行速度块,并且还可以自行修改占比。
注意事项
- 中文处理需要确保使用支持中文的模型
- 语义相似度计算通常需要较多的计算资源
- 对于生产环境,建议使用sentence-bert或use
- 首次使用某些方法需要下载大型预训练模型
选择哪种方法取决于你的具体需求、计算资源和语言要求。
以上就是python根据字符串语义相似度计算的多种实现算法的详细内容,更多关于python字符串语义相似度算法的资料请关注代码网其它相关文章!
发表评论