実践型AIプログラミング特講 最終章その3 #42

実践型AIプログラミング特講 最終章その3 #42

今回は機械学習の中でも実践的にかつ実用性に富んだアプリケーションの具体的な開発に挑戦してみようとおみます。アプリケーションと定義されている通り、皆様が日々使われているアプリケーションと構造は同じもので実際に開発手順も現場とは少し異なりはしますがほとんど同じ工程を本記事で再現したつもりですので、是非ご自身の手でアプリケーションを作成する体験を通してアプリケーションがどのような順序で作成されているのかを感覚でつかんでいきましょう。

機械学習で業務を効率化しよう

Webで使える文章ジャンル判定アプリケーションを作成してみよう

前回の記事にて文章のジャンル判定ツールを作成しました。そこで、そのジャンル判定ツールをWebで使えるように、Web システムに組み込んで使ってみましょう。ここでは、APIを使って連携する方法を紹介します。

機械学習を Web アプリにする方法

機械学習のプログラムも、普通のPython のプログラムです。そのため、必要に応じて起動し、学習を行えば良いでしょう。しかし、1回学習を実行するごとにプロセスを起動し直すのは効率がよくありません。と言うのも、TensorFlow のライブラリーを取り込むだけで、かなり起動に時間がかかってしまうからです。そこで、機械学習を行うシステムを別途サーバー(プロセス)として起動しておいて、Web アプリから機械学習サーバーに問い合わせる形でプログラムを作ります。GUIにはローカルで機能するアプリケーションとwebからサーバーを介して、APIを利用してアプリケーションを実装する方法の二通り存在します。今回はその後者を作成してみようと思います。

▲ Web アプリと機械学習のシステム

ジャンル分けモデルを Web アプリで使おう

先ほど紹介した図では、Web サーバーと機械学習サーバーは異なるサーバーで動かすことを前提としていました。しかし、ポート番号さえ変更すれば、どちらも同じマシン上に存在できます。さらに言えば、大量のアクセスがないことがわかっている場合には、Web サーバーに機械学習のシステムを持たせてしまう方法もあります。今回は、読者の実行環境の利便性を考慮して、もっとも簡易な方法である、Web サーバーに機械学習のシステムを持たせる方法を紹介します。ここでは、次のようにWeb サーバーと機械学習システムを同時に1つのプログラム上に実装してみます。プログラムを作る前に、アプリの仕組みを図で確認してみましょう。

▲今回作るジャンル判定アプリの構造

 

この図にあるように、ユーザーがWeb サーバーにアクセスすると、最初にHIML5/JavaScript がレンダリングされて、フロントエンドとしてインターフェイスが立ち上がります。アプリが実行され、ユーザーがテキストボックスにテキストを記入して、「判定」ボタンをクリックすると、判定結果が表示されるというものを作ってみましょう。

機械学習の機能を持つ Web サーバーの作成

それでは、ジャンル判定を行う APIを含めた、Web サーバー側のプログラムをPython で作ってみましょう。なお『API』というのは、アプリケーションプログラミングインターフェイス(ApplicationProgramming Interface)の略で、外部のアプリケーションなど、使いやすい形で機能を提供するWebサーバーのことです。なお、以下のWeb サーバーでは、前節で手順通りに作成した辞書データと MLP の重みデータ、そしてモジュール「tfidf.py」と「my_text.py」を利用しますので、<genre> ディレクトリーにあるプログラムとデータを同じディレクトリーに配置した上で実行してください。ディレクトリーの理解が浅いとこの辺でデバックとしてエラーを返してしますため、知見が薄い方は各々補填学習をお勧めします。

import json

import flask

from flask import request

import my_text

# ポート番号

TM_PORT_NO == 8888

# HTTP サーバーを起動(*1)

app = flask.Flask(__name__)

