日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

文本匹配算法综述

發布時間:2024/8/1 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 文本匹配算法综述 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文本匹配,顧名思義,就是描述兩段文本之間的關系,是否指向同一語義;比如兩句話是否描述同一件事,或者兩句話是否是上下文/問題與答案的關系。例:

小寶寶生病怎么辦狗寶寶生病怎么辦
明天天氣怎么樣明天預報有雨
先帝創業未半而中道崩殂今天下三分,益州疲弊,此誠危急存亡之秋也

文本匹配任務在自然語言處理中是非常重要的基礎任務之一,有很多應用場景;如信息檢索、問答系統、智能對話、文本鑒別、智能推薦、文本數據去重等,但文本匹配或者說自然語言處理仍然存在很多難點。

? ? ? ?如語言不規范,同一句話可以有多種表達方式;如“股市跳水、股市大跌、股市一片綠”

???????歧義,同一個詞語或句子在不同語境可能表達不同意思;如“割韭菜”,“領盒飯”,“能穿多少穿多少”,在不同語境下語義完全不同

? ? ? ? 不規范或錯誤的輸入;如 “?yyds”,“舉個栗子”

? ? ? ? 需要知識依賴;如豐田supra綽號“牛魔王”等。

????????

常見的文本匹配算法如下表,按傳統模型和深度模型簡單的分為兩類:

算法類型JaccordBM25VSMSimHashLevenshteincdssmarc-iimatch_pyramidmvlstmbimpmdrcnesimtextmatchingbert-basealbert-base

albert-large

rabertasbert
傳統模型
傳統模型
傳統模型
傳統模型
傳統模型
深度模型
深度模型
深度模型
深度模型
深度模型
深度模型
深度模型
深度模型
深度模型
深度模型
深度模型
深度模型
深度模型

接下來,讓我們通過一個例子,來具體看一下各個算法的實現過程及匹配效果(其中并沒有實現深度學習類算法)。

舉個栗子:

序號句1句2真實結果123
內蒙古錫林郭勒盟多倫縣縣醫院多倫縣醫院1(匹配)
綿陽市四零四醫院四川綿陽404醫院1(匹配)
鄧州市人民醫院南召縣人民醫院0(不匹配)

1.Jaccard杰卡德相似系數

????????jaccard相似度是一種非常直觀的相似度計算方式,即兩句子分詞后詞語的交集中詞語數與并集中詞語數之比。

def jaccard(list1, list2):"""jaccard相似系數:param list1:第一句話的詞列表 :param list2: 第二句話的詞列表:return:相似度,float值 """list1, list2 = set(list1), set(list2) #去重intersection = list1.intersection(list2) # 交集union = list1.union(list2) # 并集Similarity = 1.0 * len(intersection) / len(union) #交集比并集return Similarity

? a.分詞

????????內蒙古 錫林郭勒盟 多倫縣 縣醫院? ? /? ? 多倫縣 醫院

????????綿陽市? 四 零 四 醫院? ? ?/? ? ?四川 綿陽?404?醫院

????????鄧州市 人民 醫院? ? ? ?/? ? ? ?南召縣 人民 醫院

b.去重求交集--并集

? ? ? ? 多倫縣(交集)? ? --? ? ? 內蒙古、錫林郭勒盟、多倫縣縣醫院、醫院(并集)

? ? ? ? 醫院(交集)? ? ? --? ? ? ? 綿陽市、四、零、醫院、四川、綿陽、404(并集)

? ? ? ? 人民、醫院(交集)? ? --? ? ?鄧州市、人民、醫院、南召縣(并集)

c.相似度

文本對相似度真實標簽
內蒙古 錫林郭勒盟 多倫縣 縣醫院? ? /? ? 多倫縣 醫院1/5=0.21
綿陽市? 四 零 四 醫院? ? ?/? ? ?四川 綿陽?404?醫院1/7 = 0.141
鄧州市 人民 醫院? ? ? ?/? ? ? ?南召縣 人民 醫院2/4 = 0.50

????????

2.Levenshtein編輯距離

? ? ? ?一個句子轉換為另一個句子需要的編輯次數,編輯包括刪除、替換、添加,然后使用最長句子的長度歸一化得相似度。

def Levenshtein(text1, text2):"""Levenshtein編輯距離:param text1:字符串1:param text2:字符串2:return:相似度,float值"""import Levenshteindistance = Levenshtein.distance(text1, text2)Similarity = 1 - distance * 1.0 / max(len(text1), len(text2))return Similarity

a.分詞-計字數

????????內 蒙 古 錫 林 郭 勒 盟 多 倫 縣 縣 醫 院 (14)? ?/? ? 多 倫 縣 醫 院(5)

