LoginSignup
2
3

More than 3 years have passed since last update.

NNCとPython+Flaskで簡単なディープラーニングWebアプリ

Last updated at Posted at 2021-01-10

Flaskを少しかじって、ごく簡単なWebアプリを作れるようになったので、さっそくディープラーニングを組み込んで遊んでみました。ディープラーニングの部分はNeural Network Console(NNC)を使用します。

利用環境

  • Windows 10 Home 20H2
  • Neural Network Console Windows版 2.0.0
  • Neural Network Libraries 1.15.0
  • Anaconda3-2020.11-Windows-x86_64
  • Flask 1.1.2

環境構築

環境を構築します。試行錯誤しながらやっているので、いくつか手順が抜けてるかもしれませんが、だいたいこんな感じだったと思います。

Neural Network Consoleのインストール

こちらからダウンロードしてインストールしてください。
https://dl.sony.com/ja/app/

Anacondaのインストールと仮想環境構築

Anacondaをインストールし、仮想環境を構築します。具体的な方法は
こちらの記事【初心者向け】AnacondaでPythonの仮想環境を作成・切り替える(多分)最も簡単な方法を参照してください。
Neural Network LibrariesはPython 3.6~3.8に対応しているとのことなので、仮想環境構築時にPythonのバージョンを指定するようにします。

仮想環境にNeural Network Librariesをインストール

Neural Network Librariesのインストール方法は下記ページに記載されています。
https://nnabla.org/ja/install/
といっても難しいものはなく、

> pip install -U nnabla

とするだけです。(GPUを利用するときは設定が異なります)

ただし、これ以外にもモジュールが必要なようです。
https://nnabla.readthedocs.io/en/latest/python/installation.html
によるとscipy等も必要らしいので、あわせてインストールしておきます。

> conda install scipy scikit-image ipython

仮想環境にFlaskをインストール

Flaskもインストールしておきます。

> conda install flask

Neural Network Librariesで推論実行できるようにする

今回は下記のチュートリアルの「2. Python APIを用いて推論を実行する方法」をそのまま利用してみました。使用したプロジェクトは02_binary_cnnという、手書き数字の4と9を識別するCNN(Convolutional Neural Network,畳み込みニューラルネットワーク)です。
チュートリアル:Neural Network Consoleによる学習済みニューラルネットワークのNeural Network Librariesを用いた利用方法2種

チュートリアル通りに作業して、Anacondaの仮想環境でエラーなく実行できれば準備完了です。

Webアプリの作成

準備ができたら、Webアプリを作成していきます。

NNCの推論実行処理

こちらはほぼ上記のチュートリアル通りです。今回画像を扱うので、画像の読み込みと正規化の処理を入れています。
今回は、画像は28×28ピクセルのグレースケールを想定しています。必要に応じて画像のリサイズや減色処理を入れてもいいと思います。

app.py前半
import nnabla as nn
import nnabla.functions as F
import nnabla.parametric_functions as PF

import os
import sys

from PIL import Image
import numpy as np


#----------NNCの処理----------

def network(x, test=False):
    # Input:x -> 1,28,28
    # Convolution -> 16,24,24
    h = PF.convolution(x, 16, (5,5), (0,0), name='Convolution')
    # MaxPooling -> 16,12,12
    h = F.max_pooling(h, (2,2), (2,2))
    # Tanh
    h = F.tanh(h)
    # Convolution_2 -> 8,8,8
    h = PF.convolution(h, 8, (5,5), (0,0), name='Convolution_2')
    # MaxPooling_2 -> 8,4,4
    h = F.max_pooling(h, (2,2), (2,2))
    # Tanh_2
    h = F.tanh(h)
    # Affine -> 10
    h = PF.affine(h, (10,), name='Affine')
    # Tanh_3
    h = F.tanh(h)
    # Affine_2 -> 1
    h = PF.affine(h, (1,), name='Affine_2')
    # Sigmoid
    h = F.sigmoid(h)
    return h

#画像の読み込みと正規化
def normalize_image(save_filepath):
    im_gray = np.array(Image.open(save_filepath)) / 255.0
    return im_gray

