具體而言,我們將了解:

在本教程結束時,你將能很好地理解創建Keras REST API所需的組件(以最簡單的形式)。

請隨意使用本指南中提供的代碼作為你自己的深度學習REST API起點。

1配置開發環境

假設Keras已經配置并安裝在你的機器上。如果沒有,請確保使用官方安裝說明安裝Keras(https://keras.io/#installation)。

然后,需要安裝Flask (http://flask.pocoo.org/)(及其相關的依賴項),一個Python web框架,這樣就可以構建API端點了。還需要請求(http://docs.python-requests.org/en/master/)這樣就可以使用API了。

有關的pip安裝命令如下:

$ pip install flask gevent requests pillow

2構建你的Keras REST API

Keras REST API獨立于一個名為run_keras_server.py的文件中。為了簡單起見,我們將安裝保存在一個文件中——安裝啟用也可以很容易地模塊化。

在 run_keras_server.py中,你會發現三個函數,即:

# import the necessary packagesfrom keras.applications import ResNet50from keras.preprocessing.image import img_to_arrayfrom keras.applications import imagenet_utilsfrom PIL import Imageimport numpy as npimport flaskimport io

# initialize our Flask application and the Keras modelapp = flask.Flask(__name__)model = None

第一個代碼片段處理導入了所需的程序包,并且對Flask應用程序和模型進行了初始化。

在此,我們定義load_model函數:

def load_model():

# load the pre-trained Keras model (here we are using a model

# pre-trained on ImageNet and provided by Keras, but you can

# substitute in your own networks just as easily)

global model

model = ResNet50(weights="imagenet")

顧名思義,這個方法負責將我們的架構實例化,并從磁盤加載權重。

為了簡單起見,將使用在ImageNet數據集上預先訓練過的ResNet50架構。如果你正在使用自定義模型,則需要修改此函數以從磁盤加載架構+權重。

在對任何來自客戶端的數據進行預測之前,首先需要準備并預處理數據:

def prepare_image(image, target):

# if the image mode is not RGB, convert it

if image.mode != "RGB":

image = image.convert("RGB")

# resize the input image and preprocess it

image = image.resize(target)

image = img_to_array(image)

image = np.expand_dims(image, axis=0)

image = imagenet_utils.preprocess_input(image)

# return the processed image

return image

這個函數:

·此外,在通過模型傳遞輸入數據之前,應該根據某一預處理、縮放或標準化來修改這個函數。

現在可以定義predict函數了——該方法會處理對/predict端點的任何請求:

@app.route("/predict", methods=["POST"])def predict():

# initialize the data dictionary that will be returned from the

# view

data = {"success": False}

# ensure an image was properly uploaded to our endpoint

if flask.request.method == "POST":

if flask.request.files.get("image"):

# read the image in PIL format

image = flask.request.files["image"].read()

image = Image.open(io.BytesIO(image))

# preprocess the image and prepare it for classification

image = prepare_image(image, target=(224, 224))

# classify the input image and then initialize the list

# of predictions to return to the client

preds = model.predict(image)

results = imagenet_utils.decode_predictions(preds)

data["predictions"] = []

# loop over the results and add them to the list of

# returned predictions

for (imagenetID, label, prob) in results[0]:

r = {"label": label, "probability": float(prob)}

data["predictions"].append(r)

# indicate that the request was a success

data["success"] = True

# return the data dictionary as a JSON response

return flask.jsonify(data)

數據字典用于存儲希望反饋到客戶端的所有數據。現在,它包含一個布爾值,用來表示預測是否成功,還將使用此字典來存儲對傳入數據進行的所有預測的結果。

為了接收輸入的數據,我們會檢查是否:

如果使用的是非圖像數據,則應刪除該請求文件代碼,并解析原始輸入數據,或者使用request.get_json()將輸入數據自動解析為Python字典/對象。

現在只需啟動我們的服務:

# if this is the main thread of execution first load the model and# then start the serverif __name__ == "__main__":

print(("* Loading Keras model and Flask starting server..."

"please wait until server has fully started"))

load_model()

app.run()

首先調用load_model從磁盤加載Keras模型。

對load_model的調用是一個阻止操作——阻止web服務在模型完全加載之前啟動。如果未能確保模型完全載入內存中,在啟動web服務之前也沒有做好推理準備,就可能會遇到以下情況:

在構建自己的Keras REST APIs時,務必確保插入邏輯,以保證在接受請求前模型就已加載并準備好進行推理。

3如何不在REST API中加載Keras模型

你可能想在predict函數中加載模型,如下所示:

# ensure an image was properly uploaded to our endpoint

if request.method == "POST":

if request.files.get("image"):

# read the image in PIL format

image = request.files["image"].read()

image = Image.open(io.BytesIO(image))

# preprocess the image and prepare it for classification

image = prepare_image(image, target=(224, 224))

# load the model

model = ResNet50(weights="imagenet")

# classify the input image and then initialize the list

# of predictions to return to the client

preds = model.predict(image)

results = imagenet_utils.decode_predictions(preds)

data["predictions"] = []...


該代碼意味著每次有新請求時都將加載模型。這太低效了,甚至會導致系統內存耗盡。

如果嘗試運行上面的代碼,你會注意到API將運行得特別慢(尤其是在模型很大的情況下)——這是由于為每個新請求加載模型的I/O和CPU操作開銷太大所致。

為了了解服務器內存是如何因此輕易崩潰的,假設服務器同時收到N個傳入請求。同樣,這意味著將有N個模型同時加載到內存中。同時,如果模型較大(如ResNet),那么存儲在RAM中的N個模型副本很容易就會耗盡系統內存。

所以,除非你有一個非這樣做不可的理由,否則請盡量避免為每個新的傳入請求加載一個新的模型實例。

注意:

這里我們假定使用的是默認的單線程Flask服務器。如果將其部署到多線程服務器,那么即使使用本文前面討論的“更正確”的方法,內存中仍會加載多個模型。如果你打算使用專用服務器,如Apache或nginx,則應該考慮使管道更具可擴展性。

4啟動你的Keras Rest API

啟動Keras REST API服務很簡單。

打開終端,執行:

$ python run_keras_server.py

Using TensorFlow backend.

* Loading Keras model and Flask starting server...please wait until server has fully started

...

* Running on http://127.0.0.1:5000

從輸出中可以看到,首先加載模型,然后可以啟動Flask服務器。

現在可以通過http://127.0.0.1:5000 訪問服務器。

但是,如果將IP地址+端口復制粘貼到瀏覽器中,會出現以下情況:這是因為在Flask URLs路由中沒有設置索引/主頁。那么試著通過瀏覽器訪問/predict端點:

這是因為在Flask URLs路由中沒有設置索引/主頁。那么試著通過瀏覽器訪問/predict端點:

出現了“方法不允許”錯誤。該錯誤是由于瀏覽器正在執行GET請求,但/predict只接受一個POST(我們將在下一節中演示如何執行)。

5使用cURL測試Keras REST API

在測試和調試Keras REST API時,請考慮使用cURL(https://curl.haxx.se/)(無論如何,cURL都是一個值得去學習如何使用的好工具)。

下圖是我們想要進行分類的圖像——一只狗,更具體而言,是一只比格犬:

我們可以使用curl將該圖像傳遞給API,并找出ResNet認為該圖像包含的內容:

$ curl -X POST -F image=@dog.jpg 'http://localhost:5000/predict'{

"predictions": [

{

"label": "beagle",

"probability": 0.9901360869407654

},

{

"label": "Walker_hound",

"probability": 0.002396771451458335

},

{

"label": "pot",

"probability": 0.0013951235450804234

},

{

"label": "Brittany_spaniel",

"probability": 0.001283277408219874

},

{

"label": "bluetick",

"probability": 0.0010894243605434895

}

],

"success": true}

-x標志和POST值表示我們正在執行POST請求。

我們提供-F image=@dog.jpg來表示正在提交表單編碼的數據。然后將image鍵設置為dog.jpg文件的內容。在dog.jpg之前提供@意味著我們希望cURL加載圖像的內容并將數據傳遞給請求。

最后的終點是:http://localhost:5000/predict

請注意輸入的圖像是如何以99.01%的置信度被正確地分類為“比格犬”的。余下的五大預測及其相關概率也包含在Keras API的響應之內。

6以編程方式使用Keras REST API

你很可能會向Keras REST API提交數據,然后以某種方式利用反饋的預測——這就要求我們以編程的方式處理來自服務器的響應。

這是一個使用requests Python程序包的簡單過程(
http://docs.python-requests.org/en/master/):

# import the necessary packagesimport requests

# initialize the Keras REST API endpoint URL along with the input# image pathKERAS_REST_API_URL = "http://localhost:5000/predict"IMAGE_PATH = "dog.jpg"

# load the input image and construct the payload for the requestimage = open(IMAGE_PATH, "rb").read()payload = {"image": image}

# submit the requestr = requests.post(KERAS_REST_API_URL, files=payload).json()

# ensure the request was successfulif r["success"]:

# loop over the predictions and display them

for (i, result) in enumerate(r["predictions"]):

print("{}. {}: {:.4f}".format(i + 1, result["label"],

result["probability"]))

# otherwise, the request failedelse:

print("Request failed")

KERAS_REST_API_URL指定端點,而IMAGE_PATH是在磁盤上輸入圖像的路徑。

使用IMAGE_PATH加載圖像,然后將payload構建到請求中??紤]到有效載荷,我們可以使用requests.post調用將數據發布到端點。在指示requests調用的末尾附加.json() :

一旦有了請求r的輸出,就可以檢查分類是否成功,然后循環r[“predictions”]。

要運行指令simple_request.py,首先要確保run_keras_server.py(即 Flask web服務器)正在運行。然后在一個單獨的框架中執行下列命令:

$ python simple_request.py

beagle: 0.9901

Walker_hound: 0.0024

pot: 0.0014

Brittany_spaniel: 0.0013

bluetick: 0.0011


我們成功地調用了Keras REST API,并通過Python得到了模型的預測。

注意,本文中的代碼僅用于指導,而非生產級別,也不能在高負載和大量傳入請求的情況下進行擴展。

該方法最好在以下情況下使用:

本文章轉載微信公眾號@海豚數智科學實驗室

上一篇:

利用Scriptable和百度API:開發你的百度熱搜追蹤工具

下一篇:

.NET Core Web APi類庫如何內嵌運行和.NET Core Web API 中的異常處理
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費