Cython 是一个工具包,可以使你在 Python 中编译 C 语言,这就是为什么 numpy 和 pandas 很快的原因,Cython 就是 Python 的超集。在本文中,作者将为我们介绍他的 GitHub 项目 NeuralCoref v3.0,详解如何利用 spaCy 和 Cython 以约 100 倍于 Python 的速度实现 NLP 项目。
相关 Jupyter Notebook 地址: https://github.com/huggingface/100-times-faster-nlp
尽管对话信息的处理速度非常好,但对于长的新闻文章来说,处理速度可能会非常慢。我决定详细研究这一问题,最终成果即 NeuralCoref v3.0,它在相同准确率的情况下比老版本快 100 倍左右(每秒几千字),同时兼顾 Python 库的易用性和兼容性。
NeuralCoref v3.0 :https://github.com/huggingface/neuralcoref/
我想在这篇文章中分享一些关于这个项目的经验,特别是:
- 如何用 Python 设计一个高速模块;
- 如何利用 spaCy 的内部数据结构来有效地设计超高速 NLP 函数。
所以我在这里有点作弊,因为我们会谈论 Python,但也谈论一些 Cython 的神奇作用。但是,你知道吗?Cython 是 Python 的超集,所以不要让它吓跑你!
你现在的 Python 程序已经是 Cython 程序。
有几种情况下你可能需要加速,例如:
- 你正在使用 Python 开发一个 NLP 的生产模块;
- 你正在使用 Python 计算分析大型 NLP 数据集;
- 你正在为深度学习框架,如 PyTorch / TensorFlow,预处理大型训练集,或者你的深度学习批处理加载器中的处理逻辑过于繁重,这会降低训练速度。
再强调一遍:我同步发布了一个 Jupyter Notebook,其中包含我在本文中讨论的例子。试试看!
Jupyter Notebook:https://github.com/huggingface/100-times-faster-nlp
加速第一步:剖析
首先要知道的是,你的大多数代码在纯 Python 环境中可能运行的不错,但是如果你多用点心,其中一些瓶颈函数可能让你的代码快上几个数量级。
因此,你首先应该分析你的 Python 代码并找出瓶颈部分的位置。使用如下的 cProfile 是一种选择:
import cProfile import pstats import myslowmodule cProfile.run( myslowmodule.run() , restats ) p = pstats.Stats( restats ) p.sortstats( cumulative ).printstats(30)
如果你使用神经网络,你可能会发现瓶颈部分是几个循环,并且涉及 Numpy 数组操作。
那么,我们如何加速这些循环代码?
在 Python 中使用一些 Cython 加速循环
让我们用一个简单的例子来分析这个问题。假设我们有一大堆矩形,并将它们存储进一个 Python 对象列表,例如 Rectangle 类的实例。我们的模块的主要工作是迭代这个列表,以便计算有多少矩形的面积大于特定的阈值。
我们的 Python 模块非常简单,如下所示:
from random import random class Rectangle: def __init__(self, w, h): self.w = w self.h = h def area(self): return self.w * self.h def che