將Keras深度學習模型部署爲Web應用程序

編譯:yxy

出品:ATYUN訂閱號

建立一個很酷的機器學習項目確實很不錯,但如果你希望其他人能夠看到你的作品怎麼辦呢?當然,你可以將整個項目放在GitHub上,但這隻能給程序員看,如果你想給自己家裏的老人看呢?GitHub肯定不行,所以我們想要的是將我們的深度學習模型部署成世界上任何人都輕易訪問的Web應用程序。

在本文中,我們將看到如何編寫一個Web應用程序獲取經過訓練的RNN,並使用戶生成新的專利摘要。這個項目建立在RNN示例項目:詳解使用RNN撰寫專利摘要文章的基礎上,但你不需要知道如何創建RNN。我們現在只將其視爲一個黑盒子:我們輸入一個起始序列,它輸出一個全新的專利摘要,然後將其在瀏覽器上顯示!

http://www.atyun.com/32461.html

一般來說,數據科學家開發模型,前端工程師負責展示。但在這個項目中,我們將不得不同時扮演這兩個角色,並深入研究Web開發(儘管幾乎的都用Python寫)。

這個項目需要結合:

  • Flask:用Python創建一個基本的Web應用程序
  • Keras:部署訓練好的RNN
  • 使用Jinja模板庫進行模板化
  • 用於編寫網頁的HTML和CSS

最終我們得到一個Web應用程序,允許用戶使用訓練好的RNN生成全新的專利摘要:

方法

我們的目標是儘快啓動和運行Web應用程序。因此,我選擇了Flask,它使我們可以用Python編寫應用程序。我不喜歡亂糟糟的樣式所以幾乎所有的CSS都是複製和粘貼的。

Flask的基本Web應用程序

在Python中構建Web應用程序的最快方法是使用Flask。要製作我們自己的應用,我們可以:

from flaskimport Flask
app= Flask(__name__)
@app.route("/")
def hello():
    return "<h1>Not Much Going On Here</h1>"
app.run(host='0.0.0.0', port=50000)

如果你複製粘貼此代碼並運行它,將能夠在localhost:50000上看到自己的Web應用程序。當然,我們要做的肯定不僅僅是這些,所以我們使用一個稍微複雜的函數,它基本上做同樣的事情:處理來自瀏覽器的請求並將一些內容作爲HTML提供。對於我們的主頁面,我們希望向用戶顯示一個表單(Form),使用戶可以輸入一些詳細信息。

用戶輸入表格

當我們的用戶到達應用程序的主頁面時,我們將向他們展示一個包含三個參數的表單:

  1. 輸入RNN的起始序列或隨機選擇
  2. 選擇RNN預測的多樣性
  3. 選擇RNN輸出的字數

要在Python中構建表單,我們將使用wtforms 。製作表單的代碼是:

from wtformsimport (Form, TextField, validators, SubmitField,
DecimalField, IntegerField)
class ReusableForm(Form):
    """User entry form for entering specifics for generation"""
    # Starting seed
    seed= TextField("Enter a seed string or 'random':", validators=[
                     validators.InputRequired()])
    # Diversity of predictions
    diversity= DecimalField('Enter diversity:', default=0.8,
                             validators=[validators.InputRequired(),
                                         validators.NumberRange(min=0.5,max=5.0,
                                         message='Diversity must be between 0.5 and 5.')])
    # Number of words
    words= IntegerField('Enter number of words to generate:',
                         default=50, validators=[validators.InputRequired(),
                                                 validators.NumberRange(min=10,max=100,
                                                 message='Number of words must be between 10 and 100')])
    # Submit button
    submit= SubmitField("Enter")

這將創建一個如下所示的表單(帶有main.css的樣式):

代碼中的validator確保用戶輸入正確的信息。例如,我們檢查所有輸入框已填充且diversity介於0.5和5之間。必須滿足這些條件才能接受表單。

驗證錯誤

我們實際使用Flask提供表單服務的方式是使用模板。

模板

模板是一個帶有基本框架的文檔,我們需要添加詳細信息。對於Flask Web應用程序,我們可以使用Jinja模板庫將Python代碼傳遞給HTML文檔。例如,在我們的main函數中,我們將表單的內容發送到一個名爲index.html的模板。

from flaskimport render_template
# Home page
@app.route("/", methods=['GET','POST'])
def home():
    """Home page of app with form"""
    # Create form
    form= ReusableForm(request.form)
    # Send template information to index.html
    return render_template('index.html', form=form)

當用戶到達主頁時,我們的應用程序將提供帶有form詳細信息的index.html息。模板是一個簡單的html腳手架,我們用{{variable}} 語法引用python變量。

<!DOCTYPE html>
<html>
<head>
  <title>RNN Patent Writing</title>
  <link rel="stylesheet" href="/static/css/main.css">
  <link rel="shortcut icon" href="/static/images/lstm.ico">
</head>
<body>
  <divclass="container">
    <h1>
      <center>Writing Novel Patent Abstracts with Recurrent Neural Networks</center>
    </h1>
    {% block content %}
    {%for message in form.seed.errors %}
    <divclass="flash">{{ message }}</div>
    {%endfor %}
    {%for message in form.diversity.errors %}
    <divclass="flash">{{ message }}</div>
    {%endfor %}
    {%for message in form.words.errors %}
    <divclass="flash">{{ message }}</div>
    {%endfor %}
    <form method=post>
      {{ form.seed.label }}
      {{ form.seed }}
      {{ form.diversity.label }}
      {{ form.diversity }}
      {{ form.words.label }}
      {{ form.words }}
      {{ form.submit }}
    </form>
    {% endblock %}
  </div>
