当前位置: 代码网 > it编程>前端脚本>Python > Python根据字符串语义相似度计算的多种实现算法

Python根据字符串语义相似度计算的多种实现算法

2025年07月31日 Python 我要评论
以下是几种基于语义的字符串相似度计算方法,每种方法都会返回0.0到1.0之间的相似度分数(保留一位小数)。方法1:计算 levenshtein 距离 (基于字符的相似度)如果需要基于字符的相似度而非语

以下是几种基于语义的字符串相似度计算方法,每种方法都会返回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的余弦相似度、标准化编辑距离,效果好,运行速度块,并且还可以自行修改占比。

注意事项

  1. 中文处理需要确保使用支持中文的模型
  2. 语义相似度计算通常需要较多的计算资源
  3. 对于生产环境,建议使用sentence-bert或use
  4. 首次使用某些方法需要下载大型预训练模型

选择哪种方法取决于你的具体需求、计算资源和语言要求。

以上就是python根据字符串语义相似度计算的多种实现算法的详细内容,更多关于python字符串语义相似度算法的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com