對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了


對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

一、摘要

很多NLP相關的任務都需要分詞,而當文本語料比較多時,用python處理分詞任務的過程會比較消耗時間。本文測試了對pandas百萬級中文語料分詞的多種實現方案和相應的執行時間,希望讀者可以根據本次實驗的結果選擇適合自己的實現方式,節約分詞任務帶來的時間損耗。尤其是在沒有集群環境下,需要在單機上處理大量文本分詞任務時,可以有所參考。我們測試的多種方案中,最好的方案比最差的方案速度提升了318倍,最好的方案對百萬級中文語料分詞的總耗時僅有27.9秒!

二、python中文分詞工具

用python進行中文分詞任務,最常見的分詞工具是jieba,當然可以用Jython調用一些java的分詞工具,例如HanLP、Ansj等。本文主要討論jieba分詞工具。在python中使用jieba分詞工具,簡單、輕便,但是速度上不夠快,所以有了用Cpython重新實現了jieba的核心函數的分詞工具jieba_fast。jieba_fast分詞工具在保證了與jieba分詞工具一致性的基礎上,分詞速率大大提升。接下來,我們測試一下jieba和jieba_fast工具的分詞速率。

我們網上找來1000條文本,句子長度平均在20個字,首先導入兩個分詞工具:

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

我們寫一個計算函數執行時間的函數,如下:

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

定義兩個分詞函數進行分詞,如下:

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

測試這兩個分詞函數的執行時間,如下:

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

我們可以看到,對1000條文本進行分詞,jieba工具需要1.737秒,而jieba_fast工具只需要0.157秒,jieba_fast速度提升了近11倍,當文本數量更大時,節約的時間更加明顯。所以,在用python對中文文本進行分詞時,我們推薦使用jieba_fast分詞工具。

三、對Pandas逐行運算的加速

本次測試,我們用pandas讀取網絡上的公開中文文本進行分詞。共有137萬+的中文文本,單個文本字數平均為20個字,最小的字數為11,最大的字數為1170個字。

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

下面將用這份中文數據,測試多種對pandas dataframe逐行分詞運算的加速方案。

分詞函數定義如下:

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

3.1、普通的逐行遍歷dataframe

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

運行上述函數,查看執行時間:

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

可以看到用普通的逐行遍歷的方式,來對137萬的中文語料進行分詞,總耗時是229.7秒。

3.2、使用iterrows()函數遍歷dataframe

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

運行上述函數,查看執行時間:

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

可以看到用iterrows()函數遍歷的方式,來對137萬的中文語料進行分詞,總耗時488.3秒。

3.3、使用apply()函數進行遍歷dataframe

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

運行上述函數,查看執行時間:

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

可以看到用apply()函數遍歷的方式,來對137萬的中文語料進行分詞,總耗時227.9秒。

3.4、啟用joblib多進程+apply()函數進行遍歷

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

執行上述代碼,我們在後臺查看,是否啟用了多個進程來處理:

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

後臺看到確實啟用了多個進程來並行的跑job。我們再來看看執行時間:

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

採用joblib起多個進程來跑這個分詞任務時,我們震驚地發現執行時間竟然高達8895.7秒(2.5h)!

原因可能是多個進程之間頻繁的數據複製和傳輸,再加上多個數據之間的pd.concat 效率並不高。真是”一頓操作猛如虎,定睛一看原地杵“……

3.5、dataframe轉成numpy array之後再遍歷

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

運行上述函數,查看執行時間:

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

可以看到將dataframe轉化成numpy array之後再遍歷的方式,來對137萬的中文語料進行分詞,總耗時138.5秒。我們發現轉化成numpy array之後再遍歷比直接對dataframe遍歷要高效,速度大約提升1倍左右。

3.6、使用modin給pandas加速

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

運行上述函數,查看執行時間:

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

可以看到用modin給dataframe加速的方式,來對137萬的中文語料進行分詞,總耗時54.9秒。另外從輸出日誌中也可以看出來,modin也啟用了多個進程並行處理,只是多個進程之間不會將原始數據多次複製,所以處理速度大大提升了(modin啟用了redis)。

3.7、使用swifter對dataframe加速

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

運行上述函數,查看執行時間:

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

可以看到用swifter給dataframe加速的方式,來對137萬的中文語料進行分詞,總耗時278.2秒。另外,swifter處理過程會顯示進度條,顯示已經處理的數據條數、已經處理時間和預估剩餘時間等。

3.8、使用dask對dataframe加速

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

運行上述函數,查看執行時間:

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

可以看到用dask給dataframe加速的方式,來對137萬的中文語料進行分詞,總耗時僅需要27.9秒!非常迅速。我們在後臺可以看到啟用的多個進程的資源使用非常平衡。

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

四、總結一下

1、用Python對中文分詞,建議使用jieba_fast工具包代替jieba工具包。

2、各種對Pandas DataFrame的逐行迭代運算方案及其相應耗時如下:

對Pandas百萬級文本進行中文分詞加速,看這一篇就足夠了

對Pandas DataFrame遍歷加速,除了本文測試的之外,還有一種方式,就是使用Mars對pandas加速。至於Mars給pandas的提速可以達到多少,留給感興趣的讀者自行嘗試。


分享到:


相關文章: