助力 Python 老司机都开火箭了!Cython 实现百倍加速 NLP (助力油和液压油一样吗)

文章编号:41195 资讯动态 2024-12-03 加速 Cython Python NLP

老司机都开火箭了!<a href=C++ython 助力 Python NLP 实现百倍加速" src="https://www.gpxz.com/zdmsl_image/article/20241203204528_93505.jpg" loading="lazy">

SpaceX 猎鹰重型发射器,版权归

在去年我们发布了用 Python 实现的 基于神经网络的相互引用解析包(Neural coreference reSolution package) 之后,在社区中获得了惊人数量的反馈,许多人开始将该解析包用到各种各样的应用中,有一些应用场景甚至已经超出了我们原本设计的对话框用例(Dialog use-case)。

后来我们发现,虽然这个解析包对于对话框消息而言,解析速度完全够用,但如果要解析更大篇幅的文章就显得太慢了。

因此我决定要深入探索解决方案,并最终开发出了 NeuralCoref v3.0 。这个版本比之前(每秒解析几千字)的要快出百倍,同时还保证了相同的准确性,当然,它依然易于使用,也符合 Python 库的生态环境。

在本篇文章中,我想向大家分享我在开发 NeuralCoref v3.0 过程中学到的一些经验,尤其将涉及:

我的标题其实有点作弊,因为我实际上要谈论的是 Python,同时也要介绍一些 Cython 的特性。不过你知道吗?Cython 属于 Python 的超集,所以不要让它吓跑了!

以下给出了一些可能需要采用这种加速策略的场景:

百倍加速第一步:代码剖析

老司机都开火箭了!Cython 助力 Python NLP 实现百倍加速

你需要知道的第一件事情是,你的大部分代码在纯 Python 环境下可能都运行良好,但是其中存在一些瓶颈函数(Bottlenecks functions),一旦你能给予它们更多的「关照」,你的程序将获得几个数量级的提速。

所以你应该从剖析自己的 Python 代码开始,找出那些低效模块。其中一种方法就是使用:

你很可能会发现低效的原因是因为一些循环控制,或者你使用神经网络时引入了过多的 Numpy 数组操作(我不会花费时间在这里介绍 Numpy,这个问题已经有 太多文章 进行了讨论)。

那么我们该如何来加速循环呢?

在 Pyhthon 中加入 Cython 加速循环计算

老司机都开火箭了!Cython 助力 Python NLP 实现百倍加速

让我们通过一个简单的例子来解决这个问题。假设有一堆矩形,我们将它们存储成一个由 Python 对象(例如对象实例)构成的列表。我们的模块的主要功能是对该列表进行迭代运算,从而统计出有多少个矩形的面积是大于所设定阈值的。

我们的 Python 模块非常简单:

其中 check_rectangles 函数就是我们程序的瓶颈!它对一个很长的 Python 对象列表进行迭代,而这一过程会相当缓慢,因为 Python 解释器在每次迭代中都需要做很多工作(查找类中的方法、参数的打包和解包、调用 Python API 等等)。

Cython 语言是 Python 的一个超集,它包含有两种类型的对象:

定义这种循环最直接的一种方法就是,定义一个包含有计算过程中我们所需要用到的所有对象的结构体。具体而言,在本例中就是矩形的长度和宽度。

然后我们可以将矩形对象列表存储到 C 的结构数组中,再将数组传递给 check_rectangles 函数。这个函数现在将接收一个 C 数组作为输入,此外我们还使用关键字取代了(注意:也可以用于定义 Cython C 对象)将函数定义为一个 Cython 函数。

这里是 Cython 版本的模块程序:

这里我们使用了原生的 C 数组指针,不过你还有其它选择,特别是 C++ 中诸如向量、二元组、队列这样的结构体 。在这段程序中,我还使用了一个来自提供的内存管理对象,它可以避免手动释放所申请的 C 数组内存空间。当不再需要使用 Pool 中的对象时,它将自动释放该对象所占用的内存空间。

有很多办法来测试、编译和发布 Cython 代码。Cython 甚至可以像 Python 一样 直接用于 Jupyter Notebook 中。

通过 pip install cython 命令安装 Cython。

老司机都开火箭了!Cython 助力 Python NLP 实现百倍加速

使用 %load_ext Cython 指令在 Jupyter notebook 中加载 Cython 扩展。

然后通过指令,我们就可以像 Python 一样在 Jupyter notebook 中使用 Cython。

如果在执行 Cython 代码的时候遇到了编译错误,请检查 Jupyter 终端的完整输出信息。

大多数情况下可能都是因为在之后遗漏了标签(比如当你使用 spaCy Cython 接口时)。如果编译器报出了关于 Numpy 的错误,那就是遗漏了 import numpy

正如我在一开始就提到的,请好好阅读 这份 Jupyter notebook 和这篇文章,它包含了我们在 Jupyter 中讨论到的所有示例。

