Python根據(jù)字符串語(yǔ)義相似度計(jì)算的多種實(shí)現(xiàn)算法
以下是幾種基于語(yǔ)義的字符串相似度計(jì)算方法,每種方法都會(huì)返回0.0到1.0之間的相似度分?jǐn)?shù)(保留一位小數(shù))。
方法1:計(jì)算 Levenshtein 距離 (基于字符的相似度)
如果需要基于字符的相似度而非語(yǔ)義,可以使用 Levenshtein 距離。
先安裝模塊:
pip install Levenshtein
案例代碼:
import Levenshtein
def levenshtein_similarity(text1, text2):
# 計(jì)算 Levenshtein 距離
distance = Levenshtein.distance(text1, text2)
# 計(jì)算相似度并保留一位小數(shù)
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預(yù)訓(xùn)練模型
Sentence Transformers 可以將文本轉(zhuǎn)換為語(yǔ)義向量,然后通過(guò)余弦相似度計(jì)算文本之間的相似度。
使用Sentence-BERT模型計(jì)算語(yǔ)義相似度,需要先安裝:
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])
# 計(jì)算余弦相似度
cosine_score = util.cos_sim(embeddings[0], embeddings[1])
# 轉(zhuǎn)換為0-1范圍并保留一位小數(shù)
similarity = float(np.clip(cosine_score.item(), 0.0, 1.0))
return round(similarity, 1)
# 示例
print(semantic_similarity_sbert("我喜歡吃蘋果", "我愛吃水果")) # 輸出類似: 0.8
方法3:使用spaCy進(jìn)行語(yǔ)義相似度比較
spaCy 是一個(gè)強(qiáng)大的自然語(yǔ)言處理庫(kù),可以通過(guò)預(yù)訓(xùn)練模型來(lái)計(jì)算兩個(gè)文本的語(yǔ)義相似度。
需要先安裝:
pip install spacy
英語(yǔ)模型,需要先安裝:
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)
# 計(jì)算語(yǔ)義相似度并保留一位小數(shù)
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 是一種基于詞向量的距離度量,可以用來(lái)計(jì)算文本之間的語(yǔ)義差異,通過(guò)轉(zhuǎn)換為相似度。
import spacy
import numpy as np
def semantic_similarity_spacy(str1, str2):
"""
使用spaCy的詞向量計(jì)算語(yǔ)義相似度
"""
nlp = spacy.load("zh_core_web_lg")
doc1 = nlp(str1)
doc2 = nlp(str2)
# 計(jì)算余弦相似度
similarity = doc1.similarity(doc2)
# 確保在0-1范圍內(nèi)并保留一位小數(shù)
return round(max(0.0, min(1.0, similarity)), 1)
# 示例
print(semantic_similarity_spacy("今天天氣很好", "明天的天氣不錯(cuò)")) # 輸出類似: 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 # 必須導(dǎo)入
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])
# 計(jì)算余弦相似度
similarity = np.inner(embeddings[0], embeddings[1]) / (
np.linalg.norm(embeddings[0]) * np.linalg.norm(embeddings[1])
)
# 確保在0-1范圍內(nèi)并保留一位小數(shù)
return round(max(0.0, min(1.0, similarity)), 1)
# 示例
print(semantic_similarity_use("這只貓很可愛", "那只貓咪非常漂亮")) # 輸出類似: 0.8
方法6:使用BERT-as-Service
使用BERT-as-Service計(jì)算語(yǔ)義相似度
需要先安裝:
pip install bert-serving-server bert-serving-client
并下載預(yù)訓(xùn)練模型運(yùn)行服務(wù)端
from bert_serving.client import BertClient
import numpy as np
def semantic_similarity_bert(str1, str2):
"""
"""
bc = BertClient()
# 編碼句子
embeddings = bc.encode([str1, str2])
# 計(jì)算余弦相似度
similarity = np.dot(embeddings[0], embeddings[1]) / (
np.linalg.norm(embeddings[0]) * np.linalg.norm(embeddings[1])
)
# 確保在0-1范圍內(nèi)并保留一位小數(shù)
return round(max(0.0, min(1.0, similarity)), 1)
# 示例
# print(semantic_similarity_bert("他正在跑步", "他在運(yùn)動(dòng)")) # 輸出類似: 0.9
方法7:使用TF-IDF和余弦相似度(基于詞頻統(tǒng)計(jì))
這是一種基于詞頻的相似度計(jì)算方法。
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和余弦相似度計(jì)算文本相似度
基于詞頻統(tǒng)計(jì),不是真正的語(yǔ)義相似度,但可以作為基線方法
"""
vectorizer = TfidfVectorizer()
tfidf_matrix = vectorizer.fit_transform([str1, str2])
# 計(jì)算余弦相似度
similarity = cosine_similarity(tfidf_matrix[0:1], tfidf_matrix[1:2])[0][0]
# 確保在0-1范圍內(nèi)并保留一位小數(shù)
return round(max(0.0, min(1.0, similarity)), 1)
# 示例
print(semantic_similarity_tfidf("深度學(xué)習(xí)", "神經(jīng)網(wǎng)絡(luò)")) # 輸出類似: 0.6
方法8:博主自創(chuàng)算法
結(jié)巴分詞、TF-IDF的余弦相似度、標(biāo)準(zhǔn)化編輯距離相似度:
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):
"""標(biāo)準(zhǔn)化編輯距離相似度(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):
"""綜合語(yǔ)義相似度(保留1位小數(shù))"""
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 = "第十八條 【商標(biāo)代理】外國(guó)人或者外國(guó)企業(yè)在中國(guó)申請(qǐng)商標(biāo)注冊(cè)和辦理其他商標(biāo)事宜的,應(yīng)當(dāng)委托國(guó)家認(rèn)可的具有商標(biāo)代理資格的組織代理。"
str2 = "第十八條 申請(qǐng)商標(biāo)注冊(cè)或者辦理其他商標(biāo)事宜,可以自行辦理,也可以委托依法設(shè)立的商標(biāo)代理機(jī)構(gòu)辦理。"
print(f"相似度: {ss.combined_similarity(str1, str2)}")
綜合比較
- Levenshtein:基于字符的相似度而非語(yǔ)義,簡(jiǎn)單快速,但不是真正的語(yǔ)義相似度
- Sentence-BERT:輕量級(jí),效果好,支持多語(yǔ)言,推薦使用
- spaCy:中等大小,適合英文,中文需要大模型
- TF-IDF:簡(jiǎn)單快速,但不是真正的語(yǔ)義相似度
- USE:Google官方模型,效果好但模型較大
- BERT-as-Service:需要額外服務(wù),適合生產(chǎn)環(huán)境
- 博主自創(chuàng)算法:結(jié)合了結(jié)巴分詞、TF-IDF的余弦相似度、標(biāo)準(zhǔn)化編輯距離,效果好,運(yùn)行速度塊,并且還可以自行修改占比。
注意事項(xiàng)
- 中文處理需要確保使用支持中文的模型
- 語(yǔ)義相似度計(jì)算通常需要較多的計(jì)算資源
- 對(duì)于生產(chǎn)環(huán)境,建議使用Sentence-BERT或USE
- 首次使用某些方法需要下載大型預(yù)訓(xùn)練模型
選擇哪種方法取決于你的具體需求、計(jì)算資源和語(yǔ)言要求。
以上就是Python根據(jù)字符串語(yǔ)義相似度計(jì)算的多種實(shí)現(xiàn)算法的詳細(xì)內(nèi)容,更多關(guān)于Python字符串語(yǔ)義相似度算法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
pytorch 如何使用amp進(jìn)行混合精度訓(xùn)練
這篇文章主要介紹了pytorch 使用amp進(jìn)行混合精度訓(xùn)練的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-05-05
beam search及pytorch的實(shí)現(xiàn)方式
這篇文章主要介紹了beam search及pytorch的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-05-05
Pygame實(shí)戰(zhàn)練習(xí)之一百層游戲
跳上一百層想必是很多人童年時(shí)期的經(jīng)典游戲,我們依舊能記得抱個(gè)老人機(jī)娛樂(lè)的場(chǎng)景,下面這篇文章主要給大家介紹了關(guān)于如何利用python寫一個(gè)簡(jiǎn)單的跳上一百層小游戲的相關(guān)資料,需要的朋友可以參考下2021-09-09
python機(jī)器學(xué)習(xí)之決策樹分類詳解
這篇文章主要介紹了python機(jī)器學(xué)習(xí)之決策樹分類,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12

