Linux服務(wù)器-flask部署深度學(xué)習(xí)模型
1.首先本地構(gòu)建DL模型
根據(jù)自己的實際業(yè)務(wù)場景構(gòu)建ML羹奉、DL模型,訓(xùn)練模型约计,并保存自己需要的模型诀拭,這里就不用過多贅述了。
2.本地跑通mac-將題目分類模型轉(zhuǎn)換為Web應(yīng)用程序
在原本的項目文件夾中新增如下幾個文件:
app.py
templates/
? ? ? ? home.html
? ? ? ? result.html
static/
? ? ? ? style.css
如圖:
子目錄templates是Flask在Web瀏覽器中查找靜態(tài)HTML文件的目錄煤蚌。
2.1 app.py代碼
from flask import Flask,render_template,url_for,request
from lstm_clf import get_title_text_label
app = Flask(__name__)
@app.route('/')
def home():
? ? return render_template('home.html')
@app.route('/predict',methods=['POST'])
def predict():
? ? if request.method == 'POST':
? ? ? ? message = request.form['message']
? ? ? ? y_label = get_title_text_label(message)
? ? return render_template('result.html',prediction = y_label)
if __name__ == '__main__':
? ? app.run(host='0.0.0.0', port=5018,debug=True)
app.py文件包含將由Python解釋器執(zhí)行以運行Flask Web應(yīng)用程序的主代碼
1耕挨、我們將應(yīng)用程序作為單個模塊運行细卧,因此我們使用參數(shù)初始化了一個新的Flask實例,__name__是為了讓Flask知道它可以在templates所在的同一目錄中找到HTML模板文件夾()筒占。
2贪庙、接下來,我們使用route decorator(@app.route('/'))來指定可以觸發(fā)home?函數(shù)執(zhí)行的URL?翰苫。我們的home?函數(shù)只是呈現(xiàn)home.htmlHTML文件止邮,該文件位于templates文件夾中。
3革骨、在predict函數(shù)內(nèi)部农尖,封裝了一個get_title_text_label(text)函數(shù)析恋,這個函數(shù)是對之前保存模型的封裝及使用良哲,通過訪問用戶輸入信息,傳入get_title_text_label(message)函數(shù)助隧,就會對輸入的數(shù)學(xué)題目文本進(jìn)行分類筑凫,返回預(yù)測的分類標(biāo)簽。
4并村、我們使用該POST方法將表單數(shù)據(jù)傳輸?shù)椒?wù)器巍实。最后,通過debug=True在app.run方法中設(shè)置參數(shù)哩牍,進(jìn)一步激活Flask的調(diào)試器棚潦。
5、最后膝昆,使用run函數(shù)執(zhí)行在服務(wù)器上的腳本文件丸边,我們需要確保使用if語句?__name__ == '__main__'。
2.2 home.html
以下是home.html將呈現(xiàn)文本表單的文件的內(nèi)容荚孵,用戶可以在其中輸入數(shù)學(xué)題目文本:
<!DOCTYPE html>
<html>
<head>
? ? <title>Home</title>
? ? <!--<link rel="stylesheet" type="text/css" href="../static/styles.css">-->
? ? <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/styles.css') }}">
</head>
<body>
? ? <header>
? ? ? ? <div class="container">
? ? ? ? <div id="brandname">
? ? ? ? ? ? <h2 style="color:black;text-align:center;">Mathematical Problem Classifier</h2>
? ? ? ? </div>
? ? </div>
? ? </header>
? ? <div class="ml-container" >
? ? ? ? <form action="{{ url_for('predict')}}" method="POST">
? ? ? ? <p style="color:blue;font-size:20px;text-align:center;">Enter Your Mathematical Problem Here</p>
? ? ? ? <div style="display: flex;justify-content:center;flex-direction: column">
? ? ? ? ? ? <textarea name="message" rows="10" cols="100" style="align-self: center;color:black;font-size:14px;text-align:left;" placeholder="e.g. '{'main': '直線\\{\\begin{matrix}x=-2+t\\\\ y=1-t\\end{matrix}(t為參數(shù))被圓(x-3)^{2}+(y+1)^{2}=25所截得的弦長為(? )', 'options': [], 'subquestions': []}'" ></textarea>
? ? ? ? <br/>
? ? ? ? <input type="submit" class="btn-info" value="predict" style="margin: 0 auto;font-size:18px;text-align:center;">
? ? </div>
? ? </form>
? ? </div>
</body>
</html>
2.3 style.css
在home.html的head部分妹窖,我們將加載styles.css文件,CSS文件是用于確定HTML文檔的外觀和風(fēng)格的收叶。styles.css必須保存在一個名為的子目錄中static骄呼,這是Flask查找靜態(tài)文件(如CSS)的默認(rèn)目錄。
body{
? ? font:15px/1.5 Arial, Helvetica,sans-serif;
? ? padding: auto;
? ? background-color:#f4f3f3;
}
.container{
? ? width:100%;
? ? margin: 0 auto;
? ? overflow: hidden;
}
header{
? ? background:#03A9F4;
? ? border-bottom:#448AFF 3px solid;
? ? height:120px;
? ? width:100%;
? ? padding-top:30px;
}
.main-header{
? ? ? ? ? ? text-align:center;
? ? ? ? ? ? background-color: blue;
? ? ? ? ? ? height:100px;
? ? ? ? ? ? width:100%;
? ? ? ? ? ? margin:0 auto;
? ? ? ? }
#brandname{
? ? float:left;
? ? font-size: 100px;
? ? color: #fff;
? ? /*margin: 10px;*/
}
header h2{
? ? text-align:center;
? ? color:#fff;
}
.btn-info {background-color: #2196F3;
? ? height:40px;
? ? width:100px;} /* Blue */
.btn-info:hover {background: #0b7dda;}
.resultss{
? ? border-radius: 15px 50px;
? ? background: #345fe4;
? ? padding: 20px;
? ? width: 200px;
? ? height: 150px;
}
2.4 result.html
我們創(chuàng)建一個result.html文件判没,該文件將通過函數(shù)render_template('result.html', prediction=my_prediction)返回呈現(xiàn)predict蜓萄,我們在app.py腳本中定義該文件以顯示用戶通過文本字段提交的文本。result.html文件包含以下內(nèi)容:
<!DOCTYPE html>
<html>
<head>
? ? <title></title>
? ? <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/styles.css') }}">
</head>
<body>
? ? <header>
? ? ? ? <div class="container">
? ? ? ? <div id="brandname">
? ? ? ? ? ? <h2 style="color:black;text-align:center;">Mathematical Problem Classifier</h2>
? ? ? ? </div>
? ? </div>
? ? </header>
? ? <p style="color:blue;font-size:20px;text-align:center;"><b>math tag:</b></p>
? ? <div class="results">
? ? <h2 style="color:blue;text-align:center;">{{prediction}}</h2>
? ? </div>
</body>
</html>
從result.htm文件我們可以看到一些代碼使用通常在HTML文件中找不到的語法例如{{prediction}}澄峰,這是jinja語法嫉沽,它用于訪問從HTML文件中請求返回的預(yù)測。
2.5 本地運行app.py
完成上述所有操作后摊阀,可以直接在pycharm中運行app.py文件耻蛇,也可以在mac 終端中切換至項目目錄踪蹬,然后
python app.py
結(jié)果顯示:
點擊網(wǎng)址進(jìn)入,顯示以下頁面:
predict之后頁面顯示:
到這里就已經(jīng)本地跑通flask部署web應(yīng)用了臣咖。
2.6 其他
深入了解其原理跃捣,可參見以下文章:
https://www.cnblogs.com/sebastiane-root/p/9365248.html
https://segmentfault.com/a/1190000018807684
3.最后實現(xiàn)linux服務(wù)器部署
Linux常用命令:https://www.cnblogs.com/gaojun/p/3359355.html
3.1首先下載secureCRT 登陸服務(wù)器
詳細(xì)Mac下安裝SecureCRT并激活教程鏈接:
https://blog.csdn.net/gengxiaoming7/article/details/79433940
安裝激活之后登陸
3.2打包項目文件zip,上傳至服務(wù)器并解壓
把自己項目文件打包成zip文件
在服務(wù)器上新建自己的文件夾:mkdir filename
zip文件包上傳至自己的文件夾夺蛇,? secureCRT可以使用 rz 和 sz 命令完成文件的上傳和下載疚漆,rz上傳時,自動跳出文件目錄進(jìn)行選擇刁赦,選擇相應(yīng)文件進(jìn)行選擇即可娶聘。對于需要變更默認(rèn)上傳以及下載文件目錄的,可以進(jìn)行設(shè)置
中文版目錄設(shè)置:??點開 secureCRT 的菜單項中的【選項】 --> 會話選項 --> 打開會話選項對話框 -->點擊分類中的的終端 --> X/Y/Zmodem
英文版目錄設(shè)置:?Options --> session options --> terminal --> X/Y/Zmodem
對上傳的zip包解壓:
解壓zip文件到當(dāng)前目錄 unzip filename.zip
3.3使用nohup啟動flask服務(wù)
上面已經(jīng)完成了項目文件的上傳甚脉,接下來啟動flask服務(wù):
在并發(fā)量不大丸升,僅是開發(fā)環(huán)境試用時,可以試用nohup啟動服務(wù)牺氨,nohup命令詳解鏈接:https://www.cnblogs.com/zq-inlook/p/3577003.html狡耻,下面簡單介紹:
nohup保證部署的服務(wù)在退出SSH客戶端后程序能一直執(zhí)行
nohup /usr/local/python3.6/bin/python3? app.py &
2.執(zhí)行nohup命令的時候,經(jīng)常會出現(xiàn)下面這種沒有寫入權(quán)限的錯誤猴凹。
nohup: ignoring input and appending output to `nohup.out'
解決方案:https://www.cnblogs.com/quchunhui/p/5582371.html
在使用nohup命令的時候夷狰,經(jīng)常由于輸出nohup.out的路徑?jīng)]有寫入權(quán)限,而無法使用nohup郊霎。
這是可以使用Linux重定向的方法沼头,將nohup.out重定向至一個有寫入權(quán)限的路徑,或者直接扔到/dev/null中书劝。
nohup ./program >/dev/null 2>/dev/null &
或者
nohup ./program >/dev/null 2>&1 &
本次使用的是:
nohup /usr/local/python3.6/bin/python3? app.py >/dev/null 2>&1 &
3. 到此為止进倍,就已經(jīng)完成服務(wù)器的flask服務(wù)部署了
訪問網(wǎng)址就可以體驗數(shù)學(xué)題目分類標(biāo)簽預(yù)測服務(wù)了:
IP地址:服務(wù)器的對外地址
端口號:5018是自己程序中設(shè)置的,未被占用的端口號
3.4其他1--關(guān)于端口號被占用的解決方案
如果端口號被占用本次使用的是:
查看進(jìn)程
ps -ef | grep python3
殺掉進(jìn)程
kill -9 XXXX
詳細(xì)鏈接:https://blog.csdn.net/weixin_42109679/article/details/80578778
關(guān)于LINUX中如何查看某個端口是否被占用:https://blog.csdn.net/yyf960126/article/details/80908823
這樣就可以在app.py中設(shè)置不被占用的端口號
#查看該端口號是否被占用
netstat ?-anp ?|grep ? 端口號
#該命令是查看當(dāng)前所有已經(jīng)使用的端口情況
netstat ? -nultp
3.5 其他2--關(guān)于Python2與Python3出現(xiàn)沖突的問題
如果使用pip install jieba,在服務(wù)器上會默認(rèn)安裝至Python2庄撮,但是我們平時使用的是Python3背捌,所以使用如下命令執(zhí)行:
/usr/local/python3.6/bin/pip install --user jieba
為什么使用--user,也是為了解決?Permission denied這個問題洞斯,防止pip安裝報錯
對于Python執(zhí)行程序時毡庆,也是使用:
/usr/local/python3.6/bin/python3 XX.py
3.6 其他3--對并發(fā),進(jìn)程烙如,線程有要求時么抗,可以使用uwsgi 啟動flask 服務(wù)方式
添加 app.ini文件
代碼如下:
[uwsgi]
master = true
http=0.0.0.0:5018
chdir =項目文件夾地址
wsgi-file=app.py
callable=app
processes=4
threads=2
buffer-size = 65536
socket-timeout = 240
uid = work
gid = work
protocol = uwsgi
詳細(xì)解釋,參考鏈接:https://www.runoob.com/python3/python-uwsgi.html
https://blog.csdn.net/u013421629/article/details/84103873
相關(guān)參數(shù)解釋:
master = true
#啟動主進(jìn)程亚铁,來管理其他進(jìn)程蝇刀,其它的uwsgi進(jìn)程都是這個master進(jìn)程的子進(jìn)程,如果kill這個master進(jìn)程徘溢,相當(dāng)于重啟所有的uwsgi進(jìn)程吞琐。
chdir = /web/www/mysite
#在app加載前切換到當(dāng)前目錄捆探, 指定運行目錄
socket = /test/myapp.sock
#指定socket文件,也可以指定為127.0.0.1:9000站粟,這樣就會監(jiān)聽到網(wǎng)絡(luò)套接字
processes = 2 #啟動2個工作進(jìn)程黍图,生成指定數(shù)目的worker/進(jìn)程
buffer-size = 32768
#設(shè)置用于uwsgi包解析的內(nèi)部緩存區(qū)大小為64k。默認(rèn)是4k奴烙。
服務(wù)器中啟動方式
/usr/local/python3.6/bin/uwsgi app.ini
停止:
-- 停止 uwsgi
pkill -f -9 uwsgi