Cython 代码的文件后缀是,这些文件将被 Cython 编译器编译成 C 或 C++ 文件,再进一步地被 C 编译器编译成字节码文件。最终 Python 解释器将能够调用这些字节码文件。

你也可以使用将一个 .pyx 文件直接加载到 Python 程序中:

你也可以将自己的 Cython 代码作为 Python 包构建,然后像正常的 Python 包一样将其导入或者发布,更多细节请参考 这里 。不过这种做法需要花费更多的时间,特别是你需要让 Cython 包能够在所有的平台上运行。如果你需要一个参考样例,不妨看看 spaCy 的安装脚本 。

在我们开始优化自然语言处理任务之前,还是先快速介绍一下、和这三个关键字。它们是你开始学会使用 Cython 之前需要掌握的最主要的知识。

你可以在 Cython 程序中使用三种类型的函数:

关键字的另一个用途就是,在代码中表明某一个对象是 Cython C/C++ 对象。所以除非你在代码中使用声明对象,否则这些对象都会被解释器当做 Python 对象(这会导致访问速度变慢)。

使用 Cython 和 spaCy 加速自然语言处理

这一切看起来都很好,但是......我们到现在都还没开始涉及优化自然语言处理任务!没有字符串操作,没有 unicode 编码,也没有我们在自然语言处理中所使用的妙招。

此外 Cython 的官方文档甚至 建议不要使用 C 语言类型的字符串:

那么当我们在操作字符串时,要如何在 Cython 中设计一个更加高效的循环呢?

spaCy 处理该问题的做法就非常地明智。

将所有的字符串转换为 64 位哈希码

spaCy 中所有的 unicode 字符串(一个标记的文本、它的小写形式文本、它的引理形式、POS 标记标签、解析树依赖标签、命名实体标签等等)都被存储在一个称为 StringStore 的数据结构中,它通过一个 64 位哈希码 进行索引,例如 C 类型的。

老司机都开火箭了!Cython 助力 Python NLP 实现百倍加速

StringStore 对象实现了 Python unicode 字符串与 64 位哈希码之前的查找映射。

它可以从 spaCy 的任何地方和任意对象进行访问,例如 npl.vocab.strings doc.vocab.strings 或者 span.doc.vocab.string

当某一个模块需要在某些标记(tokens)上获得更快的处理速度时,你可以使用 C 语言类型的 64 位哈希码代替字符串来实现。调用 StringStore 查找表将返回与该哈希码相关联的 Python unicode 字符串。

但是 spaCy 能做的可不仅仅只有这些,它还允许我们访问文档和词汇表完全填充的 C 语言类型结构,我们可以在 Cython 循环中使用这些结构,而不必去构建自己的结构。

与 spaCy 文档有关的主要数据结构是 Doc 对象,该对象拥有经过处理的字符串的标记序列(“words”)以及 C 语言类型对象中的所有标注,称为,它是一个 TokenC 的结构数组。

TokenC 结构包含了我们需要的关于每个标记的所有信息。这种信息被存储成 64 位哈希码,它可以与我们刚刚所见到的 unicode 字符串进行重新关联。

如果想要准确地了解这些漂亮的 C 结构中的内容,可以查看新建的 spaCy 的 Cython API 文档 。

接下来看一个简单的自然语言处理的例子。

假设现在有一个文本文档的数据集需要分析。

我写了一个脚本用于创建一个包含有 10 份文档的列表,每份文档都大概含有 17 万个单词,采用 spaCy 进行分析。当然我们也可以对 17 万份文档(每份文档包含 10 个单词)进行分析,但是这样做会导致创建的过程非常慢,所以我们还是选择了 10 份文档。

我们想要在这个数据集上展开某些自然语言处理任务。例如,我们可以统计数据集中单词「run」作为名词出现的次数(例如,被 spaCy 标记为「NN」词性标签)。

采用 Python 循环来实现上述分析过程非常简单和直观:

但是这个版本的代码运行起来非常慢!这段代码在我的笔记本上需要运行 1.4 秒才能获得答案。如果我们的数据集中包含有数以百万计的文档,为了获得答案,我们也许需要花费超过一天的时间。

我们也许能够采用多线程来实现加速,但是在 Python 中这种做法并不是那么明智 ,因为你还需要处理 全局解释器锁(GIL) 。另外请注意,Cython 也可以 使用多线程 !Cython 在后台可以直接调用 OpenMP。不过我没有时间在这里讨论并行性,所以请查看 此链接 以了解更多详情。

现在让我们尝试使用 spaCy 和 Cython 来加速 Python 代码。

首先需要考虑好数据结构,我们需要一个 C 类型的数组来存储数据,需要指针来指向每个文档的 TokenC 数组。我们还需要将测试字符(「run」和「NN」)转成 64 位哈希码。

当所有需要处理的数据都变成了 C 类型对象,我们就可以以纯 C 语言的速度对数据集进行迭代。

这里展示了这个例子被转换成 Cython 和 spaCy 的实现:

代码有点长,因为我们必须在调用 Cython 函数之前在 main_nlp_fast 中声明和填充 C 结构。

