HIROBIRO

HIROBIRO

精神的自由を目指すブログ。最近はプログラミングの記事多め。

【6章前半・応用編】PythonによるAI・機械学習・深層学習アプリのつくり方

「PythonによるAI・機械学習・深層学習アプリのつくり方」の第6章についてまとめます。

この章は本の最終章なのですが、応用編として機械学習をWebアプリや業務システムに組み込む方法について紹介されています。

 

はじめに

この本に載っているコードは全てgithubで公開されているため、この記事では具体的なコードは書きません。以下を参照してください。
https://github.com/kujirahand/book-mlearn-gyomu


私はこの本を最初から取り組みましたが、第4章以降から苦労したため内容をまとめることにしました。

第4章については以下の記事でまとめています。

www.hirobiro-life.com


ちなみに第5章は飛ばしています。

内容はTensorFlowの基本的な説明と、第3章までに行っているアヤメの分類・手書き数字や文字の判定・写真に写った物体の認識をTensorFlowで行っています。
 

TensorFlowの導入について

TensorFlowの導入に苦労したのでそこだけ少し解説します。
私は以下の環境にしています。


ホストPC:Windows10 Home 64bit 
開発環境:CentOS7 (VirtualBox & Vagrant)
 

なぜこうしたかと言うと、以前Web開発を勉強するためにドットインストールの「ローカル開発環境の構築 [Windows編] 」の動画を見て参考にしたからです。この動画は無料で公開されているのでおすすめです。


・ローカル開発環境の構築 [Windows編]
https://dotinstall.com/lessons/basic_localdev_win_v2


この動画内ではCentOS 6.8を使用していましたが、そのままTensorFlowを入れようとするとエラーになりました。

$ pip install --upgrade tensorflow==1.5.0

