作者|ThomasWolf译者|王强来自|AI前线AI前线导读:去年我们发布了基于Python的共指解析包之后,社区反馈非常热烈,大家开始在各式应用中使用它,有些应用场景与我们原来的对话用例非常不一样。之后我们发现,虽然这个解析包的性能对于对话消息来说是足够的,但涉及到大篇幅新闻文章时就远远不够了。
让我们通过一个简单的例子来解决这个问题。假设有一堆矩形,我们将它们存储成一个由Python对象(例如Rectangle类实例)构成的列表。我们的模块的主要功能是对该列表进行迭代运算,从而统计出有多少个矩形的面积是大于所设定阈值的。我们的Python模块非常简单,看起来像这样:
这个check_rectangles函数就是我们的瓶颈所在!它对大量Python对象进行循环检查,而因为Python解释器在每次迭代中都要做很多工作(比如在类中查找area方法、打包和解包参数、调用PythonAPI等),这个循环就会非常影响性能。这时就该引入Cython来帮助我们加速循环了。
这里我们使用了C指针的原始数组,但你也可以选择其它方案,特别是诸如向量、二元组、队列之类的C++结构(http://cython.readthedocs.io/en/latest/src/userguide/wrapping_CPlusPlus.html#standard-library)。
StringStore对象实现了Pythonunicode字符串与64位哈希值之间的映射。我们可以从spaCy的任意位置和任意对象访问它,例如npl.vocab.strings、doc.vocab.strings或span.doc.vocab.string。当一个模块需要在某些节点上获得更高的性能时,只要使用C类型的64位哈希值代替字符串即可。
我写了一个脚本,创建一个包含10个文档(经过spaCy处理)的列表,每个文档有大约17万个单词。当然,我们也可以做17万个文档(每个文档包含10个单词),但是创建这么多文档会很慢,所以我们还是选择10个文档。我们想要在这个数据集上执行一些NLP任务。例如,我们想要统计数据集中单词“run”作为名词出现的次数(也就是被spaCy标记为“NN”)。
但它也非常慢!这段代码在我的笔记本上需要运行1.4秒才能获得结果。如果我们的数据集中包含数以百万计的文档,我们也许要花费一天以上才能看到结果。我们可以使用多线程来提速,但在Python中这往往不是最佳方案(https://youtu.be/yJR3qCUB27I?
代码有点长,因为我们必须在调用Cython函数[*](https://medium.com/huggingface/100-times-faster-natural-language-processing-in-python-ee32033bdced#a220)之前在main_nlp_fast中声明和计算C结构。但它的性能得到大幅提升!
领取专属 10元无门槛券
私享最新 技术干货