• トップ
  • ブログ一覧
  • 【第1回】ResponderとKerasを使って機械学習Webアプリケーションを作ってみた【大枠作成編】
  • 【第1回】ResponderとKerasを使って機械学習Webアプリケーションを作ってみた【大枠作成編】

    広告メディア事業部広告メディア事業部
    2019.10.29

    IT技術

    第1回~ResponderとKerasで機械学習アプリケーションを作りたい!~

    今、人気に火が着きつつある Python の WebAPIフレームワーク「Responder(レスポンダー)」

    以前、ライトコードでも流行りに全力で乗っかり「Responderを使ってDjangoチュートリアルをやってみた」という連載記事を行いました。

    featureImg2019.10.25【まとめ編】Responderを使ってDjangoチュートリアルをやってみたResponderを使ってDjangoチュートリアルをやってみた~まとめ~ライトコード社長も今、イチオシのWEBフレー...

    ResponderとKerasを使って機械学習Webアプリケーションを作ってみる!

    今回から始まる連載は「ResponderとKerasを使って機械学習Webアプリケーションを作ってみた」です!

    なぜこのような連載を始めたかというと、3つ理由があります。

    1. Responderが面白く、他にもWebアプリを作ってみたい!
    2. Responderの非同期処理を使ってみたい!
    3. せっかくのPythonのフレームワークなので機械学習と組み合わせたい!

    特に、2番目の「非同期処理」については「Responderを使ってDjangoチュートリアルをやってみた」の連載では紹介しきれませんでした。

    連載終了後、「機械学習と相性が良いのでは!?」と思い立ち、「Responder」と「機械学習」を絡めた記事を書くことを決めました。

    簡単なアプリケーションではありますが、Responderのさらに詳しい使い方が分かっていただける記事になるはずです!

    実装環境

    1.  Webアプリケーション部分は、「Responder」
    2. 機械学習フレームワークは、「Keras」

    Responder は Webアプリケーション部分、機械学習フレームワークは Keras を使います。

    なお、本記事では、以下の環境で実装をしています。

    Python3.7.4
    Responder1.3.2
    Keras2.2.4

    この記事の完成品

    今回の連載で「どんなWebアプリケーションが完成するのか?」を、簡単にお見せしておきたいと思います。

    トップページ

    トップページでは、学習させるタスク(データセット)を選択します。

    ネットワーク作成ページ

    データセットを選択したら、ユーザがネットワークを自由に作成します。

    また、ちょっとしたパラメータも指定できるようにします。

    以下のように、層を ある程度自由に追加できます。

    ネットワークを学習させる

    作成したネットワークをバックグラウンド(重要!)で学習させます。

    結果を表示する

    学習が終了したら、学習結果ページに移行させます。

    そのページでは、学習遷移などが確認できます。

    アプリを作成手順

    それでは早速、作業に取り掛かってまいりましょう!

    手順

    アプリ作成は、以下の手順で進めていきます。

    1. Responderの大枠作成
    2. トップページのデザインの作成
    3. ネットワーク作成ページの作成
    4. バックグラウンドタスク(学習部)の作成
    5. 学習結果ページの作成

    それでは、順番にいきます。

    Responderの大枠作成

    まずはじめに、Responderのファイル構成などを決めてしまいます。

    Responderでは、サーバー立ち上げもルーティングも1つのファイルでやろうと思えばできるのですが、それだと後々管理が困難になります。

    ですので、Djangoのように用途によってファイルを分けたいと思います。

    サーバー立ち上げ用 - run.py

    これは、今後いじることはありません。

    サーバーの立ち上げのみ担います。

    1"""
    2run.py
    3サーバ立ち上げ用ファイル
    4"""
    5
    6from urls import api
    7
    8if __name__ == '__main__':
    9    api.run()

    ルーティング用 - urls.py

    このファイルに、「ルーティング処理」を記述していきます。

    が、ここにはURLを受け取ったときの処理は書きません。

    この後に説明する、コントローラに処理を投げます

    Responderは通常、@api.route() デコレータでルーティングをします。

    しかし、今回は処理を分けるためにapi.add_route('URL', classなど) を使います。

    1"""
    2urls.py
    3ここではURLとコントローラのルーティング、およびJinja2のフィルタ設定を行う。
    4"""
    5
    6from controllers import *
    7
    8
    9# ルーティング
    10api.add_route('/', IndexController)

    ルーティング処理用 - controller.py

    先ほどのapi.add_route() で追加されたURLの処理を書くファイルです。

    また、ここで Responder の APIインスタンスを作成します。

    1"""
    2controllers.py
    3ResponderAPIを生成し、コントローラを管理するファイル。
    4"""
    5
    6import responder
    7
    8api = responder.API(
    9    title='Let\'s Learn Machine Learning',
    10    openapi='3.0.2',
    11    description='Web上で機械学習を学ぼう!',
    12    version='Beta',
    13)
    14
    15
    16class IndexController:
    17    async def on_get(self, req, resp):
    18        title = 'ResponderとKerasで学ぶ機械学習アプリケーション'
    19        resp.html = api.template('index.html', title=title)

    これで、Responder-Webアプリケーションの大枠が完成です。

    それでは試しに、全体レイアウトの「 templates/layout.html 」と、トップページデザインの「 templates/index.html 」を作りましょう。

    全体のレイアウト - layout.html

    今回もデザインには、Bootstrap4 を用います。

    【参考】
    はじめに - Bootstrap 4.3 - 日本語リファレンス

    各コントローラから、ページタイトルを受け取る仕様にしてみます。

    1<!DOCTYPE html>
    2<html lang="ja">
    3<head>
    4    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    5    <meta charset="UTF-8">
    6    <title>ResKeras | {{title}}</title>
    7</head>
    8<body>
    9<div style="display: flex; flex-direction: column; min-height: 80vh">
    10    <div class="container">
    11        {% block content %}
    12        <!-- メインコンテンツ -->
    13        {% endblock %}
    14    </div>
    15</div>
    16<br>
    17<hr>
    18<footer>
    19    <div align="center">
    20        <p>Copyright &copy; RightCode Inc. All right reserves.</p>
    21        <p>Powered by Responder and Keras</p>
    22    </div>
    23</footer>
    24</body>
    25</html>

    このファイルは、もういじることはありません。

    トップページ - index.html

    それでは、トップページを適当に作ります。

    1{% extends "layout.html" %}
    2
    3{% block content %}
    4<br>
    5<h1>ResKeras</h1>
    6<p> - ResponderとKerasで学ぶ機械学習アプリケーション - </p>
    7<hr>
    8<br>
    9<br>
    10<p>Web上で気軽に機械学習を学ぼう!</p>
    11<p>まずは以下から学習させたいタスクを選択しましょう。</p>
    12
    13{% endblock %}

    まだ質素なページですが、ここで動作確認をしてみましょう。

    動作確認

    1$ python run.py

    http://127.0.0.1:5042 にアクセスしてみます。

    うまく動作していそうです。

    Jinja2にフィルタを追加してみる

    トップページに情報を書き加えていきます。

    が、その前に、htmlファイルがスッキリするように、Jinja2 のフィルタ機能を活用してみます。

    ちなみに、Jinja2とは先程の、htmlファイルでいう{{ }} や{% %} に囲まれた部分がJinja2が処理する部分で、htmlを生成してくれるテンプレートエンジンです。

    Jinja2環境設定用ファイル - jinja_env.py

    Jinja2のフィルタは、「 jinja_env.py 」というファイルで定義します。

    とりあえずは、以下のように書いておきます。

    1"""
    2jinja_env.py
    3Jinja2のフィルタを定義する
    4"""
    5
    6
    7def static_filter(path):
    8    return '/static/' + path
    9
    10
    11def image_filter(path):
    12    return '/static/images/' + path
    13
    14
    15def css_filter(path):
    16    return '/static/css/' + path
    17
    18
    19def script_filter(path):
    20    return '/static/script/' + path
    21
    22
    23def badge_filter(text):
    24    return '<span class="badge badge-secondary">' + text + '</span>'
    25
    26
    27def badge_active_filter(text):
    28    return '<span class="badge badge-primary">' + text + '</span>'

    urls.pyでフィルタを登録

    次に、urls.py に以下を追記します。

    1import jinja_env  # 追記部分
    2from controllers import *
    3
    4# 以下追記部分 ... フィルタを辞書に登録
    5api.jinja_env.filters.update(
    6    static=jinja_env.static_filter,
    7    image=jinja_env.image_filter,
    8    css=jinja_env.css_filter,
    9    script=jinja_env.script_filter,
    10    badge=jinja_env.badge_filter,
    11    badge_active=jinja_env.badge_active_filter,
    12)
    13
    14# ルーティング
    15api.add_route('/', IndexController)

    そうすると、テンプレート側では、'/static/images/image.png' と書いていたところを、{{ 'image.png' | image }} のように、パイプでスッキリ書けます。

    これで管理のしやすさも向上しました。

    バッジ

    また、ついでに「バッジ」もフィルタに登録しました。

    これは

    1{% autoescape false %}
    2{{ 'データセットを選択' | badge_active }}
    3{{ 'ネットワークを作成' | badge }}
    4{{ '学習' | badge }}
    5{{ '結果' | badge }}
    6{% endautoescape %}

    と書くと、以下のように表示されます。

    ちょっとしたオシャレ要素です(笑)

    ここで{% autoescape false %} をつけないと、うまく表示されません。(一度消してみるとどうなるか分かります)

    トップページを完成させる

    では、トップページを完成させましょう。

    役割としては、ユーザに「データセット」を選ばせるページなので、使うデータセットの情報を表示し、選択されたデータセットに対応したネットワーク作成ページにリンクさせます。

    そのため、こんな感じにしてみました。

    1{% extends "layout.html" %}
    2
    3{% block content %}
    4<br>
    5<h1>ResKeras</h1>
    6<p> - ResponderとKerasで学ぶ機械学習アプリケーション - </p>
    7<hr>
    8
    9{% autoescape false %}
    10{{ 'データセットを選択' | badge_active }}
    11{{ 'ネットワークを作成' | badge }}
    12{{ '学習' | badge }}
    13{{ '結果' | badge }}
    14{% endautoescape %}
    15
    16<br>
    17<br>
    18<p>Web上で気軽に機械学習を学ぼう!</p>
    19<p>まずは以下から学習させたいタスクを選択しましょう。</p>
    20<div class="row">
    21    <div class="col-md-4">
    22        <div class="card bg-dark text-white">
    23            <div class="card-header">
    24                <a href="/create/mnist">MNIST Dataset</a>
    25            </div>
    26            <div class="card-body">
    27                <a href="/create/mnist"><img src="{{ 'mnist.png' | image }}" width="100%"></a>
    28            </div>
    29            <div class="card-footer">
    30                <p>
    31                    タスク : 画像分類<br>
    32                    入力  : 28x28のグレースケール画像<br>
    33                    ラベル : 0~9 (欠損なし)<br>
    34                    データ :70000<br>
    35                    特徴  : 簡易画像分類ベンチマーク
    36                </p>
    37                <p>配布元 : <a href="http://yann.lecun.com/exdb/mnist/">THE MNIST DATABAE</a></p>
    38            </div>
    39        </div>
    40    </div>
    41
    42    <div class="col-md-4">
    43        <div class="card bg-dark text-white">
    44            <div class="card-header">
    45                <a href="/create/iris">UCI Iris Dataset</a>
    46            </div>
    47            <div class="card-body">
    48                <a href="/create/iris"><img src="{{ 'iris.png' | image }}" width="100%"></a>
    49            </div>
    50            <div class="card-footer">
    51                <p>
    52                    タスク : 単純クラス分類<br>
    53                    入力  : 4次元の実数値 <br>
    54                    [sepal length, sepal width, petal length, petal width]<br>
    55                    ラベル : 3クラス <br>
    56                    [iris-setosa, iris-versicolour, iris-virginica]<br>
    57                    データ :150<br>
    58                    特徴  : 簡易・軽量多クラス分類ベンチマーク
    59                </p>
    60                <p>配布元 : <a href="https://archive.ics.uci.edu/ml/datasets/iris">UCI Machine Learning Repository: Iris Data Set</a></p>
    61            </div>
    62        </div>
    63    </div>
    64
    65    <div class="col-md-4">
    66        <div class="card bg-dark text-white">
    67            <div class="card-header">
    68                <a href="/create/wine">UCI Wine Dataset</a>
    69            </div>
    70            <div class="card-body">
    71                <a href="/create/wine"><img src="{{ 'wine.png' | image }}" width="100%"></a>
    72            </div>
    73            <div class="card-footer">
    74                <p>
    75                    タスク : 単純クラス分類<br>
    76                    入力  : 13次元の実数値 <br>
    77                       1) Alcohol <br>
    78                       2) Malic acid <br>
    79                       3) Ash <br>
    80                       4) Alcalinity of ash <br>
    81                       5) Magnesium <br>
    82                       6) Total phenols <br>
    83                       7) Flavanoids <br>
    84                       8) Nonflavanoid phenols <br>
    85                       9) Proanthocyanins <br>
    86                       10)Color intensity <br>
    87                       11)Hue <br>
    88                       12)OD280/OD315 of diluted wines <br>
    89                       13)Proline<br>
    90                    ラベル : 3クラス (品種)<br>
    91                    データ :178<br>
    92                    特徴  : 簡易・軽量多クラス分類ベンチマーク
    93                </p>
    94                <p>配布元 : <a href="https://archive.ics.uci.edu/ml/datasets/wine">UCI Machine Learning Repository: Wine Data Set</a></p>
    95            </div>
    96        </div>
    97    </div>
    98
    99</div>
    100
    101{% endblock %}

    長々としたコードですが、大したことは書いていません。

    最初に見せたトップページのデザインになります。

    ネットワーク作成URLは、http://127.0.0.1:5042/create/mnist といったhttp://127.0.0.1:5042/create/{dataset} とします。

    新たにルーティング

    したがって、「 urls.py 」に新たに、以下を記述しましょう。

    1api.add_route('/create/{dataset}', CreateController)

    そうしたら、controllers.py にclass CreateController を作れば、ルーティング完了です。

    その実装は、次の記事にて!

    第2回へ続く!

    今回から新たに「Responder で機械学習アプリを作る」という短い連載がスタートしました。

    最初に書いたように、「Responder の非同期処理を如何にうまく利用するか」が重要なアプリケーションです。

    筆者も非同期処理には、少し格闘しながら作成したのですが、これがなかなか思うようにいかず…。

    そんな「苦労」と「発見」を読者のみなさまと共有できたらと思っています(笑)

    それでは、第2回でまたお会いしましょう!

    第2回はこちら!

    featureImg2019.11.05【第2回】ResponderとKerasを使って機械学習Webアプリケーションを作ってみた【ネットワーク作成編】第2回~ResponderとKerasで機械学習アプリケーションを作りたい!~この第2回記事は、「Responderと...

    こちらの記事もオススメ!

    featureImg2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...
    featureImg2020.07.28機械学習 特集知識編人工知能・機械学習でよく使われるワード徹底まとめ!機械学習の元祖「パーセプトロン」とは?【人工知能】ニューラルネ...
    featureImg2020.07.30Python 特集実装編※最新記事順Responder + Firestore でモダンかつサーバーレスなブログシステムを作ってみた!P...

    Kerasのオススメ本

    直感 Deep Learning ―Python×Kerasでアイデアを形にするレシピ
    直感 Deep Learning ―Python×Kerasでアイデアを形にするレシピ

     

    広告メディア事業部

    広告メディア事業部

    おすすめ記事