对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的提速可以达到多少,留给感兴趣的读者自行尝试。


分享到:


相關文章: