#python #rest #machine-learning #deployment #fastapi
#python #rest #машинное обучение #развертывание #fastapi
Вопрос:
Я новичок в разработке Rest API и пытаюсь развернуть модель машинного обучения для сегментации изображений с использованием Python и Rest API.
На стороне сервера я использую FastAPI, а на стороне клиента я использую библиотеку запросов Python. Клиент уже изменяет размер изображения до необходимого входного размера модели и, следовательно, не отправляет излишне большие изображения. Сервер передает полученное изображение в модель и возвращает двоичную маску сегментации. Изображение и маска преобразуются из массивов numpy в списки, которые затем отправляются в виде данных json.
Ниже приведен некоторый код, представляющий то, что я только что описал. Поскольку я не могу предоставить здесь модель, сервер в этом минимально воспроизводимом примере просто вернет то же изображение, которое он получил.
server.py
import uvicorn
from fastapi import FastAPI
import numpy as np
from datetime import datetime
app = FastAPI()
@app.get('/test')
def predict_and_process(data: dict = None):
start = datetime.now()
if data:
image = np.asarray(data['image'])
print("Time to run: ", datetime.now() - start)
return {'prediction': np.squeeze(image).tolist()}
else:
return {'msg': "Model or data not available"}
def run():
PORT = 27010
uvicorn.run(
app,
host="127.0.0.1",
port=PORT,
)
if __name__=='__main__':
run()
client.py
import requests
import numpy as np
import json
from matplotlib.pyplot import imread
from skimage.transform import resize
from datetime import datetime
def test_speed():
path_to_img = r"path_to_some_image"
image = imread(path_to_img)
image = resize(image, (1024, 1024))
img_list = image.tolist()
data = {'image': img_list}
start = datetime.now()
respond = requests.get('http://127.0.0.1:27010/test', json=data)
prediction = respond.json()['prediction']
print("time for prediction: {}".format(datetime.now()-start))
if __name__=='__main__':
test_speed()
Вывод с сервера выглядит следующим образом:
(cera) PS C:Usersuser_nameDesktopMRMREST> python .server.py
[32mINFO[0m: Started server process [[36m20448[0m]
[32mINFO[0m: Waiting for application startup.
[32mINFO[0m: Application startup complete.
[32mINFO[0m: Uvicorn running on [1mhttp://127.0.0.1:27010[0m (Press CTRL C to quit)
Time to run: 0:00:00.337099
[32mINFO[0m: 127.0.0.1:61631 - "[1mGET /test HTTP/1.1[0m" [32m200 OK[0m
и вывод от клиента:
(cera) PS C:Usersuser_nameDesktopMRMREST> python .client.py
time for prediction: 0:00:16.845123
Поскольку код, выполняемый на сервере, занимает меньше секунды, время, необходимое для передачи изображения с клиента на сервер (или обратно), составляет где-то около 8 секунд, что определенно слишком долго.
Я не могу отправлять изображения меньшего размера, так как входной размер модели должен оставаться неизменным.
Итак, для новичка в развертывании / REST: каким был бы профессиональный / передовой способ быстрее получать мои прогнозы из REST API? Я предполагаю, что есть ограничения, так как я использую python, но 16 секунд все еще кажутся мне слишком долгими.
Заранее благодарю вас!
Комментарии:
1. вы могли бы base64 кодировать ваше изображение при передаче его через REST
2. Это на самом деле решение! Я опубликую это в качестве ответа, если вы не возражаете, чтобы другие могли это увидеть 🙂
Ответ №1:
Как указал @slizb, кодирование изображения в base64 делает все намного быстрее. Вместо img_list = img.to_list()
того, чтобы использовать
data = {'shape': image.shape, 'img': base64.b64encode(image.tobytes())}
и на сервере
image = np.frombuffer(base64.b64decode(data.img)).reshape(data.shape)
Не забудьте также отправить форму, потому что numpy не собирается «запоминать» форму из буфера, поэтому мне нужно было вручную .reshape()
обработать изображение.
Общее время сократилось примерно до 1 секунды, что в основном составляет время вывода моей модели.
Ответ №2:
Я бы посоветовал ознакомиться с этой документацией и попробовать примеры, предоставленные для вашего маршрута загрузки изображений.
Комментарии:
1. Если я правильно понимаю, это может сработать для mrm, но на самом деле я не загружаю файлы с жесткого диска. Начальной точкой всегда будет numpy.ndarray …