????????綿 陽 市? 四 零 四 醫 院(8)? ? ?/? ? ?四 川 綿 陽?4 0 4?醫 院(9)

????????鄧 州 市 人 民 醫 院 (7)? ? ? /? ? ? ?南 召 縣 人 民?醫 院(7)

b.計算編輯距離

? ? ? ?內 蒙 古 錫 林 郭 勒 盟 多 倫 縣 醫 院 ------->刪除內、蒙、古、錫、林、郭、勒、盟、縣

? ? ???綿 陽 ? 四 零 四 醫 院? ?------->加 四、川

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?------->刪除 市

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?------->替換 四(4)、零(0)、四(4)

? ? ? ?鄧 州 市 人 民 醫 院? ? ? ? ?------->替換鄧(南)、 州(召)、 市(縣)

文本對距離真實標簽
內蒙古 錫林郭勒盟 多倫縣 縣醫院? ? /? ? 多倫縣 醫院0.3571
綿陽市? 四 零 四 醫院? ? ?/? ? ?四川 綿陽?404?醫院0.3331
鄧州市 人民 醫院? ? ? ?/? ? ? ?南召縣 人民 醫院0.5710

3 simhash相似度

先計算兩句子的simhash二進制編碼,然后使用海明距離計算,最后使用兩句的最大simhash值歸一化得相似度。

def simhash_(text1, text2):"""simhash相似度:param s1: 字符串1:param s2: 字符串2:return: 相似度,float值"""from simhash import Simhashtext1_simhash = Simhash(text1, f=64) #計算simhash向量text2_simhash = Simhash(text2, f=64) #計算simhash向量distance = text1_simhash.distance(text2_simhash) #漢明距離Similarity = 1 - distance / max(len(bin(text1_simhash.value)), len(bin(text2_simhash.value))) #相似度return Similarity

a.分詞

????????內蒙古 錫林郭勒盟 多倫縣 縣醫院? ? /? ? 多倫縣 醫院

????????綿陽市? 四 零 四 醫院? ? ?/? ? ?四川 綿陽?404?醫院

????????鄧州市 人民 醫院? ? ? ?/? ? ? ?南召縣 人民 醫院

b.計算詞權重(此處用tfidf計算,其他方法也可以)

內蒙古5錫林郭勒盟5多倫縣2縣醫院5多倫縣7醫院1
綿陽市3四6零3四6醫院1四川5綿陽54045醫院1
?鄧州市7人民4醫院1南召縣7人民4醫院1

c.hash函數映射詞向量;先將詞映射到二進制編碼,然后用b步驟中的權重值替換1,b步驟中權重值的負數替換0

二進制編碼加權重
內蒙古1111000-5 5 5 5 5 -5 -5 -5
錫林郭勒盟1100000-5 5 5 -5 -5 -5 -5 -5
多倫縣1111011-2 2 2 2 2 -2 2 2
縣醫院101100105 -5 5 5 -5 -5 5 -5
多倫縣1111011-7 7 7 7 7 -7 7 7
醫院100100011 -1 -1 1 -1 -1 -1 1
綿陽市101111113 -3 3 3 3 3 3 3
111001006 6 6 -6 -6 6 -6 -6
1011110-3 3 -3 3 3 3 3 -3
111001006 6 6 -6 -6 6 -6 -6
醫院100100011 -1 -1 1 -1 -1 -1 1
四川1100001-5 5 5 -5 -5 -5 -5 5
綿陽111010-5 -5 5 5 5 -5 5 -5
4041010-5 -5 -5 -5 5 -5 5 -5
醫院100100011 -1 -1 1 -1 -1 -1 1
鄧州市101010117 -7 7 -7 7 -7 7 7
人民100010114 -4 -4 -4 4 -4 4 4
醫院100100011 -1 -1 1 -1 -1 -1 1
?南召縣111010107 7 7 -7 7 -7 7 -7
人民100010114 -4 -4 -4 4 -4 4 4
醫院100100011 -1 -1 1 -1 -1 -1 1

d.合并(將一段文本內的詞向量進行累加)

文本合并向量simhash值
內蒙古錫林郭勒盟多倫縣縣醫院-7 7 17 7 -3 -17 -3 -13-1 1 1 1 -1 -1 -1 -1
多倫縣醫院-6 6 6 8 6? -8 6 8-1 1 1 1 1 -1 1 1
綿陽市四零四醫院13 11 11 -5 -7 17 -7 -111 1 1 -1 -1 -1 -1 -1
四川 綿陽?404?醫院-14 -6 4 -4 4 -16 4 -4-1 -1 1 -1 1 -1 1 -1
鄧州市人民醫院?12 -12 2 -10 10 -12? ?10 121 -1 1 -1 1 -1 1 1?
南召縣人民醫院12 2 2 -10 10 -12 10 -21 1 1 -1 1 -1 1 -1

