我正在使用pycontractions中的函数尝试将文本扩展为语法准确的形式。它可以工作,但是速度非常慢,我不禁要问,我是否在做不必要的事情,从而导致性能下降。供参考,大约需要一分钟才能输出。

from pycontractions import Contractions

def cont_expand(a):
    cont = Contractions(api_key="glove-twitter-100")
    expText = cont.expand_texts(a, precise=False)

return expText

mystr = ["I'd like to have lunch today"]
x = list(cont_expand(mystr))

最佳答案

我以前没有听说过pycontractions库,也没有使用过它,但是从快速的角度看,我有一些想法。

首先,关于您的用法:

Contractions对象需要从磁盘加载一大堆预先存在的字向量,以进行一些分析。它还需要实例化另一个库language-check,该库显然包装在基于Java的语法检查实用程序上。

查看source code时,我发现实际上是在expand_texts()期间首次需要时才以惰性方式进行这些初始化,而不是在提供api_key='glove-twitter-100'时在对象初始化期间进行的。)

在像探测值这样的小文字上,这可能是运行时的最大贡献者。因此,刚初始化的expand_texts()对象上的单个Contractions不能准确指示该对象在跟随类似文本时的性能。因此,假设您的实际用法是每个Python调用包含多个文本,则应该:


更改您的代码以重新使用单个实例化的Contractions对象
强制该对象完全加载其子组件,并在实际工作进行基准测试之前先将其击中


例如:

from pycontractions import Contractions

PYCNTRCTNS = Contractions(api_key="glove-twitter-100")

# dummy call to force vector/grammar loading
PYCNTRCTNS.expand_texts([])  # expect this to take a while

def cont_expand(a):
    expText = PYCNTRCTNS.expand_texts(a, precise=False)
    return expText

mystr = ["I'd like to have lunch today"]
x = list(cont_expand(mystr))  # care about how long this takes


除此之外,您的用法非常简单,通过以不同的方式调用该库来加快处理速度,我看不到您可以做的其他事情。

但是,稍微研究一下pycontractions的工作原理,它的速度相当慢,尤其是在大型文本上,我不会感到惊讶。它在内部执行的操作通常是相当缓慢的过程,并且它以未进行严重优化的方式来执行它们-对于代码的简化,尤其是在短文本上,这可能是完美的,除非/直到更高的性能是必需的。

例如,它描述了使用“三遍”方法。


第一遍涉及许多基于模式的替换,为此,源代码具有数百个单独的正则表达式。每个文本都需要在循环中跨这数百个表达式进行正则表达式匹配,以执行第一步。 (有多种方法可以优化此方法以减少使用次数。)
对于具有多个可能扩展的收缩(包括测试字符串中的“ I”),它将执行每个扩展并检查其语法。幸运的是,这仅涉及一些扩展,但是语法检查也不是最便宜的操作。
对于每个替代扩展,它都会从原始文本计算出一个基于单词矢量的语义差异度量,即“单词移动器的距离”,它本身可能会非常昂贵,尤其是在较长的文本上。 (对于每个候选项,它都是从头开始执行的-即使除了几个单词,每个候选项都以相同的方式开始-即使找到至少一个语法选项,它也会继续为没有语法可能性的非语法候选者进行此计算选择)。


并且在每个步骤中,它都将临时结果作为原始字符串保留,因此pycontractions代码或各个支持库的代码将重复执行相同的标记化步骤。

因此:如果您批量进行此操作,并且对基础库进行了修补,那么可能存在很大的微优化空间。

但是我认为,对于许多临时用途,只要确保您不必重复支付每次操作的Contractions初始化加载成本就可以改善。

关于python - 加快pycontractions?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58429876/

10-08 22:10