print(“http://localhost:” + str(TM_PORT_NO))

# ルートヘアクセスした場合(*2)

Capp.route(‘/’, methods=[‘GET’])

def index():

with open (“index.html”, “rb”) as f:

return f.read ()

# /api ヘアクセスした場合

@app.route(‘/api’, methods= [‘GET’])

def api():

# URL パラメーターを取得(* 3)

q =request.args.get(‘q’,’’)

if q==””:

return ‘{“1abel”:”空です”,”per”:0}’

print(“q=”, q)

# テキストのジャンル判定を行う(*4)

label, per, no = my_text.check_genre (q)

# 結果を JSON で出力

return json.dumps({

“label”: label,

“per”: per,

genre_no”: no

})

if __name__==’__main__’:

# サーバーを起動

app.run(debug=True, host=’0.0.0.0′, port=TM_PORT_NO)

プログラムを実行するのにあたって、Web サーバーを手軽に作成するフレームワーク「Flask」を利用します。以下のコマンドを実行して、Flask をインストールしましょう。こののプログラムは、サーバーとして動かしますので、Jupyter Notebook ではなく、コマンドラインを起動して、以下のコマンドを実行します。

$ python tm_server.py

それから、WebブラウザーのURL 欄へ以下の書式でアクセスしましょう。

[書式]

http://localhost:8888/api?q=(判定したいテキスト)

たとえば、URL 欄に以下のように記述してみましょう。http://localhost:8888/api?q= 野球を観るのは楽しいものです。試合だけでなくインタビューも楽しみです。すると、JSON 形式で以下のような結果が返ってきます。JSON なので日本語がエンコードされてしまっていますがデコードすると「スポーツ」となります。

genre_no”: 0,

“label”: “\u30b9\u30dd\u30fc\u30c4”,

“per”: 0.46637967228889465

}

それでは、プログラムを見てみましょう。基本的には、my_text.pyの check_genre()関数を Webサーバーで提供するようにしただけのものです。Web フレームワークの Flask を使っているので、最低限のコードでHTTP サーバーを実現できます。プログラムの(※1)では、ポート 8888を使って HTTP サーバーを起動するように指定します。もし、別のアプリ(たとえばJupyter Notebook) が8888 番を使っている場合には、別の番号に変更しましょう。プログラムの(※2)の index() 関数では、ルートへのアクセスがあった場合に、「index.html」を返すように指定します。次に、(※3)の部分の api) 関数は、「/api」へのアクセスがあった場合に呼び出されます。ここで、request.args.get()メソッドを呼び出すと、URLのパラメーターを取得できます。(※4)の部分では、モジュール my_text の check_genre() 関数を呼び出し、その結果をJSON 形式で出力します。つまり、このサーバープログラムでは、前節で作った機械学習のプログラムをモジュールとして利用する形です。モジュールを取り込んだ時点で、TensorFlow と Keras が起動され、学習済みの重みデータが読み込まれます。そして、lapi にアクセスがあると、ジャンル判定を行います。

APIを呼び出す Web アプリを作ろう

次に、Web アプリを作りましょう。ここでは、HTML5/JavaScript を利用します。先ほどのtm_server.py と同じディレクトリーに、以下の「index.html」を配置しましよう。

<DOCTYPE html>

<html><meta charset=”utf-8″><body>

<h1> テキストのジャンル判定</h1>

<div>

<textarea id=”q” rows=”10″ cols=”60″></textarea>

<br><button id=”qButton”> 判定</button>

<div id=”result”></div>

</div>

epiiget

<script>

const qs = (q) => document.querySelector(q)

