跳到主要内容

快速上手

这里以 PyTorch ResNet50 为例,介绍一下模型部署的流程。所有的代码可以在 openbayes-serving-examples/pytorch/image-classifier-resnet50/ 获取。

准备模型

import torch
from torchvision import models

# 加载预训练模型
model = models.resnet50(pretrained=True)

# 保存到本地
torch.save(model.state_dict(), "resnet50.pt")

编写模型部署脚本 predict.py

predictor.py 文件需要包含一个名为 Predictor 的类,其结构如下:

import openbayes_serving as serv


class Predictor:
def __init__(self):
"""
负责加载相应的模型以及对元数据的初始化
"""
...

def predict(self, json):
"""
接受 HTTP 请求的内容,进行必要的处理后预测结果,最终将结果返回给调用方
"""
...


if __name__ == '__main__':
serv.run(Predictor)

具体的参数和介绍可以在 Serving Predictor 找到。

而对于 PyTorch ResNet50 其 predictor.py 的内容如下所示:

import torch
import cv2
import numpy as np
import json
import requests
from torchvision import models, transforms

import openbayes_serving as serv


def get_url_image(url_image):
resp = requests.get(url_image, stream=True).raw
image = np.asarray(bytearray(resp.read()), dtype="uint8")
image = cv2.imdecode(image, cv2.IMREAD_COLOR)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
return image


class Predictor:
def __init__(self):
# 加载分类元数据
classes = json.load(open('classes.json'))
self.idx2label = [classes[str(k)][1] for k in range(len(classes))]

# 指定模型文件名称
model_name = 'resnet50.pt'

# 加载模型
self.device = "cuda" if torch.cuda.is_available() else "cpu"
self.model = models.resnet50()
self.model.load_state_dict(torch.load(model_name))
self.model.eval()
self.model = self.model.to(self.device)

# 图像预处理,包括 normalization 和 resize
normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
self.transform = transforms.Compose(
[
transforms.ToPILImage(),
transforms.Resize([224, 224]),
transforms.ToTensor(),
normalize,
]
)

def predict(self, json):
# 从 json.url 获取图片的 url,即要求传递的 HTTP 请求内容为 {"url": "xxx"}
imageurl = json["url"]
# 获取图片内容
image = get_url_image(imageurl)
# 图片预处理
image = self.transform(image)
image = torch.tensor(image.numpy()[np.newaxis, ...])

# 推理
results = self.model(image.to(self.device))

# 获取结果前五
top5_idx = results[0].sort()[1][-5:]

# 获取前五分类的名称
top5_labels = [self.idx2label[idx] for idx in top5_idx]
top5_labels = top5_labels[::-1]

return top5_labels


if __name__ == '__main__':
serv.run(Predictor)

上传到数据仓库

将已经准备好的 .pt 文件与 predictor.py 文件以及其他需要的文件放置于同一个目录下,目录中必须包含的文件如下所示:

.
├── classes.json
├── predictor.py
└── resnet50.pt

其中

  • resnet50.pt 为模型文件。
  • predictor.py 目前 OpenBayes 模型部署要求其文件名称固定为 predictor.py 使用其他的文件名将会导致部署失败。
  • classes.json 包含 resnet 分类的元数据,在展示分类的名称时使用。

创建一个模型仓库:

将以上三个文件上传:

查看上传结果:

创建 Serving

左侧导航栏「算力容器」->「模型部署」创建一个新的 Serving:

绑定模型目录,选择刚才上传的模型版本目录:

点击部署等待部署标记为「运行中」:

点击当前最新的部署版本(也是目前唯一的部署版本)查看日志:

测试

在模型展示为「运行中」后可以看到「概览」页面展示了当前部署的 http 访问地址。

通过 curl 工具可以对该当前部署的服务进行测试:

curl -X POST \
<服务地址> \
-H "Content-Type: application/json" \
--data-raw '{ "url": "http://openbayes-public.cn-bj.ufileos.com/cat.jpg" }'

「模型部署」默认使用的请求为 JSON 格式,其中 url 字段与我们上文 predictor.pyjson 中获取的 url 相对应。

可以获得相应的结果:

["tabby", "Egyptian_cat", "tiger_cat", "lynx", "tiger"]