Press "Enter" to skip to content

丧心病狂!最新NLP模型的写作水平已突破次元壁

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

 

图片来源:unsplash.com/@thoughtcatalog

 

本文将介绍一款基于OpenAI的新NLP文本编写APP——GPT-2,旨在随时随地和用户一起写作。

 

这是一款全新的创造性文本编辑器APP。 与传统文本编辑器不同,这款APP的NLP模型可以完成用户要求的句子,并为“用机器写作”带来全新的维度。 该APP基于GPT-2(OpenAI的语言模型),可以生成在语法意义上准确无误的句子和连贯的文字段落。

 

 

在GPT-2的帮助下讲故事

 

该演示现已在https://transformer.huggingface.co上发布。

 

用transformer写作就像用计算器写微积分。

 

这个模型是NLP最新趋势的一部分,在对特定任务进行微调时,该模型用于创建大型的语言模型,从而使各项任务圆满完成。这使得具有大量参数(GPT-2 Large或Grover的参数多达15亿个)的Transformer模型由于其重量而很难处理。

 

APP为用户提供两种型号:小型GPT-2和中型GPT-2。两种型号同时加载到计算机的RAM中共需2.4 GB内存。

 

当前存在的问题

 

注意:这里的方法针对无法执行批量推理的模型。对于可以进行批量推理的模型,如我们使用的模型,可能不需要显示的解决方法。

 

这个APP设置了一些限制,以便用户拥有愉悦的使用感。如反应时间要尽可能短,并生成足够长的句子。每次运行时,系统必须提供几种可能的结果,以便用户从中做出选择,这会使生成的数据量增加两倍之多。因此,该APP的目标是尽可能优化计算,利用GPU高度并行性的特点创建工作流程。

 

设置工作区

 

构建一个服务器端API,与前端APP连接。该API将负责处理生成句子所需的计算。因为大多数NLP模型都是现成的,所以使用Python来完成这项任务。其他低级语言(如C++或Rust)更适合以性能为导向的后端。

 

