Python中通用的文本相似度計(jì)算方法詳解
一、最長(zhǎng)公共子序列
最長(zhǎng)公共子序列(Longest Common Subsequence,LCS)是指兩個(gè)或多個(gè)序列中共同出現(xiàn)的一段連續(xù)序列,它在多個(gè)序列中都保持相同的順序和連續(xù)性。在計(jì)算機(jī)科學(xué)中,尋找最長(zhǎng)公共子序列是一個(gè)經(jīng)典問(wèn)題,通常通過(guò)動(dòng)態(tài)規(guī)劃算法解決。
動(dòng)態(tài)規(guī)劃算法解決最長(zhǎng)公共子序列問(wèn)題的步驟如下:
初始化狀態(tài)數(shù)組:創(chuàng)建一個(gè)二維數(shù)組dp,其大小為(m+1)×(n+1),其中m和n分別是兩個(gè)序列的長(zhǎng)度。dp[i][j]表示序列1的前i個(gè)字符與序列2的前j個(gè)字符的最長(zhǎng)公共子序列的長(zhǎng)度。
填充狀態(tài)數(shù)組:遍歷兩個(gè)序列,對(duì)于每一對(duì)字符,如果它們相同,則dp[i][j] = dp[i-1][j-1] + 1;如果不同,則dp[i][j] = max(dp[i-1][j], dp[i][j-1])。
找到最長(zhǎng)公共子序列:dp數(shù)組的最后一個(gè)元素dp[m][n]就是兩個(gè)序列的最長(zhǎng)公共子序列的長(zhǎng)度??梢酝ㄟ^(guò)回溯的方式找到具體的子序列。
python代碼如下:
## 最長(zhǎng)公共子序列計(jì)算最長(zhǎng)公共子串-------------------
def LCS(str_a, str_b):
if len(str_a) == 0 or len(str_b) == 0:
return 0
dp = [0 for _ in range(len(str_b) + 1)]
for i in range(1, len(str_a) + 1):
left_up = 0
dp[0] = 0
for j in range(1, len(str_b) + 1):
left = dp[j-1]
up = dp[j]
if str_a[i-1] == str_b[j-1]:
dp[j] = left_up + 1
else:
dp[j] = max([left, up])
left_up = up
return dp[len(str_b)]
#轉(zhuǎn)換最長(zhǎng)公共子序列為0-1之間的數(shù)值,結(jié)果越接近1,相似度越大
def LCS_Score(str_a, str_b):
return np.round(LCS(str_a, str_b)*2/(len(str_a)+len(str_b)),2)
#LCS_Score(str_a, str_b)
## 對(duì)dataframe的2列按照最長(zhǎng)公共子序列計(jì)算相似度
## df: 數(shù)據(jù)來(lái)源變量
## col_name1、col_name2:用于計(jì)算相似度的2個(gè)列名
## simarity_score_name: 返回的相似度結(jié)果的列名
## 返回?cái)?shù)據(jù)框,則simarity_score_name是用該計(jì)算方法對(duì)2列文本相似度的計(jì)算結(jié)果
def df_simarity_lcs(df , col_name1 , col_name2 , simarity_score_name):
df[simarity_score_name] = list(map(lambda str_a, str_b:LCS_Score(str_a, str_b),df[col_name1],df[col_name2]))
return df二、Jaccard相似度(Jaccard Similarity)
基于集合的交集與并集的比值來(lái)計(jì)算相似度。
適用于短文本或關(guān)鍵詞列表的比較。
## 采用集合的方法計(jì)算2個(gè)集合的相似度
def similarity(a, b):
try:
return len(a & b) / len(a | b)
except ZeroDivisionError:
return -1e-4
## 采用集合的方法計(jì)算一個(gè)數(shù)據(jù)框中2個(gè)列的文本相似度
## df: 數(shù)據(jù)來(lái)源變量
## col_name1、col_name2:用于計(jì)算相似度的2個(gè)列名
## simarity_score_name: 返回的相似度結(jié)果的列名
## 返回?cái)?shù)據(jù)框,則simarity_score_name是用該計(jì)算方法對(duì)2列文本相似度的計(jì)算結(jié)果
#對(duì)dataframe的2列按照集合的方法計(jì)算相似度
def df_simarity_jh(df , col_name1 , col_name2 , simarity_score_name):
df[simarity_score_name] = list(map(lambda str_a, str_b:similarity(set(str_a), set(str_b)),df[col_name1],df[col_name2]))
return df 三、余弦相似度(Cosine Similarity)
通過(guò)計(jì)算兩個(gè)文本向量在空間中的夾角余弦值來(lái)評(píng)估它們的相似度。
通常與詞袋模型(BOW)或TF-IDF結(jié)合使用。
## vec1, vec2:待計(jì)算的向量
## 返回2個(gè)向量的相似度
def cosine_simi(vec1, vec2):
from scipy import spatial
return 1 - spatial.distance.cosine(vec1, vec2)
## 對(duì)dataframe的2列按照最長(zhǎng)公共子序列計(jì)算相似度
## df: 數(shù)據(jù)來(lái)源變量
## col_name1、col_name2:用于計(jì)算相似度的2個(gè)列名
## simarity_score_name: 返回的相似度結(jié)果的列名
## 返回?cái)?shù)據(jù)框,則simarity_score_name是用該計(jì)算方法對(duì)2列文本相似度的計(jì)算結(jié)果
def df_simarity_cosine(df , col_name1 , col_name2 , simarity_score_name):
df[simarity_score_name] = list(map(lambda str_a, str_b:cosine_simi(str_a, str_b),df[col_name1],df[col_name2]))
return df
四、方法補(bǔ)充
除了上文的方法,小編還為大家整理了一些其他Python文件相似度計(jì)算的方法,希望對(duì)大家有所幫助
TF-IDF
TF-IDF是一種統(tǒng)計(jì)方法,用于評(píng)估單詞在文檔集中的重要性。它可以將文本表示為向量,進(jìn)而計(jì)算余弦相似度。
from sklearn.feature_extraction.text import TfidfVectorizer
def calculate_tfidf_cosine_similarity(text1, text2):
vectorizer = TfidfVectorizer()
corpus = [text1, text2]
vectors = vectorizer.fit_transform(corpus)
similarity = cosine_similarity(vectors)
return similarity[0][1]
text1 = "I love Python programming"
text2 = "Python programming is great"
tfidf_cosine_similarity = calculate_tfidf_cosine_similarity(text1, text2)
print(tfidf_cosine_similarity)
Word2Vec
Word2Vec是一種將單詞表示為向量的模型,可以捕捉單詞之間的語(yǔ)義關(guān)系。使用預(yù)訓(xùn)練的詞向量模型,可以計(jì)算文本之間的相似度。
import gensim.downloader as api
from gensim import matutils
import numpy as np
def calculate_word2vec_similarity(text1, text2):
model = api.load("word2vec-google-news-300")
tokens1 = text1.split()
tokens2 = text2.split()
vec1 = np.mean([model[token] for token in tokens1 if token in model], axis=0)
vec2 = np.mean([model[token] for token in tokens2 if token in model], axis=0)
return matutils.cosine(vec1, vec2)
text1 = "I love Python programming"
text2 = "Python programming is great"
word2vec_similarity = calculate_word2vec_similarity(text1, text2)
print(word2vec_similarity)
Doc2Vec
Doc2Vec是一種將文檔表示為向量的模型,可以捕捉文檔之間的語(yǔ)義關(guān)系。與Word2Vec類似,可以使用預(yù)訓(xùn)練的Doc2Vec模型計(jì)算文本之間的相似度。
from gensim.models import Doc2Vec
from gensim.models.doc2vec import TaggedDocument
def calculate_doc2vec_similarity(text1, text2):
corpus = [TaggedDocument(text1.split(), ["text1"]), TaggedDocument(text2.split(), ["text2"])]
model = Doc2Vec(corpus, vector_size=100, window=5, min_count=1, workers=4)
vec1 = model.docvecs["text1"]
vec2 = model.docvecs["text2"]
return matutils.cosine(vec1, vec2)
text1 = "I love Python programming"
text2 = "Python programming is great"
doc2vec_similarity = calculate_doc2vec_similarity(text1, text2)
print(doc2vec_similarity)
這些方法可以根據(jù)具體需求進(jìn)行選擇和組合,為自然語(yǔ)言處理任務(wù)提供強(qiáng)大的文本相似度計(jì)算能力。在實(shí)際應(yīng)用中,可能會(huì)遇到多種場(chǎng)景,例如推薦系統(tǒng)、自動(dòng)問(wèn)答和文本聚類等。在這些場(chǎng)景中,選擇合適的文本相似度計(jì)算方法至關(guān)重要。
BERT
BERT(Bidirectional Encoder Representations from Transformers)是一種基于Transformer的預(yù)訓(xùn)練模型,用于捕捉上下文相關(guān)的單詞表示??梢酝ㄟ^(guò)BERT模型將文本表示為向量,然后計(jì)算余弦相似度。
from sentence_transformers import SentenceTransformer
def calculate_bert_similarity(text1, text2):
model = SentenceTransformer("bert-base-nli-mean-tokens")
embeddings = model.encode([text1, text2])
similarity = cosine_similarity(embeddings)
return similarity[0][1]
text1 = "I love Python programming"
text2 = "Python programming is great"
bert_similarity = calculate_bert_similarity(text1, text2)
print(bert_similarity)
到此這篇關(guān)于Python中通用的文本相似度計(jì)算方法詳解的文章就介紹到這了,更多相關(guān)Python文本相似度計(jì)算內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python 中檢查一個(gè)字符是否為數(shù)字的示例代碼
本文詳細(xì)介紹了在 Python 中檢查一個(gè)字符是否為數(shù)字的幾種常用方法。我們介紹了使用 isdigit() 方法、isnumeric() 方法和正則表達(dá)式等方法,并提供了示例代碼幫助你理解和應(yīng)用這些方法,需要的朋友可以參考下2023-06-06
python監(jiān)控windows服務(wù)器的進(jìn)程和服務(wù)
這篇文章主要為大家詳細(xì)介紹了如何使用python監(jiān)控windows服務(wù)器的進(jìn)程和服務(wù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-04-04
動(dòng)感網(wǎng)頁(yè)相冊(cè) python編寫簡(jiǎn)單文件夾內(nèi)圖片瀏覽工具
這篇文章主要為大家詳細(xì)介紹了動(dòng)感網(wǎng)頁(yè)相冊(cè)的制作方法,即利用python編寫簡(jiǎn)單文件夾內(nèi)圖片瀏覽工具,感興趣的小伙伴們可以參考一下2016-08-08
Python如何將JavaScript轉(zhuǎn)換為json
文章介紹了如何使用Python的re模塊將JavaScript代碼轉(zhuǎn)換為JSON格式,首先,使用正則表達(dá)式匹配并替換JavaScript代碼中的數(shù)字,確保它們被雙引號(hào)括起來(lái),然后,使用另一個(gè)正則表達(dá)式匹配并替換JavaScript代碼中的鍵值對(duì),確保鍵和值都被雙引號(hào)括起來(lái)2025-02-02
用Python進(jìn)行柵格數(shù)據(jù)的分區(qū)統(tǒng)計(jì)和批量提取
該教程其實(shí)源于web,我看到之后覺(jué)得很實(shí)用,于是自己又重復(fù)做了一遍,寫了詳細(xì)的注釋分享給大家,希望對(duì)大家的研究有幫助,本文講述了柵格的分區(qū)統(tǒng)計(jì),批量提取,深化理解遍歷循環(huán)等內(nèi)容2021-05-05
python3如何使用Requests測(cè)試帶簽名的接口
這篇文章主要介紹了python3如何使用Requests測(cè)試帶簽名的接口,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
Python中數(shù)據(jù)類轉(zhuǎn)換為JSON的方法詳解
這篇文章主要介紹了Python中數(shù)據(jù)類轉(zhuǎn)換為JSON的方法詳解的相關(guān)資料,需要的朋友可以參考下2023-09-09