window.onload =() => {

const q = qs(‘#q’)

const qButton = qs(‘#qButton’)

const result = qs (‘#result’)

// 判定ボタンを押した時

qButton.onclick =() => {

result.innerHTML = “…”

// API サーバーに送信する URL を構築(*2)

const api=”/api?q=” +

encodeURIComponent (q.value)

// API にアクセス(*3)

fetch(api).then ( (res) => {

return res.json() // JSON で返す

}).then ((data) => {

// 結果を画面に表示(*4)

result.innerHTML =

data [“label”] +

“<span style=’font-size:0.5em’>(” +

data[“per”] + “)</span>”

})

}

</script>

<style>

#result { padding: 10px; font-size: 2em; color: red; }

#g { background-color: #fffff0; }

</style>

</body></html>

Web ブラウザーで URL「http://ocalhost:8888/」あるいは「http://0.0.0.0:8888/」にアクセスし、適当な文章を書き込んで「判定」ボタンをクリックしてみましょう。HTML5 対応のモダンな Web ブラウザーであれば動かすことができます。

短い文章では、正しいジャンルを判定できないこともありましたが、長めの文章であれば、だいたい正しいジャンルを得ることができました。それでは、プログラムを確認してみましょう。ボタンが押されたら、テキストボックスに書かれているテキストを API サーバーに送信し、JSON で結果を得て、それを HTML に表示するようにしてみましょう。プログラムの(※1)では、判定ボタンをクリックしたときの動作を指定します。(※2)の部分では、API サーバーに送信するURL を構築します。(※3)の部分で fetch を利用して、サーバーにアクセスします。結果を得たら、(※4)の部分でHTML として表示します。

フィードバックと発展内容

さて、本節ではプログラムの簡易性のために、Web サーバーと機械学習のシステムを1つのプログラムのなかに収めてしまいました。しかし、実務でシステムを利用することを考慮すると、Web サーバーと機械学習の応答を返す APIを分離させると良いでしょう。プログラム的には、それほど違いはないことでしょう。また、今回、学習済みのデータを読み込んで使う方法を紹介しましたが、実際に業務で利用する場合では、日々更新される業務データベースから、定期的に学習データを読み出して、学習データを更新することもできるでしょう。次のコラムが参考になります。

補足事項

Web サービスにおける学習データの定期的なメンテナンス

Web サービスの運営において、機械学習を応用したシステムを組み込んでいる事例は、すでにたくさんあります。利用事例として、フリマアプリの「メルカリ」では、商品出品時の価格推定や、商品タグ、カテゴリーのサジェストを行っているそうです。また、料理レシピのコミュニティーサイトの「クックパッド」では、レシピの分類やスマートフォンに保存されている写真のなかから、料理の写真だけを抽出する機能などに利用しているそうです。このように、多くのWeb サービスで機械学習システムを導入していますが、そのシステムを活用する上で一番難しいところが「一度作って終わりではない」という点にあります。と言うのも、日々、新しい投稿が行われ、分類精度が低下してしまうからです。流行語や新製品など、正解データは常に変化していきます。そのため、定期的に教師データを新しくして、学習をやり直す必要があります。次の図を見てみましょう。Web サービスでは多くの投稿が行われ、それがデータベースに保存されます。そのデータベースに蓄積されたデータを用いて、機械学習システムを構築します。それによって、機械学習システムが Web サービスでユーザーの投稿を支援します。そして、そのことにより、ユーザーがさらに多くの投稿をし、それらがデータベースに蓄積されていきます。そうした蓄積されたデータを機械学習に応用すると高い精度で投稿を支援できます。

▲webサービスでは繰り返し学習を行う必要がある

多くのWeb サービスでは、こうしたフローが自動で行われるようになっていますが、これから構築するサービスでも、なるべく人手をかけず、自動的にこのフローが回るようなシステムを構築するのが良いでしょう。ただし、何かしらのきっかけで急に判定精度が悪くなる可能性もあります。精度が落ちたら通知が来るようにするなど、自動化の落とし穴を避ける仕組みも組み込むと良いでしょう。

総括

・学習済みのデータを保存しておいて、業務システムから読み込んで使うと効率が良い

・Flask を利用して、Python を利用した機械学習システムを持つ Web サーバーを作成した

・機械学習システムをWeb アプリに組み込むのはそれほど難しくない

・機械学習システムの入出力をWeb API として利用できるように作っておくと便利

いかがでしたか。アプリケーションを作成するにあたり、いつもとは全くかってが異なり面を食らった方も少なくはないのではないでしょうか。かくいう私も実務経験を積んだ当初は皆様と同じ気持ちで、培ってきた知識では全く歯が立ちませんでした。しかし、無理矢理にでも経験を積むことで少しずつ作成の手順が感覚で理解できるようになり今では趣味でアプリケーションを作成したり、フリーランスとして案件を受注できるまでに成長することができました。つまづき、匙を投げ出したくなることは多々あるとはおみますがその都度、先々自分の成功した姿を想像して常に前向きに取り組んでいただけると幸いです。

次回の記事リンク

プログラミングカテゴリの最新記事