基于 docker 和 Flask 的深度學(xué)習(xí)模型部署轻纪!

推薦:Python全棧教程痹扇!花了29980買的從入門到精通課程橡羞,分享給大家

模型部署一直是深度學(xué)習(xí)算法走向落地的重要的一環(huán)患整。隨著深度學(xué)習(xí)落地需求越來越迫切拜效,具備一定工程部署能力是算法工程師的必備能力之一。

深度學(xué)習(xí)模型一個比較關(guān)鍵的前置條件就是需要花不少時間進(jìn)行環(huán)境配置各谚,可能先需要建一個虛擬環(huán)境紧憾,然后配置深度學(xué)習(xí)框架和一些第三方庫,即時性和可移植性都比較差昌渤,總體而言可用性就不是那么強(qiáng)了赴穗。那么有沒有一種可以一鍵部署的方式?能在10分鐘內(nèi)就可以在一臺新機(jī)器上部署好我們的深度學(xué)習(xí)模型膀息?答案是肯定的望抽。本文筆者基于容器化技術(shù)的經(jīng)典工具docker,對REST API模型部署方式進(jìn)行升級履婉,讓模型部署更加高可用煤篙。

docker簡介

先簡單說一下docker。docker是一款基于Go語言開發(fā)的開源容器化技術(shù)毁腿。為了避免你寫的代碼在不同環(huán)境上表現(xiàn)不一辑奈,docker提供了一種環(huán)境隔離技術(shù)苛茂,將你的代碼和代碼所有的依賴都打包到container中去,做到once build鸠窗,run everywhere的效果妓羊。關(guān)于docker更詳細(xì)的介紹,各位讀者可以自行查找資料進(jìn)行學(xué)習(xí)稍计,不作為本文的重點(diǎn)躁绸。

docker實(shí)際要重點(diǎn)掌握幾個概念和操作如下圖所示。

類似于makefile風(fēng)格臣嚣,dockfile是用于生成image(鏡像)的文件翁潘,這個是需要我們自己編寫的骗露,編寫完dockerfile之后蚕涤,通過docker build命令生成image噪裕,這個image可以理解為可執(zhí)行程序,最后通過docker run運(yùn)行這個可執(zhí)行程序image怎虫,運(yùn)行起來的這個image就是container(容器)暑认。

關(guān)于ubuntu docker安裝可參考:https://docs.docker.com/engine/install/ubuntu/

基于Falsk的REST API實(shí)現(xiàn)

下面進(jìn)入正文,來看基于docker和Flask如何快速部署一個深度學(xué)習(xí)模型大审,模型是一個基于MobileNetV2的圖像分類器蘸际。用于啟動REST API的app.py文件代碼編寫如下:

import os
import sys
# Flask
from flask import Flask, redirect, url_for, request, render_template, Response, jsonify, redirect
from werkzeug.utils import secure_filename
from gevent.pywsgi import WSGIServer
# TensorFlow and tf.keras
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.applications.imagenet_utils import preprocess_input, decode_predictions
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing import image
# Some utilites
import numpy as np
from util import base64_to_pil
# Declare a flask app
app = Flask(__name__)
# You can use pretrained model from Keras
# Check https://keras.io/applications/
# or https://www.tensorflow.org/api_docs/python/tf/keras/applications
from tensorflow.keras.applications.mobilenet_v2 import MobileNetV2
model = MobileNetV2(weights='imagenet')
print('Model loaded. Check http://127.0.0.1:5000/')
# Model saved with Keras model.save()
MODEL_PATH = 'models/your_model.h5'
# Load your own trained model
# model = load_model(MODEL_PATH)
# model._make_predict_function()          # Necessary
# print('Model loaded. Start serving...')
def model_predict(img, model):
    img = img.resize((224, 224))
    # Preprocessing the image
    x = image.img_to_array(img)
    # x = np.true_divide(x, 255)
    x = np.expand_dims(x, axis=0)
    # Be careful how your trained model deals with the input
    # otherwise, it won't make correct prediction!
    x = preprocess_input(x, mode='tf')
    preds = model.predict(x)
    return preds

@app.route('/', methods=['GET'])
def index():
    # Main page
    return render_template('index.html')
@app.route('/predict', methods=['GET', 'POST'])
def predict():
    if request.method == 'POST':
        # Get the image from post request
        img = base64_to_pil(request.json)
        # Save the image to ./uploads
        # img.save("./uploads/image.png")
        # Make prediction
        preds = model_predict(img, model)
        # Process your result for human
        pred_proba = "{:.3f}".format(np.amax(preds))    # Max probability
        pred_class = decode_predictions(preds, top=1)   # ImageNet Decode
        result = str(pred_class[0][0][1])               # Convert to string
        result = result.replace('_', ' ').capitalize()        
        # Serialize the result, you can add additional fields
        return jsonify(result=result, probability=pred_proba)
    return None