e海明距離判斷相似度

簡單的說,海明距離可以理解為,兩個二進制串之間相同位置不同的個數。舉個例子,[1,1,1,0,0,0]和[1,1,1,1,1,1]的海明距離就是3。

文本對海明距離真實標簽
內蒙古 錫林郭勒盟 多倫縣 縣醫院? ? /? ? 多倫縣 醫院31
綿陽市? 四 零 四 醫院? ? ?/? ? ?四川 綿陽?404?醫院41
鄧州市 人民 醫院? ? ? ?/? ? ? ?南召縣 人民 醫院20

4 Bm25相似度

一句話概況其主要思想:對Query(待查詢語句)進行語素解析,生成語素qi;然后,對于每個搜索結果D,計算每個語素qi與D的相關性得分,最后,將qi相對于D的相關性得分進行加權求和,從而得到Query與D的相關性得分。

其中,Q表示Query,qi表示Q解析之后的一個語素(對中文而言,我們可以把對Query的分詞作為語素分析,每個詞看成語素qi。);d表示一個搜索結果文檔;Wi表示語素qi的權重,為詞語的逆文檔頻率;R(qi,d)表示語素qi與文檔d的相關性得分。

其中,N是待匹配總文本數

? ? ? ? ? ?n(qt)是出現當前詞的文本數

其中?f(qi, D)為單詞在當前候選文檔中的詞頻

????????k1、b為調節因子,通常設為k1=2,b=0.75

????????|D|為當前候選文本數(與目標文本匹配的總條數)

????????avgdl為語料庫中所有文檔的平均長度。

#Bm25 import math import jieba class BM25(object):def __init__(self, docs):#docs是一個包含所有文本的列表,每個元素是一個文本self.D = len(docs) #總文本數self.avgdl = sum([len(doc)+0.0 for doc in docs]) / self.D #平均文本長度self.docs = docs #文本庫列表self.f = [] # 列表的每一個元素是一個dict,dict存儲著一個文檔中每個詞的出現次數self.df = {} # 存儲每個詞及出現了該詞的文檔數量self.idf = {} # 存儲每個詞的idf值self.k1 = 1.5self.b = 0.75self.init()def init(self):for doc in self.docs: #對每個文本tmp = {} #定義一個字典存儲詞出現頻次for word in doc:tmp[word] = tmp.get(word, 0) + 1 # 存儲每個文檔中每個詞的出現次數self.f.append(tmp)for k in tmp.keys():self.df[k] = self.df.get(k, 0) + 1for k, v in self.df.items():self.idf[k] = math.log(self.D-v+0.5)-math.log(v+0.5) #計算idfdef sim(self, doc, index):score = 0for word in doc:if word not in self.f[index]:continued = len(self.docs[index])score += (self.idf[word]*self.f[index][word]*(self.k1+1)/ (self.f[index][word]+self.k1*(1-self.b+self.b*d/ self.avgdl)))return scoredef simall(self, doc):scores = []for index in range(self.D):score = self.sim(doc, index)scores.append(score)return scoresif __name__ == '__main__':sents1 = ["多倫縣醫院", #數據庫"四川綿陽404醫院","南召縣人民醫院"]sents2 = ["內蒙古錫林郭勒盟多倫縣縣醫院","綿陽市四零四醫院","鄧州市人民醫院"]#待匹配文本doc = []for sent in sents1:words = list(jieba.cut(sent))doc.append(words)print(doc)s = BM25(doc)print(s.f)print(s.idf)for k in sents2:print(s.simall(jieba.lcut(k))) #打印相似度匹配結果 內蒙古錫林郭勒盟多倫縣縣醫院綿陽市四零四醫院鄧州市 人民 醫院多倫縣醫院四川 綿陽?404?醫院南召縣 人民 醫院
-1.68-1.69-1.94
-2.28-1.69-1.94
-2.28-1.69-1.43

5. VSM算法

VSM算法的思路主要分為兩步:

(1) 用向量表示句子,用向量表示句子的方法很多,簡單的有onehot,詞頻法,基于語義的有word2vec/fastText/glove/bert/elmo等,本例中使用基于簡單的詞頻的向量化方式。

(2)計算兩向量的余弦距離(曼哈頓距離、歐幾里得距離、明式距離、切比雪夫距離)得相似度。

