Falcon vs. Flask-選擇哪一個來創建可擴展的深度學習REST API

Falcon vs. Flask-選擇哪一個來創建可擴展的深度學習REST API

我們有時會提供速度至關重要的關鍵服務。例如,我們有數百萬張酒店圖片,我們需要對其進行“吸引力”評估。每次瀏覽每張圖片都非常耗時,如果操作不當可能會花費數週時間。因此,優化預測過程中的每個步驟(從模型大小到創建rest服務)至關重要。在本文中,我們希望分享我們的經驗,以及Falcon是否可以用作創建可擴展的機器學習rest API的可行替代方案。

Falcon是什麼?

Falcon就像Flask,一個用Python編寫的輕量級微框架,用於構建web api和應用程序後臺。與Flask不同,Falcon的主要關注點是REST api,因為它根本不適合提供HTML頁面。它有一個乾淨的設計,包含HTTP和REST架構風格。

Falcon的簡單代碼示例:

import falcon

class HelloResource:

def on_get(self, req, resp):

resp.status = falcon.HTTP_200

resp.body = 'Hello World!'

api = falcon.API()

api.add_route('/', HelloResource())

深度學習REST API

對於Flask來說,已經有很多關於它如何用於為機器學習模型創建預測服務的文章。對於Falcon,有關如何使用它來創建機器學習API的教程列表比Flask要少。儘管如此,無論是Flask還是Falcon,將機器學習模型作為API部署的理念仍然保持不變。通常,您訓練機器學習模型,然後將其保存(例如,在scikit中,您可以pickle您的模型)。然後,您將機器學習模型包含在具有一些數據預處理邏輯的rest API中。在我們的例子中,我們訓練了一個MNIST數據集上的簡單CNN,Keras和Tensorflow作為後端(https://github.com/keras-team/keras/blob/master/examples/mnist_cnn.py)。然後,我們將模型存儲到單個HDF5文件中,該文件包含模型的體系結構,模型的權重以及一些其他信息,如訓練配置,優化器狀態等。

之後,我們使用該模型來創建預測服務。這是Python代碼:

import base64

import json

import falcon

import numpy as np

from io import BytesIO

from PIL import Image, ImageOps

def convert_image(image):

img = Image.open(image).convert('L')

inverted_img = ImageOps.invert(img)

data = np.asarray(inverted_img, dtype='int32')

rescaled_data = (data / 255).reshape(1, 28, 28, 1)

return rescaled_data

class PredictResource(object):

def __init__(self, model):

self.model = model

def on_get(self, req, resp):

resp.status = falcon.HTTP_200

resp.body = 'Hello World!'

def on_post(self, req, resp):

"""

(echo -n '{"image": "'; four_test.png; echo '"}') |

curl -H "Content-Type: application/json" -d @- http://127.0.0.1:8000/predict

"""

image = json.loads(req.stream.read())

decoded_image = base64.b64decode(image.get('image'))

data = convert_image(BytesIO(decoded_image))

predicted_data = self.model.predict_classes(data)[0]

output = {'prediction': str(predicted_data)}

resp.status = falcon.HTTP_200

resp.body = json.dumps(output, ensure_ascii=False)

基本上,我們創建了一個端點,我們需要將包含在base64中解碼的圖像的json文件發佈到此端點,然後以可用於我們在Keras中訓練的模型的格式轉換圖像。輸出是預測。您已經可以看到,模型未在on_post函數中顯式啟動,因為我們不希望每次發出請求時都將模型重新加載到內存中。這是非常低效的。相反,我們resource通過將其作為參數傳遞,在Falcon之外啟動模型(資源只是API中可以通過URL訪問的所有內容)。

import os

import falcon

from keras.models import load_model

from .predict import PredictResource

api = application = falcon.API()

def load_trained_model():

global model

model = load_model(os.path.join(os.path.dirname(__file__), 'model/cnn_model.h5'))

model._make_predict_function() # make keras thread-safe

return model

predict = PredictResource(model=load_trained_model())

api.add_route('/predict', predict)

然後為了運行Falcon API,我們使用Gunicorn作為WSGI HTTP服務器(不像Flask,它沒有內置的Web服務器)和NGINX用於代理服務器。

負載測試

現在是時候測試我們的預測服務了。我們使用Locust進行負載測試。它是用Python編寫的,開源的,使用起來非常簡單。

我們在OpenShift上部署了應用程序,兩個工作人員使用Gevent。為了確保服務的穩定性,我們還擴展了三個容器,也稱為pod。

以下是200個模擬用戶的結果,每個用戶產生的hatch rate為1秒,

Falcon vs. Flask-選擇哪一個來創建可擴展的深度學習REST API

從表格(時間以毫秒 - 毫秒給出),我們可以看到我們已經為Flask和Falcon運行了大約10k的請求。我們還可以看到兩個框架的最小響應時間與19ms相同。儘管Flask在平均響應時間和最大響應時間方面稍好一些,但我們可以得出結論,兩者的表現非常相似。

結論

從我們的測試中我們得出結論,Falcon不一定比Flask更快。當然,可以進行更多的測試,例如更多的請求和更多的模擬用戶。但是,至少我們可以總結一下Falcon和Flask表現相似,即當我們只需要創建API時,Falcon可以用作可行的替代方案。代碼設計非常好,更適合REST API(在使用Falcon開發時,您應該考慮映射到HTTP方法的資源和狀態轉換)。


分享到:


相關文章: