乐趣区

关于深度学习:初窥Ray框架

本文首发于:行者 AI

随着各行各业数字化的一直推动,AI 须要解决的数据越来越多,繁多服务器曾经难以满足以后产业的倒退需要,服务器集群成为企业用 AI 解决数据的标配硬件,而分布式计算成为人工智能利用的标配软件。

从图 1 能够看出,现今有很多开源的分布式计算框架,从模型的训练、调参到部署;从 NLP、CV 到 RS;这些框架笼罩到了 AI 产业生命周期的各个方面。本文就选取其中的 Ray 框架进行简略的介绍。

图 1. 各种分布式计算框架

Ray 是伯克利大学在 2017 年开源的 分布式计算框架,对应的论文是《Ray: A Distributed Framework for Emerging AI Applications》。强化学习工作须要与环境进行大量的交互(毫秒级),且在工夫上反对异构性。该框架专门为机器学习与强化学习设计,相较于其余框架,ray 具备以下劣势:

  • 轻量级
  • 可疾速构建
  • 通用性强
  • 性能优异

上面就这四个长处为大家进行具体介绍。

1. Ray 框架的劣势

1.1 轻量级

相较于传统的分布式框架(尤其是 hadoop、spark 等),Ray 能够间接通过 pip 进行装置,且对系统版本无要求。

pip install -U ray

Ray 是一个简略的分布式策略,而非残缺的生态,因此不须要简单的构建。

另一方面,轻量而优良的框架往往能够作为企业数据处理的根底框架,企业一直在该框架的根底上减少生态,从而造成企业独有的利用生态。

1.2 可疾速构建

如 hadoop 等传统框架,要对原有的单机程序进行分布式化,须要批改整个代码逻辑,以 MapReduce 的编程计划重构各个计算模块,这使得 hadoop 等传统框架有着良好的可编辑性,算法工程师能够依据业务需要进行具体的批改。弱小的可编辑性也带来了学习老本高,代码重构艰难等诸多问题。人工智能突飞猛进,模型在一直更迭,麻利开发成为了很多 AI 企业的开发模式,AI 利用的简单构建会大大影响整个我的项目的推动。

如下代码,将一个简略的单机程序函数,转换为 Ray 分布式的函数,只是在原有函数的根底上退出了 ray.remote 的装璜器,便实现了分布式化的工作。

### 原始单机代码
def f(x):
    return x * x

futures = [f.remote(i) for i in range(4)]
print(ray.get(futures))

### Ray 分布式代码
import ray
ray.init()
@ray.remote
def f(x):
    return x * x

futures = [f.remote(i) for i in range(4)]
print(ray.get(futures))

1.3 通用性强

近年 tensorflow、torch 等深度学习框架成为人工智能利用的模型框架,思考到产业利用场景,这些框架都给出了各自分布式训练和部署的计划,且这些计划的计算资源利用率较高。大型的我的项目往往由数个算法模型组成,为了疾速开发,算法工程师往往采纳开源的代码构建,而这些开源的代码采纳的深度学习框架很可能互不雷同,针对繁多框架的分布式计划难以实用。

除此之外,ONNIX 等为代表的框架,偏向于将所有框架的模型对立到繁多的解决方案上,因为很多前沿的深度学习模型对神经元进行了简单的批改,无奈适配到通用的算子上,须要算法工程师手写算子,从而拖慢了开发速度。Ray 将机器学习模型、numpy 数据计算、繁多的函数形象成通用的计算,实现了对各种深度学习框架、机器学习框架的适配。

另外,Ray 对强化学习的利用进行了专门的生态构建。

1.4 性能优异

图 2 为 Ray、Horovod 以及 tensorflow 原生的分布式计划训练 ResNet-101 模型的比拟,纵轴为每秒均匀迭代的图片数,能够看出 Ray 稍微优于 Horovod 框架。

图 2. 分布式训练速度比拟

图 3 为 Clipper 和 Ray 在模型调用上吞吐量的比拟,两者均用同一网络模型,能够看出 Ray 优于 Clipper。

图 3. 分布式部署吞吐量比拟

Ray 并没有做到每个分布式场景都优于其余框架,但 Ray 汇合训练、调参以及部署为一体,仍能放弃不错的性能,因此值得学习和应用。