#tfidf_余弦 def sim_vecidf(self, s1, s2):"""詞向量通過idf加權平均后計算余弦距離"""v1, v2 = [], []# 1. 詞向量idf加權平均for s in jieba.cut(s1):idf_v = idf.get(s, 1)if s in voc:v1.append(1.0 * idf_v * voc[s])v1 = np.array(v1).mean(axis=0)for s in jieba.lcut(s2):idf_v = idf.get(s, 1)if s in voc:v2.append(1.0 * idf_v * voc[s])v2 = np.array(v2).mean(axis=0)# 2. 計算cosinesim = self.cosine(v1, v2)return sim

a.句子向量化

a1.取句子對的唯一詞元組

set(內蒙古 錫林郭勒盟 多倫縣 縣醫院??/?多倫縣 醫院) = (內蒙古 錫林郭勒盟 多倫縣 縣醫院 醫院)

set(綿陽市? 四 零 四 醫院??/? 四川 綿陽?404?醫院) = (綿陽市? 四 零 醫院 四川 綿陽?404 )

set(鄧州市 人民 醫院? ?/? ?南召縣 人民 醫院) = (鄧州市 人民 醫院??南召縣)

a2.根據每個句子在元組中的詞頻建立向量表示

句子向量
內蒙古 錫林郭勒盟 多倫縣 縣醫院1 1 1 1 0???
多倫縣 醫院0 0 1 0 1
綿陽市? 四 零 四 醫院?1 2 1 1 0 0 0
四川 綿陽?404?醫院0 0 0 1 1 1 1
鄧州市 人民 醫院1 1 1 0
?南召縣 人民 醫院0 1 1 1

b.計算余弦距離

? ? ? ??????????????????

句子距離
內蒙古 錫林郭勒盟 多倫縣 縣醫院??/?多倫縣 醫院0.3535
綿陽市? 四 零 四 醫院??/? 四川 綿陽?404?醫院0.1889
鄧州市 人民 醫院? ?/? ?南召縣 人民 醫院0.6666

6.BERT模型+余弦相似度

BERT是谷歌在2018年推出的深度語言表示模型,是關于語言理解的深度雙向transformers的預訓練模型,開啟了預訓練模型的新篇章。它可以學習文本的語義信息,通過向量形式的輸出可以用于下游任務。也就說,它自己已經在大規模預料上訓練好的參數,我們在用的時候只需要在這個基礎上訓練更新參數。bert模型可以解決多種自然語言處理問題,如單文本分類、語句對分類、序列標注等。在解決文本匹配任務時,有兩種思路,第一種直接把文本匹配任務作為語句對分類任務,模型輸入語句對,輸出是否匹配的標簽;第二種利用bert模型預訓練文本對的上下文嵌入向量,再通過余弦相似度等相似度計算方法驗證文本對是否匹配,在此基礎上還有很多基于bert模型的變種,篇幅有限不做一一講述。BERT模型詳情請轉:(2條消息) 圖解Transformer(完整版)_龍心塵-CSDN博客_transformer,在此不做贅述。接下來簡單介紹一下bert預訓練文本嵌入+余弦相似度的算法框架。

a.首先使用大量公域文本數據對BERT模型進行預訓練(或直接用谷歌預訓練好的模型)

b.將文本直接輸入模型

c.對模型輸出的語義向量C,或中間隱層向量,計算余弦相似度,得到匹配結果。

基于深度學習的匹配算法種類繁多,如基于CNN網絡、RNN網絡、LSTM網絡等及各種變種層出不窮,在此不一一列舉實現。

傳統的文本匹配方法主要關注文本間字與字,詞與詞的匹配關系,無法準確識別不同表達方式下不同文本的同一指向關系,即語義關系。因此在這一背景下,要對多源異構的海量地址數據進行匹配,傳統的文本匹配方法已不再適用,深度學習方法大行其道。但深度學習方法也有自身的局限性,比如對海量文本和算力的高要求等,都使得深度學習方法的普適性大打折扣,因此沒有最好的文本匹配算法,只有當前條件下最適合的文本匹配算法。

參考文獻:

傳統文本匹配算法詳解(附代碼) - 知乎 (zhihu.com)

文本匹配利器:從孿生網絡到Sentence-BERT綜述 (360doc.com)

(2條消息) SimHash算法原理_qq_33905939的博客-CSDN博客

一種基于深度學習BERT算法的短文本相似匹配的方法 - 百度文庫 (baidu.com)

深度學習文本匹配簡述 - ZhangHT97 - 博客園 (cnblogs.com)

文本匹配模型TextMatching - 簡書 (jianshu.com)

(2條消息) BERT模型的結構,特點和實踐_dream6104的專欄-CSDN博客_bert模型結構

總結

以上是生活随笔為你收集整理的文本匹配算法综述的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。