基于Python根据两个字符串给出相似度/近似度_Python实现字符串语义相似度算法(附上多种实现算法)

以下是几种基于语义的字符串相似度计算方法,每种方法都会返回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. 首次使用某些方法需要下载大型预训练模型

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

袁袁袁袁满

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值