def predict(im_gray):
    # load parameters
    nn.load_parameters('./results.nnp')

    # Prepare input variable
    x=nn.Variable((1,1,28,28))

    # Let input data to x.d
    x.d = im_gray
    #x.data.zero()

    # Build network for inference
    y = network(x, test=True)

    # Execute inference
    y.forward()
    print(y.d)
    return y.d

Python+FlaskでWebアプリ作成

FlaskでWebアプリを作ります。digitsPred.htmlに作成したフォーム(後述)から画像を指定してSubmitすると、裏でNNCの推論処理が走って得られた結果をsuccess.htmlで表示します。
今回利用しているNNCのサンプルプロジェクトでは推論結果が0に近ければ"4"、1に近ければ"9"となるように学習されていますので、推論結果が0.5未満であれば"4"、そうでなければ"9"が画像に描かれていたと判定することにします。

app.py後半
from flask import Flask, render_template, request, redirect, url_for
from werkzeug.utils import secure_filename
import os

app = Flask(__name__)

@app.route('/digitsPred', methods=['GET', 'POST'])
def upload():
    # GETの場合
    if request.method == 'GET':
        return render_template('digitsPred.html')
    # POSTの場合
    elif request.method == 'POST':
        #submitされたファイルを取得
        file = request.files['file']
        #安全なファイル名に変換
        save_filename = secure_filename(file.filename)
        #ファイル保存
        save_filepath = os.path.join('./static/image', save_filename)
        file.save(save_filepath)
        #画像ファイルを正規化しndarrayに変換
        im_gray = normalize_image(save_filepath)
        #NNCで推論実行
        pred = predict(im_gray)
        #結果処理
        if pred < 0.5:
            res = 4 #数字の4と判定
        else:
            res = 9 #数字の9と判定
        #結果表示
        return render_template('success.html', save_filename=save_filename, res=res, pred=pred[0][0])

if __name__ == '__main__':
    app.run(debug=True)

この2つのコードを、app.pyという単一のPythonファイルで保存します。
なお、上記の処理で描かれているように、./static/imageフォルダに画像を保管するようになっているので、フォルダを作成しておきます。

HTMLファイルの準備

Pythonファイルがある場所にtemplatesというフォルダを作成し、その中に以下の3つのHTMLファイルを作成します。

  • base.html
  • digitsPred.html
  • success.html

base.html

base.htmlで各HTMLファイルで共通となる部分を作っておき、継承するようにします。

base.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <title>Form Sample</title>
    </head>
    <body>
        {% block content %}
        {% endblock %}
    </body>
</html>

digitsPred.html

このページにフォームを作成し、ファイルをSubmitできるようにします。

digitsPred.html
{% extends "base.html" %}
{% block content %}
<title>深層学習で数字判定</title>
<h1>数字の画像をアップロード</h1>
<p>画像はモノクロで28x28ピクセルにしてください。</p>
<p>現在のところ"4"と"9"の分類のみに対応しています。</p>
<form action="{{url_for('upload')}}" method="POST" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit" value="アップロード">
</form>
{% endblock %}

success.html

このページで推論結果を表示します。NNCの推論結果の生値も出しておくことにします。

success.html
{% extends "base.html" %}
{% block content %}
<title>推論結果</title>
<h1>推論が完了しました</h1>
<p>アップロードされたファイルは {{save_filename}} です。</p>
<h2>画像に書かれている数字は{{res}}です。</h2>
<p>NNCの推論結果は{{pred}}でした。</p>
{% endblock %}

実行結果

app.pyファイルを実行します。たとえばhttp://127.0.0.1:5000/digitsPredにアクセスすると、フォームが表示されます。

image.png

画像を指定して[アップロード]ボタンをクリックすると、こんな感じで結果を表示してくれます。

image.png

※画像ファイルは、NNCのサンプルデータセットに入っているものを使うと簡単です。neural_network_console_200\neural_network_console\samples\sample_dataset\MNIST\validation

参考資料

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3