[譯] 正規表示式要跑 5 天,所以我做了個工具,只跑 15 分鐘。

cf020031308發表於2018-08-10

[譯] 正規表示式要跑 5 天,所以我做了個工具,只跑 15 分鐘。

dia057 | Unsplash

當開發人員使用文字時,他們通常需要先清理它。有時是替換關鍵詞,就像用“JavaScript”替換“Javascript”一樣。其它時候,我們只想知道文件中是否提到了“JavaScript”。

像這樣的資料清理是大多數處理文字的資料科學專案的標準任務。

資料科學始於資料清理。

最近我有一項非常類似的工作。我在 Belong.co 擔任資料科學家,其中有一半工作是在做自然語言處理。

當我在我們的文件語料庫中訓練 Word2Vec 模型時,它最初會把同義詞當成近似術語給出。 比如“Javascripting”變成了“JavaScript”的近似術語。

為了解決這事,我編寫了一個正規表示式(Regex)來用標準化名稱替換所有已知的同義詞。比如將“JavaScripting”替換成“Javascript”。正規表示式解決了這一個問題,但創造了另一個問題。

有些人在面對一個問題時會想
“知道了,我該使用正規表示式。”現在他們有兩個問題了。

以上引用來自 stack-exchange 的問題,說的就是我這種。

事實證明,如果要搜尋和替換的關鍵詞數量在 100 個以內,正規表示式會很快。但我的語料庫有超過 2 萬個關鍵詞和 300 萬個檔案。

當我對我的正規表示式程式碼進行基準測試時,我發現它跑一次要花 5

[譯] 正規表示式要跑 5 天,所以我做了個工具,只跑 15 分鐘。

哦,恐怖

自然的解決方案是並行執行。但是,當我們的數量級達到文件千萬、關鍵詞十萬時,這將無濟於事。**必須有更好的方法!**我開始尋找......

我在辦公室和 Stack Overflow 上問了問 —— 收穫了一些建議。Vinay PandeySuresh LakshmananStack Overflow 指出了稱為 Aho-Corasick 演算法的美妙演算法,以及 Trie 資料結構方法。我尋找已有的解決方案,但找不到多少。

所以我編寫了自己的實現,FlashText 誕生了。

在我們瞭解什麼是 FlashText 以及它是如何工作的之前,讓我們看看它的搜尋效能:

[譯] 正規表示式要跑 5 天,所以我做了個工具,只跑 15 分鐘。

底部的紅線是 FlashText 搜尋所花費的時間

上面顯示的圖表是 1 個文件時編譯過的正規表示式與 FlashText 的比較。隨著關鍵詞數量的增加,正規表示式所用的時間幾乎呈線性增長,但 FlashText 對此並不敏感。

**FlashText 將執行時間從 5 天減少到 15 分鐘!! **

[譯] 正規表示式要跑 5 天,所以我做了個工具,只跑 15 分鐘。

這個好 :)

這是 FlashText 做替換時的計時:

[譯] 正規表示式要跑 5 天,所以我做了個工具,只跑 15 分鐘。

底部的紅線是 FlashText 用於替換的時間

用於上述基準測試的程式碼連結在此,結果連結在此

那麼什麼是 FlashText?

FlashText 是我在 GitHub 上開源的一個 Python 庫。它在提取關鍵詞和替換上都很高效。

要使用 FlashText,首先必須傳入一個關鍵詞列表。此列表將在內部用於構建 Trie 字典。然後傳入一個字串,並說明是要替換還是搜尋。

**替換**會建立一個替換了關鍵詞的新字串。**搜尋**會返回字串中找到的關鍵詞列表。在執行過程中,輸入的字串只會被掃描一遍。

以下是一位滿意的使用者對這庫的看法:

[譯] 正規表示式要跑 5 天,所以我做了個工具,只跑 15 分鐘。

@RadimRehurek@gensim_py 的建立者。

為什麼 FlashText 這麼快?

我們試著用一個例子來理解這部分。假設我們有一個句子,其中包含 3 個單詞 I like Python,以及一個包含 4 個單詞 {Python,Java,J2ee,Ruby} 的語料庫。

