快速上手
这里以 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.py
在 json
中获取的 url
相对应。
可以获得相应的结果:
["tabby", "Egyptian_cat", "tiger_cat", "lynx", "tiger"]