</body>
</html>

對於表單中的每個錯誤(那些無法驗證的條目),錯誤將flash。除此之外,此文件將顯示上面的表單。

當用戶輸入信息並點擊submit(POST請求)時,如果信息是正確的,我們希望將輸入轉移到正確的函數以使用經過訓練的RNN進行預測。這意味着要修改home() 。

from flaskimport request
# User defined utility functions
from utilsimport generate_random_start, generate_from_seed
# Home page
@app.route("/", methods=['GET','POST'])
def home():
    """Home page of app with form"""
    # Create form
    form= ReusableForm(request.form)
    # On form entry and all conditions met
    if request.method== 'POST' and form.validate():
        # Extract information
        seed= request.form['seed']
        diversity= float(request.form['diversity'])
        words= int(request.form['words'])
        # Generate a random sequence
        if seed== 'random':
            return render_template('random.html',
                                   input=generate_random_start(model=model,
                                                               graph=graph,
                                                               new_words=words,
                                                               diversity=diversity))
        # Generate starting from a seed sequence
        else:
            return render_template('seeded.html',
                                   input=generate_from_seed(model=model,
                                                            graph=graph,
                                                            seed=seed,
                                                            new_words=words,
                                                            diversity=diversity))
    # Send template information to index.html
    return render_template('index.html', form=form)

現在,當用戶點擊submit並且信息正確時,輸入被髮送到generate_random_start或generate_from_seed中(取決於輸入)。這些函數使用經過訓練的Keras模型生成具有用戶指定的diversity和num_words的新專利。這些函數的輸出依次被髮送到random.html或seeded.html任一模板作爲網頁。

用預訓練的Keras模型進行預測

model參數是經過訓練的Keras模型,其加載如下:

from keras.modelsimport load_model
import tensorflow as tf
def load_keras_model():
    """Load in the pre-trained model"""
    global model
    model= load_model('../models/train-embeddings-rnn.h5')
    # Required for model to work
    global graph
    graph= tf.get_default_graph()
load_keras_model()

(這tf.get_default_graph()是基於以下gist的變通方案。)

gist:https://gist.github.com/eyesonlyhack/2f0b20f1e73aaf5e9b83f49415f3601a

在這裏我沒有展示util函數的全部內容(https://github.com/WillKoehrsen/recurrent-neural-networks/blob/master/deployment/utils.py),你所需要了解的是,他們使用訓練過的Keras模型和參數,並對一個新的專利摘要進行預測。

這些函數都返回HTML格式的Python字符串。此字符串將發送到另一個模板以顯示爲網頁。例如,generate_random_start返回格式化的html進入random.html:

<!DOCTYPE html>
<html>
<header>
    <title>Random Starting Abstract
    </title>
    <link rel="stylesheet" href="/static/css/main.css">
    <link rel="shortcut icon" href="/static/images/lstm.ico">
    <ul>
        <li><a href="/">Home</a></li>
    </ul>
</header>
<body>
    <divclass="container">
        {% block content%}
        {{input|safe}}
        {% endblock%}
    </div>
</body>
</html>

在這裏,我們再次使用Jinja模板引擎來顯示格式化的HTML。由於Python字符串已經格式化爲HTML,我們所要做的就是使用{{input|safe}}(input是Python變量)來顯示它。然後我們可以像使用其他html模板一樣用main.css設置此頁面的樣式。

輸出

函數generate_random_start選擇隨機專利摘要作爲起始序列,並根據它進行預測。然後顯示起始序列,RNN生成的輸出和實際輸出:

隨機啓動序列的輸出。

函數generate_from_seed採用用戶提供的啓動序列,然後使用訓練好的RNN構建輸出。輸出顯示如下:

從起始種子序列得到的輸出

雖然結果並不總是完全正確,但它們確實表明RNN已經掌握了英語的基礎知識。它經過訓練可以預測前50個單詞中的下一個單詞,並且已經學會了如何編寫一個略有說服力的專利摘要!根據預測的多樣性,輸出可能完全是隨機的或循環的。

運行應用程序

要自己運行應用程序,只需下載存儲庫,到deployment目錄的python run_keras_server.py 。這將立即使web應用程序在localhost:10000上可用。

根據家庭WiFi的配置方式,你應該能夠使用你的IP地址從網絡上的任何計算機訪問該應用程序。

下一步

在個人計算機上運行的Web應用程序非常適合與朋友和家人共享。不過,我絕對不會建議在你的家庭網絡中向所有人開放這個網站!此,我們將在AWS EC2實例上設置應用程序,並將其提供給全世界(會在下節提供)。

爲了改進應用程序,我們可以改變樣式(通過main.css),或許還可以添加更多選項,比如選擇預訓練好的網絡。個人項目的好處是,你可以隨心所欲地去做。如果您想玩這個應用程序,請下載代碼並開始使用。

結論

在本文中,我們瞭解瞭如何將經過訓練的Keras深度學習模型部署爲Web應用程序。這需要許多不同的技術,包括RNN,Web應用程序,模板,HTML,CSS,當然還有Python。

雖然這只是一個基礎的應用程序,但它表明你可以用相對較少的努力開始使用深度學習來構建Web應用程序。沒有多少人可以將深度學習模型部署爲Web應用程序,但如果如果按本文操作,那麼你就可以!

GitHub:https://github.com/WillKoehrsen/recurrent-neural-networks

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章