↓ 以下のエラー発生
`GLIBC_2.17' not found


原因を調べたところ、CentOS 6.8ではglibcのバージョンが2.12止まりになってしまうそうです。
CentOS 7.2を入れるとglibc 2.17のインストールが可能になり、無事にTensorFlowが入りました。

6-1 業務システムへ機械学習を導入しよう

この章までの内容では機械学習したあとにすぐ判定処理を実施していました。
実際の業務システムでは時間のかかる機械学習は夜間処理で行い、学習済みデータを生成しておきます。
こうすることで必要なときにWebアプリなどから判定用プログラムを呼び出し、そこから学習済みデータを読み込んですぐさま判定結果を返すことができます。
また利用するデータについてですが、データベース(RDBMS)の活用の仕方についても書かれています。


第6章で学ぶ内容は以下の3つです。


・学習済みデータの保存と読み込み方法
 (判定用プログラムと機械学習プログラムの分離も含む)


・判定用プログラムをWebアプリから利用する方法


・学習用データとして、データベース(RDBMS)を利用する方法


6-2 学習モデルの保存と読み込みについて

上でも書きましたが、ディープラーニングを行う場合、学習には何時間もかかることが多いです。
そのため毎回プログラムを起動するたびにデータの学習から始めていてはレスポンスに時間がかかりすぎてしまいます。


そこで、あらかじめ夜間処理などで学習済みデータを保存しておき、プログラム起動時に学習済みデータを読み込んで判定します。
この節ではscikit-learnのサンプルデータを用いて、学習済みデータを保存するプログラムと読み込んで判定するプログラムを分離した例が紹介されています。

6-3 ニュース記事を自動でジャンル分けしよう

大量のニュース記事とそれがどのジャンルなのかの情報を教師データとして与え、機械学習を利用して未知の文章のジャンル判定を行います。


第4章でも行いましたが、文章を判定するためにベクトルデータへの変換を行います。
ここでは「TF-IDF」と呼ばれるツールを利用します。


TF-IDFの特徴


・文章を数値ベクトルに変換


・各文章ごとの単語の出現頻度に加えて、学習させる文章全体における単語の出現頻度を考慮


・文章内における特徴的な単語を見つけることを重視


本書325ページのtfidf.pyを実行すると、TF-IDFのテストが行えます。
このプログラムではlivedoorコーパスの記事データの文章から単語(名詞、動詞、形容詞)を抽出し、それぞれの単語にIDを振っています。
そして入力された文を構成する各単語の出現頻度と重要度を掛け合わせた値を確認できます。


ちなみに私は勉強だと思って全てのコードを手打ちで入力しましたが、しょーもない入力ミスのせいで変な出力が出てしまい、原因追及に苦労しました。
手打ち練習もいいですが、変な結果がでるときはgithubからコピペしてみましょう。

tfidf.pyの修正点

7行目の以下のコードはmecab-ipadic-neologdの場所を指定する必要があります。
自分の環境にあった場所に書き換えて下さい。

tagger = MeCab.Tagger("-d /var/lib/mecab/dic/mecab-ipadic-neologd")


mecab-ipadic-neologdの場所は以下のコードで調べられます。

$ find / -type d -name mecab-ipadic-neologd

/var/tmp/mecab-ipadic-neologd
/usr/lib64/mecab/dic/mecab-ipadic-neologd


私の場合、7行目を以下に書き換えました。

tagger = MeCab.Tagger("-d /usr/lib64/mecab/dic/mecab-ipadic-neologd")
使用するデータ

次に文章判定に利用するデータですが、livedoorコーパスを利用します。
ジャンル(提供媒体)ごとに分類されたニュース記事が用意されています。
以下のリンク先からアクセスできます。
https://www.rondhuit.com/download.html#ldcc


livedoorコーパスから記事をダウンロードした記事のうち、以下の4種類の媒体の記事を利用します。
そして文章を「スポーツ」「IT」「映画」「ライフ」の4カテゴリのいづれかに分類します。


・Sports Watch (ジャンル:スポーツ)


・ITライフハック (ジャンル:IT)


・MOVIE ENTER (ジャンル:映画)


・独女通信 (ジャンル:ライフ)


330ページのmakedb_tfid.pyで4ジャンルのファイルを読み込み、文章をTF-IDFベクトルに変換し、genre.pickleというファイルへデータを保存します。


このデータを使って学習を行います。
分類器のアルゴリズムをナイーブベイズにすると92%の精度(train_db.pyを実行)、TensorFlow+Kerasによる深層学習のMLPを利用すると98%以上の精度(train_mlp.py)になります。

train_mlp.pyの修正点

train_mlp.pyの最後のコードではplt.show()で学習の様子をグラフ描画しています。
しかしjupyter notebookを使わず、CUI環境でコードを実行した場合は画像表示できません。
この場合、以下のコードにすることで画像を保存することで、確認可能です。
ちなみに画像の拡張子にjpgは使えません。

# CUI環境では画像表示できない
# plt.show()

# 画像保存
plt.savefig('fig.png')
ジャンル別に分類

学習が済んだので、今度は独自のテキストを指定してジャンル別に分類します。
まずは本書内で例として取り上げられている文章で実行します。
実行するプログラムはmy_text.pyです。


f:id:hirokun1735:20181124235636j:plain



結果は以下のようになり、ちゃんと分類できています。


f:id:hirokun1735:20181125000301j:plain


では次にもっと紛らわしい文章で試してみます。


f:id:hirokun1735:20181125001420j:plain


一つ目の文章は「日経xTECH」から取ってきたIT系の記事です。
ここまできた!プロ野球のデジタル革命 | 日経 xTECH(クロステック)


二つ目の文章は「セキララ ゼクシィ」から取ってきたライフ系の記事です。
結婚相手に「IT男子」がおすすめな理由は?-セキララ★ゼクシィ


その結果は以下のようになりました。


f:id:hirokun1735:20181125001850j:plain


なんとどちらも99%以上の精度で正解しています。
正直あまり期待していなかったのでこれは驚きました。

my_text.pyの修正点

my_text.pyを最初に実行したとき、以下のエラーが発生しました。

ValueError: Dimension 0 in both shapes must be equal, but are 52800 and 52955. 
Shapes are [52800,512] and [52955,512]. for 'Assign' (op: 'Assign') with input shapes: [52800,512], [52955,512].


これはKerasのモデル定義において入力データの形式が異なることが原因です。
tfidf.pyのプログラムにてlivedoorコーパスの記事データの文章から単語(名詞、動詞、形容詞)を抽出し、それぞれの単語にIDを振っています。
ここで抽出された単語のID数が52955であるのに対し、my_text.pyで定義している入力データは52800と設定されていることがエラーの原因です。

# my_text.py 29行目を修正
model.add(Dense(512, activation='relu', input_shape=(52955,)))


修正して再度実行すると、今度は以下のエラーが発生しました。

Exception ignored in: <bound method BaseSession.__del__ of <tensorflow.python.client.session.Session object at 0x7f854fe74940>>
Traceback (most recent call last):
  File "/home/vagrant/.pyenv/versions/anaconda3-5.0.0/envs/py35/lib/python3.5/site-packages/tensorflow/python/client/session.py", line 702, in __del__
TypeError: 'NoneType' object is not callable


原因を調べると、以下のページにたどり着きました。
www.codelab.jp


このページを参考にして以下のコードを入れるとエラーが直りました。

#バックエンドをインポート
from keras.backend import tensorflow_backend as backend

#処理終了時に下記をコール
backend.clear_session()


少し長くなってしまったので、後半に続きます。

まとめ

第6章では機械学習をWebアプリや業務システムに組み込む方法について紹介されています。
前半では学習済みデータの保存と読み込み方法を紹介しています。
例としてニュース記事のジャンル分けを行っていますが、意外と精度の良い結果が出ています。


第6章後半の内容は以下の記事にまとめました。
www.hirobiro-life.com



すぐに使える! 業務で実践できる! Pythonによる AI・機械学習・深層学習アプリのつくり方