如果我們從語料庫中取出每個單詞,並檢查它是否存在於句子中,則需要 4 次嘗試。

'Python' 在句子中嗎?
'Java' 在句子中嗎?
...
複製程式碼

如果語料庫有 n 個詞,它就會重複 n 次。每個搜尋步驟 <word> 在句子中嗎? 都要獨自花費時間。這就是正規表示式匹配中發生的事情。

還有另一種方法與第一種方法相反:對於句子中的每個單詞,檢查它是否存在於語料庫中。

'I' 在語料庫中嗎?
'like' 在語料庫中嗎?
'Python' 在語料庫中嗎?
複製程式碼

如果句子中有 m 個詞,它就會重複 m 次。在這種情況下,它所花費的時間僅取決於句子中的單詞數量。而 <word> 在語料庫中嗎? 這一步可以使用字典查詢快速完成。

FlashText 演算法基於第二種方法。其靈感來自 Aho-Corasick 演算法和 Trie 資料結構。

它的工作方式是:
首先,使用語料庫建立 Trie 詞典。看起來有點像這樣:

[譯] 正規表示式要跑 5 天,所以我做了個工具,只跑 15 分鐘。

Trie 詞典的語料庫。

用 start 和 EOT(End Of Term)表示像 空格標點換行 這樣的單詞邊界。關鍵詞只有在其兩側都有單詞邊界時才匹配。這樣可以防止 pineapple 匹配到 apple。

接下來我們將輸入一個輸入字串 I like Python 並逐個字元地搜尋它。

第 1 步:<start>I<EOT> 在字典中嗎?不在。
第 2 步:<start>like<EOT> 在字典中嗎?不在。
第 3 步:<start>Python<EOT> 在字典中嗎?在。
複製程式碼

[譯] 正規表示式要跑 5 天,所以我做了個工具,只跑 15 分鐘。

<Start>Python<EOT> 在字典中。

因為這是逐個字元的匹配,所以我們可以很容易地在 <start>l 處就跳過 <start>like<EOT>,因為詞典的 <start> 後面沒有 l 這個字母。這樣可以快速跳過不在語料庫中的單詞。

FlashText 演算法只遍歷輸入字串 'I like Python' 的每個字元。字典哪怕有高達百萬個關鍵詞,對執行時也沒有影響。這就是 FlashText 演算法的真正力量。

那麼什麼時候應該使用 FlashText?

簡單的答案:當關鍵詞數 > 500 時

[譯] 正規表示式要跑 5 天,所以我做了個工具,只跑 15 分鐘。

對於搜尋,FlashText 在大約超過 500 個關鍵詞後效能優於正規表示式。

複雜的答案:正規表示式可以基於特殊字元搜尋關鍵詞,如 ^,$,*,\d,.,FlashText 不支援這個。

因此,如果您想像 word\dvec 這樣匹配部分詞,最好不要用 FlashText。但像 word2vec 這樣提取完整的單詞,就非常適合了。

用 FlashText 查詢關鍵詞

# pip install flashtext
from flashtext.keyword import KeywordProcessor
keyword_processor = KeywordProcessor()
keyword_processor.add_keyword('Big Apple', 'New York')
keyword_processor.add_keyword('Bay Area')
keywords_found = keyword_processor.extract_keywords('I love Big Apple and Bay Area.')
keywords_found
# ['New York', 'Bay Area']
複製程式碼

使用 FlashText 的簡單提取示例

用 FlashText 替換關鍵詞

您也可以替換句子中的關鍵詞,而不是提取它。我們用這作為資料處理流程中的資料清理步驟。

from flashtext.keyword import KeywordProcessor
keyword_processor = KeywordProcessor()
keyword_processor.add_keyword('Big Apple', 'New York')
keyword_processor.add_keyword('New Delhi', 'NCR region')
new_sentence = keyword_processor.replace_keywords('I love Big Apple and new delhi.')
new_sentence
# 'I love New York and NCR region.'
複製程式碼

使用 FlashText 的簡單替換示例

如果您認識誰在用文字資料、實體識別、自然語言處理或 Word2vec,請考慮與他們共享此博文。

這個庫對我們非常有用,我相信它對其他人也很有用。

終於講完了,感謝捧場 ?

如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章