使用falcon(https://falconframework.org/)作为Web服务器(任何其他HTTP框架也可以使用),与gunicorn(https://gunicorn.org/)一起运行实例并平衡负载。GPT-2 Pytorch(https://github.com/huggingface/pytorch-pretrained-BERT)运行是该项目的支柱。如果你对类似的例子感兴趣,可参见示例目录(https://github.com/huggingface/pytorch-pretrained-BERT/tree/master/examples)中的一些示例。

 

Gunicorn可以设立独立运行APP的“workers”,有效平衡不同worker的负载。可以参见官方的Gunicorn文档(http://docs.gunicorn.org/en/stable/design.html),精确了解它们是如何工作的。

 

 

 

三种方式自动完成

 

在每次自动完成的请求中,我们都希望API可能生成三个不同的句子。这些句子将呈现给终端用户,最终用户将在三者中选择一个。这是设计的重要部分,API必须反映这一点。这三个句子应该同时出现,每次自动完成后,最好只向服务器发送一个请求。

 

最简单的方法是使用在后台加载模型的单个worker:

 

 

Naïve API

 

使用这种体系结构,每个请求都将按顺序处理,并且模型将被提示,在响应传入请求之前生成三个不同的句子。

 

可以通过添加更多工作人员来轻松扩展此基础架构,同时牢记:每个工作人员会根据GPU的使用情况在RAM或VRAM中加载模型。

 

 

Multi-worker naïve API

 

使用这种方法意味着加载模型并对其进行操作的过程,以请求生成三个不同的句子。如果模型能执行批量推理,就可以一次生成三个句子。但是,如果不能执行批量推理,则需要单独生成每个句子——从而导致三次模型迭代。因为批量推断需要一些更具设计性的方法,所以后面将考虑其无法进行的情况。

 

在计算自动完成的最短响应时间时,最好将这三个迭代并行化。幸运的是,Python使用户可以访问在场景中使用的几个并行化选项:

 

· 多线程(

 

· 多进程(子进程或多进程)

 

· 不同的Web服务器作为一种多处理形式

 

多线程

 

传送门:https://docs.python.org/3/library/threading.html

 

Python中的多线程通常使用线程类来完成,该线程允许程序创建多个线程,每个线程都会继续执行各自的操作。多线程的问题在于Global Interpreter Lock ( GIL ) 在Python中的工作方式。

 

如果一个线程访问某个模型对象,那幺在第一个线程完成处理之前,其他线程无法访问该对象。因为三个迭代将按顺序处理,所以这种方法类似于在执行过程中根本不使用任何线程。唯一的性能差异将是开始或者连接每个线程所花费的额外时间,不利于实现目标。

 

如果真的想要使用线程,可以将三个不同的模型加载到RAM中,每个单独的线程使用一个模型。但本文并没有选择那样做,下面将做出进一步解释。

 

多进程

 

多进程有两种方式:通过启动完全独立的进程并连接到它们的输入或输出(使用子进程模块)( https://docs.python.org/3/library/subprocess.html )或者生成可以继承当前Python解释器进程资源的python进程(使用多进程模块可绕过GIL问题)( https://docs.python.org/3.4/library/multiprocessing.html )。

 

这里,一个棘手的部分是如何确保模型不必每次计算推理时都加载到RAM中;大型模型需要很长时间才能加载到内存中。

 

可以选择采用另一种不同的方法。

 

使用gunicorn负载平衡

 

该方法的不同之处在于使用gunicorn worker的功能来平行工作。为此,在之前的模型中需添加另一个层。先前定义的体系结构可以接收多个请求,并在几个worker中同时处理这些请求。将此当作优势。最终模型如下。

 

 

最终有两个不同型号的Falcon或Gunicorn服务器

 

当请求从前端APP发送到API时,它将由第一个Web服务器处理。该Web服务器中会有一个运行API的工作程序。此API负责向第二个Web服务器发送三个相同的请求。API发送的请求包含当前上下文(文档中的前一个句子)以及一些有关参数信息(小型或中型模型,特定top_k值等等)。

 

第二个Web服务器中有多个worker分别处理请求。三个worker将同时分别处理从API收到的各个请求。在API中使用单独线程,以便将请求并行发送到第二个Web服务器而不是顺序发送(HTTP请求 – >没有GIL问题)。

 

此体系结构具有其他先前提到的方法所不具备的几个优势:

 

· 可以生成尽可能多的worker,只要模型的数量能适合人类记忆。如果有一个分布式系统,可以将worker分布到不同的GPU中。

 

· 每个worker在内存中加载一个模型。因此,与每次加载三个模型相比,可能会加载更多模型(更多的计算能力),例如线程方法。

 

· 作为Web服务器的worker,模型将始终保持在内存中。

 

· 架构中的每一步都使用了gunicorn的负载平衡。并不是要简单地产生并行运行进程,要想办法确保每个进程处理与其计算能力相关的负载。如果使用两个具有不同计算能力的GPU,而拥有较低计算能力的GPU所造成的瓶颈对另一个GPU的影响不会像在纯多进程程序中那样大。

 

图2显示了在初始化期间以及向API发送两个并发请求时,体系结构在内存管理方面的表现。

 

 

初始化和并发行为

 

 

 

结果

 

不出所料,与初始顺序系统相比,使用并行系统时,响应时间方面有了很大改进。对一个需要在三个模型迭代中分解的请求进行基准测试,只需三分之一的初始响应时间,实际的本地HTTP请求只需要几百微秒。

 

该系统特别适用于垂直扩展,因为它能适应系统的内存和计算能力。但是,它不能与可以执行批量推理的模型进行比较,因为这种方法将在内存中存储三个模型,而如果使用批量推理,则只能存储一个模型。

 

 

进一步改进

 

这个系统是为在机器上运行而设计的,所以没有考虑集装箱化或水平扩展。对于需要处理10万用户的完整生产系统而言,这广受欢迎,也必不可少。

 

另一项改进是使用TorchScript模块。由于在模型中使用了pytorch,所以可以看到它的torchscript版本,在任何编程语言中进行推理。因此,如果想得到最大限度优化,可以用一种非常低级的语言优化一个更好的、更合适的Web服务器。

 

这个系统已经证明其价值,因为它在4-GPU(K80)机器上运行时,一周之内处理了超过100,000个不同的请求。

Be First to Comment

发表评论

邮箱地址不会被公开。 必填项已用*标注