这串代码虽然变长了,但是运行效率却更高!在我的 Jupyter notebook上,这串 Cython 代码只运行了大概 20 毫秒,比之前的纯 Python 循环快了大概 80 倍。

使用 Jupyter notebook 单元编写模块的速度很可观,它可以与其它 Python 模块和函数自然地连接:在 20 毫秒内扫描大约 170 万个单词,这意味着我们每秒能够处理高达 8 千万个单词。

对使用 Cython 进行自然语言处理加速的介绍到此为止,希望大家能喜欢它。

关于 Cython 还有很多其它的东西可以介绍,但是已经超出了这篇文章的初衷(这篇文章只是作为简介)。从现在开始,最好的资料也许是这份综述性的 Cython 教程 和介绍 spaCy 自然语言处理的 Cython 页面 。

如果你还想要获得更多类似的内容,请记得给我们点赞哟!

Via 100 Times Faster Natural Language Processing in Python ,雷锋网 AI 研习社编译整理

版权文章,未经授权禁止转载。详情见 转载须知 。

老司机都开火箭了!Cython 助力 Python NLP 实现百倍加速


本文地址: https://www.gpxz.com/article/f016106ea005723ef0f8.html
全局中部横幅
全局中部横幅
健康网站导航大全

LOL网址导航网是专业的上网导航网站,精心收录各类优质热门网站信息,同时提供天气、快递、违章等各种生活便民查询工具网址,为您提供安全便捷的上网导航服务,现已被众多网友设为上网主页,网址导航大全首选LOL网址导航.

米保险

米保险是专业的第三方保险咨询服务平台,提供各类保险险种产品测评、购买保险咨询、以及各类保险知识科普等保险服务;帮助保险人科学购买适合被保人的保险产品,避开保险里的坑。

2144游戏

2144游戏是专业的游戏平台,免费为你提供各种精品小游戏,好玩的网页游戏,手机游戏,同时还提供精品游戏专题,游戏攻略,人气论坛等,玩小游戏,网页游戏,手机游戏就上2144游戏网2144.cn

八百方网上药店

网上药店哪个好?八百方网上药店-全国网上买药的正规网站,网上药店提供覆盖中西药品、营养保健、医疗器械、医疗辅料等品类范围的销售服务,八百方网上药店是您网上购买药品正规合法药房网,并有专业的药师免费为你用药指导。

网页游戏平台

特玩网页游戏是中国一家专注与游戏行业数十年的网页游戏平台,页游运营平台,势力为广大玩家提供最好玩游戏最齐全的网页游戏,手游平台,最新网页游戏,手游游戏,开服表,排行榜等等。致力打造并提供国内最优质的客户服务,打造《页游.手游》绿色游戏成为全球深受玩家喜爱的网页游戏以及手游平台,玩游戏就来Www.tewan.com

奇绩高考智库

奇绩高考智库——探索教育奇迹,启迪智慧人生,高考路上的智能伙伴。

迪信通官网

迪信通DIXINTONG.COM-手机、智能穿戴、数码类网购首选020平台,提供三星,苹果,华为,魅族,oppo,vivo,小米,中兴,酷派,摩托罗拉等各品牌手机,保证正品行货,支持分期付款.20年专业手机连锁品质保证,全国联保,急速送达,货到付款.迪信通O2O平台与全国3000家门店竭诚为您提供更好的购物体验.

密度计

中山市三易测量仪器有限公司,2009年02月16日成立,经营范围包括生产、销售:仪器、仪表、五金配件等。扎根于在线密度计、浓度计、压力变送器、流量计、液位计、温度等过程控制仪表的研发和生产制造。在线浓、密度检测具有长期深入的研究及现场应用经验。

深孔机床

德州冠鲁【电话15166987816】是一家专业从事深孔钻床、深孔机床、深孔镗床、深孔钻镗床、枪钻机床、深孔珩磨机床、数控深孔机床设备企业;公司成立以来,根据国内外市场最新需求,设计制造各种专业深孔机床;是口碑好优质可靠的源头厂家;价格合理,交货及时;服务范围覆盖:山东/北京/河北/天津/河南/上海陕西/山西/江苏/浙江/成都/杭州/武汉/重庆/南京/天津/苏州/西安/长沙/沈阳/青岛/郑州/大连/东莞/宁波/济南/青岛/石家庄等全国各大省市及地区。深孔机床哪家好,首选德州冠鲁。深孔机床代理费用报价需要多少钱?哪里有?欢迎拨打咨询电话,联系方式:山东省德州市平原县三唐乡京津鲁冀产业园

爱加速

爱加速App是一款专业的网络加速软件,提供高质量的静态网络接入服务,全平台支持。爱加速让网络安全与速度尽在掌握。

货运物流网

货运物流网-货运物流官网:提供到全国空车配货、货运找车、货物运输、大件运输、冷藏货运、长途搬家、货运公司、物流公司、货运信息部、货运物流推广咨询服务。


全局底部横幅