得益于 Ray 框架良好的性能,Ray 宽泛用于工业界(如蚂蚁金服),要先学会应用 Ray 必先理解 Ray 的形成,下一大节就 Ray 的形成进行介绍。

2. Ray 的应用

2.1 Ray 的形成

Ray 大抵由四局部组成:

  • Tune: 超参数调整模块
  • RLlib: 强化学习模块
  • RaySGD: 分布式训练模块
  • Ray Serve: 应用服务部署模块

Ray 波及了 AI 利用的整个生命周期:训练、调参、部署,并对强化学习场景进行了专门的优化。因为集体应用教训无限,这里只介绍 Ray 的 Serve 模块。

2.2 Ray 的启动

如图 4,Ray 由一个 头节点 (Head node)和一组 工作节点(Worker node)组成。启动 Ray 须要首先启动头节点,并为工作节点提供头节点的地址以造成集群。头节点负责管理和调配工作节点的工作,工作节点负责执行工作并返回后果。通过测试,头节点和工作节点能够为同一台计算机。

Ray 的启动由两个步骤组成:启动头节点、注册工作节点到头节点。

图 4. Ray 节点示意图

以下是头节点的启动代码和敞开代码。

import ray
ray.init()  # 启动
assert ray.is_initialized() == True

ray.shutdown()  # 敞开
assert ray.is_initialized() == False

注:启动脚本该当退出敞开代码,如果没有,ray 程序可能始终在过程中运行。

Ray 框架采纳 Actor 模型,相较于传统的共享内存模型,Ray 不存在状态竞争、能够不便的组建集群、能更好的管制状态。每个 Actor 即每个工作节点的注册形式如下。

import ray
ray.init(address= 头节点地址)  # 启动
assert ray.is_initialized() == True

ray.shutdown()  # 敞开
assert ray.is_initialized() == False

2.3 Ray Serve

Ray Serve 能够类比 clipper,次要用于模型的部署服务,并反对多种深度学习框架,官网给出的示例有:

  • Keras and Tensorflow Tutorial
  • PyTorch Tutorial
  • Scikit-Learn Tutorial

这里以 tensorflow2 为例,来说一下如何用 ray 来部署模型服务。

步骤一:定义一个模型服务类

如下是模型服务类的繁难代码,和 Flask 等框架部署 AI 服务相似。因为 Ray 应用 gRPC 作为通信协议,速度更快,Ray 还在 gRPC 根底上进行了优化,有些场景快于原生的 gRPC 通信。

class TFMnistModel:
    def __init__(self, model_path):
        import tensorflow as tf
        self.model_path = model_path
        # 加载模型
        self.model = tf.keras.models.load_model(model_path)

    async def __call__(self, starlette_request):  # 异步调用
        # transform HTTP request -> tensorflow input
        input_array = np.array((await starlette_request.json())["array"])
        reshaped_array = input_array.reshape((1, 28, 28))

        #  tensorflow input -> tensorflow output
        prediction = self.model(reshaped_array)

        # 返回后果
        #  tensorflow output -> web output  
        return {"prediction": prediction.numpy().tolist(),
            "file": self.model_path
        }

步骤二:模型部署到 Ray Serve

如下代码中,start 函数用于启动服务,create_backend 函数用于启动模型,create_endpoint 函数启动服务。在 Ray 中,模型和服务是拆散的,能够多个服务调用同一个模型,以反对简单的调用逻辑。

“tf:v1″ 为模型的名称,”tf_classifier” 为服务的名称,route 参数为路由,这些参数都可自在定义。

client = serve.start()
client.create_backend("tf:v1", TFMnistModel, TRAINED_MODEL_PATH)
client.create_endpoint("tf_classifier", backend="tf:v1", route="/mnist")

步骤三:申请测试

resp = requests.get(
    "http://localhost:8000/mnist",
    json={"array": np.random.randn(28 * 28).tolist()})
print(resp.json())

3. 结语

一个优良的框架往往蕴含了泛滥先进的设计理念。Ray 框架在构建时,参考了许多先进的设计理念,如混合调度策略、GCS 治理等等,这些设计理念使得框架自身欠缺而又先进。Ray 宽泛用于 AI 企业的分布式计算场景,从泛滥框架中怀才不遇,值得学习。

退出移动版