if __name__ == '__main__':
    # app.run(port=5002, threaded=False)
  # Serve the app with gevent
    http_server = WSGIServer(('0.0.0.0', 5000), app)
    http_server.serve_forever()

這里主要是基于Flask web框架實(shí)現(xiàn)一個REST API服務(wù),并添加html模板徒扶,將服務(wù)運(yùn)行到指定的IP地址上捡鱼。

為了實(shí)現(xiàn)在指定網(wǎng)頁上的效果,除了應(yīng)用html模板之外酷愧,我們還需要編寫一點(diǎn)css樣式和js代碼,這里略過缠诅,可參考文末鏈接查看完整代碼溶浴。

編寫dockerfile

接下來我們需要編寫dockerfile,這是實(shí)現(xiàn)docker一鍵部署的起始點(diǎn)和關(guān)鍵所在管引。簡單來說士败,就是通過一系列dockerfile指令將Python環(huán)境、項目所需第三方庫褥伴、腳本運(yùn)行等串起來谅将,實(shí)現(xiàn)一鍵操作。所以在本例中我們可編寫dockfile文件如下:

# 指定Python環(huán)境
FROM python:3.6-slim-stretch
# 拷貝Python依賴庫requirements文件到當(dāng)前目錄下
ADD requirements.txt /
# 安裝依賴庫
RUN pip install -r /requirements.txt
# 拷貝所有文件到app目錄下
ADD . /app
# 指定app為工作目錄
WORKDIR /app
# 聲明端口
EXPOSE 5000
# docker容器啟動
CMD [ "python" , "app.py"]

requirements.txt包括的第三方依賴庫有:

Flask==1.1.1
gevent==1.4.0
h5py==2.10.0
numpy==1.17.0
Pillow==6.1.0
tensorflow==2.3.1
Werkzeug==0.16.0

基于docker的模型部署

編寫完dockerfile文件后重慢,即可通過docker來對該深度學(xué)習(xí)分類器進(jìn)行線上部署饥臂。docker build命令建立改項目鏡像:

docker build -t keras_flask_app .

根據(jù)dockerfile中的7條指令,docker build也會經(jīng)過個步驟來生成鏡像似踱。

生成鏡像后即可運(yùn)行隅熙,使得該深度學(xué)習(xí)項目服務(wù)啟動:

服務(wù)啟動后稽煤,我們打開http://localhost:5000/即可使用該深度學(xué)習(xí)服務(wù):

我們從本地上傳一張圖像進(jìn)行測試:

這樣,通過基于Flask實(shí)現(xiàn)的REST API服務(wù)和基于docker的一鍵部署功能結(jié)合在一起囚戚,我們就可以在短時間內(nèi)快速搭建一套線上的深度學(xué)習(xí)服務(wù)酵熙。

完整項目代碼可參考:https://github.com/mtobeiyf/keras-flask-deploy-webapp

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市驰坊,隨后出現(xiàn)的幾起案子匾二,更是在濱河造成了極大的恐慌,老刑警劉巖拳芙,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件察藐,死亡現(xiàn)場離奇詭異,居然都是意外死亡态鳖,警方通過查閱死者的電腦和手機(jī)转培,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浆竭,“玉大人浸须,你說我怎么就攤上這事“钚梗” “怎么了删窒?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長顺囊。 經(jīng)常有香客問我肌索,道長,這世上最難降的妖魔是什么特碳? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任诚亚,我火速辦了婚禮,結(jié)果婚禮上午乓,老公的妹妹穿的比我還像新娘站宗。我一直安慰自己,他們只是感情好益愈,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布梢灭。 她就那樣靜靜地躺著,像睡著了一般蒸其。 火紅的嫁衣襯著肌膚如雪敏释。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天摸袁,我揣著相機(jī)與錄音钥顽,去河邊找鬼。 笑死靠汁,一個胖子當(dāng)著我的面吹牛耳鸯,可吹牛的內(nèi)容都是我干的湿蛔。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼县爬,長吁一口氣:“原來是場噩夢啊……” “哼阳啥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起财喳,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤察迟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后耳高,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扎瓶,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年泌枪,在試婚紗的時候發(fā)現(xiàn)自己被綠了概荷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡碌燕,死狀恐怖误证,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情修壕,我是刑警寧澤愈捅,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站慈鸠,受9級特大地震影響蓝谨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜青团,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一譬巫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧督笆,春花似錦芦昔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瘪松。三九已至咸作,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間宵睦,已是汗流浹背记罚。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留壳嚎,地道東北人桐智。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓末早,卻偏偏與公主長得像,于是被迫代替她去往敵國和親说庭。 傳聞我的和親對象是個殘疾皇子然磷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容