Python Flashtext 實現大數據集下高效的關鍵詞查找和替換

2019-10-03     軟體測試開發技術棧

通常,我們使用Python 在文本中進行關鍵詞查找或替換時,會使用 re 模塊以正則的形式實現。在文本數量、文本內容、關鍵詞數量較小時,該方法能夠滿足我們程序的功能、性能需要。但當在大規模的文本或者對大量關鍵詞語料查找或者替換,re 實現方案的性能將成為瓶頸,本文我們將介紹一種新的關鍵詞搜索和替換的算法:Flashtext 算法,它是一個高效的字符搜索和替換算法。

有多高效呢?如下,是通過隨機生方式生成10000個單詞組成的文本,我們分別在該文本中查找由 0, 500, 1000, 5000, 10000, 50000, 100000, 200000, 400000 個關鍵詞組成的關鍵詞庫,我們來感受一下兩者的性能差異:

我們發現隨著關鍵詞查詢數量的增加,Flashtext 與 re 的時間消耗存在百倍乃至千倍以上的差異 。

為何存在這麼大的差異呢?Flashtext 算法的時間複雜度不依賴於查找或替換的字符的數量。如,對於一個文檔有 N 個字符,和一個有 M 個詞的關鍵詞庫,那麼時間複雜度就是 O(N) 。而正則匹配的時間複雜度是 O(M * N) 。這也是兩者在性能上的差異隨著關鍵詞數量增多而拉大的原因。

因此,在一些大數據下的內容檢索和替換,我們更傾向於選擇 Flashtext 算法 ,比如,自然語言處理領域中數據清洗是一項必須的操作。經常涉及使用標準的關鍵詞替換一些非標準的詞,如,將Javascript替換成JavaScript。或者我們需要判斷文本中是否存在JavaScript 關鍵詞等等。

接下來,就讓我們了解一下,如何使用Flashtext 實現關鍵詞的查找和替換。


FlashText

Flashtext 算法主要分為三部分,我們接下來將對每一部分進行單獨分析:

  1. 構建 Trie 字典
  2. 關鍵詞搜索
  3. 關鍵詞替換

構建 Trie 字典 (這部分不理解不影響我們使用Flashtext

Flashtext 是一種基於 Trie 字典數據結構和 Aho Corasick 的算法。它的工作方式是,首先它將所有相關的關鍵詞作為輸入,使用這些關鍵詞建立一個 trie 字典。

為了構建 trie 字典,Flashtext 創建一個空的節點指向空字典。這個節點被用作所有關鍵詞的起點。我們在字典中插入一個關鍵詞。這個關鍵詞中的下一個字符在本字典中作為關鍵詞,並且這個指針需要再次指向一個空字典。這個過程不斷重複,直到我們達到單詞中的最後一個字符。當我們到達單詞的末尾時,我們插入一個特殊的字符(eot)來表示詞尾,如下:

starteot 是兩個特殊的字符,用來定義關鍵詞的邊界,因此,也可知 Flashtext 只匹配完整的單詞,這個 trie 字典就是我們後面要用來搜索和替換的數據結構。

我們舉一個簡單的例子,假設我們有一個包含3個單詞的句子 「I like Python」,和一個有4個關鍵詞的語料庫 corpus = [Python,Java,J2ee,Ruby]。

Flashtext 算法將對於句子中的每一個單詞,檢查其是否在語料庫中出現,如下:

如果句子 N 個單詞,意味著需要做 N 次的循環操作。在這個例子中所需的時間步取決於句子中的單詞數。

如上,因為將文本中的每個字符串進行匹配,由於這是一個字符匹配過程,因為 start 並沒有和 l 相連,因此可以快速的跳過的I、like的匹配,這使得跳過缺失單詞的過程變得非常快。

因此,FlashText 算法不受 corpus 中關鍵詞數量的影響。


使用 Flashtext 進行搜索

我們對輸入文本中的字符進行逐個遍歷,當我們在文檔中的字符 word 匹配到字典中的 word 時,則認為這是一個完整匹配。我們將匹配到的字符序列所對應的標準關鍵詞進行輸出,具體如下:

代碼示例如下:


使用 Flashtext 進行替換

Flashtext 對輸入文本中的字符進行逐個遍歷,Flashtext 先創建一個空的字符串,當字符序列中的 word 無法在 Trie 字典中找到匹配時,那麼Flashtext 就簡單的原始字符複製到返回字符串中。但當Flashtext 可以從 Trie 字典中找到匹配時,那麼Flashtext 將把匹配到的字符的標準字符複製到返回字符串中。因此,返回字符串是輸入字符串的一個副本,唯一的不同是替換了匹配到的字符序列,具體如下:

代碼示例如下:


性能比對

在本文開始,我們首先介紹了使用 re模塊與 flashtext 模塊在不同數量的關鍵詞語料庫下,兩者的耗時情況差異,具體性能比對實現的源碼如下:

輸出結果:


Flashtext 常用方法及參數說明

add_keyword

添加關鍵詞。

語法

參數

  • keyword:檢索的詞。
  • clean_name:顯示或要被替換為的詞(默認keywords本身),如果匹配到keyword,則會返回clean_name。

示例


add_keywords_from_dict

添加多個關鍵詞。

語法

參數

  • keyword_dict:其中 key 類似於clean_name,value類似於keyword ,如果匹配到value,則會返回key。

示例


add_keywords_from_list

添加多個關鍵詞。

語法

參數

  • keyword_list:要添加的關鍵詞列表

示例


remove_keyword

刪除關鍵詞。

語法

參數

  • keyword:刪除的關鍵詞。

示例


remove_keywords_from_list

刪除多個關鍵詞。

語法

參數

  • keyword_list:要刪除的關鍵詞列表

示例


remove_keywords_from_dict

刪除多個關鍵詞。

語法

參數

  • keyword_list:其中 key 類似於clean_name,value類似於keyword 。

示例


文章來源: https://twgreatdaily.com/XC0ClW0BMH2_cNUgMxDN.html