Python AI/人工知能サンプルコード:機械学習プログラム(自作)で工数を見積りしてみた【ラズパイ,ディープラーニング】

AI(ディープラーニング)について、色々活用できないか日々勉強、模索中です。

これまで、関連書籍の紹介やAIの概観、歴史について記事を書いてきましたが、今回は具体的かつ実践的なテーマになります。拙作ではありますが、自作のAIプログラムも公開します!

背景:検証テストの消化日数をAIで簡単に試算できないか?


以前にあげたAppiumKatalon Studioの記事でも触れましたが、スマホアプリの検証テスト作業が開発現場で行われています。ここで、テストに限らずどんな業務でもそうですが、「今のチームでこの作業にかかる所要時間(工数・日数)はどれくらいか?」という「見積もり」は常に付きまとう話だとは思います。

そこでふと思ったのが、「もしかしてそれ、AIで楽に見積もりできるのではないか?」なと。

AIの代表的な使い方の一つに予測(回帰問題)というものがあります。明日の株価とかを予測したりとかですね。知りたいデータ(目的変数)と、それと何らかの因果関係がみられるパラメータ(説明変数)について十分な過去データがあれば、任意の説明変数の値から目的変数を割り出して、知りたいことが予測できるというものです。

今回のテスト作業の例でいえば、テストの工数(消化日数)は大体テスト項目数に依存(比例)するので、

・説明変数(入力変数): テスト項目数 [個]
・目的変数(出力変数): テスト消化日数 [日]

のように入出力の仕様を決めて、AI(ディープニューラルネットワーク)プログラムをPythonで自作してみました。GitHub上でサンプルを公開します。

開発環境


以前にも紹介しましたが、AI勉強用に使っているRaspberry Pi(ラズパイ)上で、Python・Kerasを用いて開発しました。

■ハードウェア

・Raspberry Pi 3 Model B


■OS

・Raspbian GNU/Linux 9.11 (stretch)


■プログラミング言語、主なライブラリ

・Python 2.7.13
・Keras 2.1.5
・numpy 1.12.1
・theano 1.0.1
・matplotlib 2.0.0
・pandas 0.19.2


Raspberry Pi でAI環境を開発する際には、↓の書籍が参考になります。



ディープラーニングに関する仕様


■学習データ

先に示した、以下の入出力データ仕様

・説明変数(入力変数): テスト項目数[個]
・目的変数(出力変数): テスト消化日数[日]

に基づく、csvファイルを準備します。以下のようなイメージです。

----------------------------------------
テスト項目数,消化所要日数
100,1
200,2
300,3
400,4
500,5
……
----------------------------------------

もちろん↑はあくまで今回の一例なので、テスト項目-消化所要日数の以外のデータでもOKです!


■構成するディープニューラルネットワーク

全結合層による4層ニューラルネットワーク。主なハイパーパラメータは以下の通りです。

----------------------------------------
・入力層
 -層数: 1層
 -ニューロン数(入力数): 1個

・中間層
 -層数:2層
 -ニューロン数: 3個
 -活性化関数: relu関数

・出力層:
 -層数: 1層
 -ニューロン数(出力数): 1個
 -活性化関数: 恒等関数

・その他
 -ネットワークタイプ: 回帰問題学習、予測型
 -バッチサイズ: 8
 -エポック数: 2000回
 -損失関数: 平均二乗誤差
 -最適化アルゴリズム: adam
----------------------------------------

活性化関数、最適化アルゴリズム、損失関数、エポック数などの専門用語が出てきますが、このあたりの概念の話については、以下の本が参考になります。


プログラム


GitHubにサンプルプログラムを公開します。

https://github.com/kotetsu99/deep_regression


■各プログラムの説明

・deep_regression_train.py: 学習プログラム
 -学習用データセットファイルを読み込んで予測モデルを作成する
 -エポック数に対する損失関数の値変化のグラフを出力する

・deep_regression_predict.py: 予測プログラム
 -予測モデルと説明変数(テスト項目数)を引数とし、テスト消化の所要日数の予測値を返す

・deep_regression_plot.py: データプロットプログラム
 -テスト項目数のベクトルを読み込んで、テスト項目数-予測消化日数をグラフを出力する
 -プロットしたデータのcsvファイルを出力する

・dataset/train.csv
 -学習用データセットのサンプル
 -1列目がテスト項目数、2列目が消化日数
 ※開発現場での実績を元にしたわけではなく、適当なサンプルです。

・dataset/plot.csv
 -データプロット用のテスト項目数データ


■プログラムの使用イメージ

以下のようなイメージで学習、予測を実行します。

----------------------------------------

【学習】
python deep_regression_train.py 予測モデル.h5

【予測】
python deep_regression_predict.py 予測モデル.h5 テスト項目数
ディープラーニングによる予測消化日数
=〇〇 [日]

【プロット】
python deep_regression_plot.py 予測モデル.h5 dataset/plot.csv

----------------------------------------


テスト項目数と消化日数実績値のデータセットを学習。予測モデルを生成。
次に予測モデルとテスト項目数を引数として、見積もりを返すという流れです。
# なんか、Googleでキーワード検索すると関連ページが出てくるような感じ?

テスト項目数を変化させた時の予測消化日数を、グラフとしてプロットさせることもできます。

プログラム説明


ソースコードすべてに関しての詳細な説明は割愛しますが、重要な箇所のみ取り上げます。

■deep_regression_train.py

 15 # バッチサイズ設定
 16 n_bs = 8
 17 # 中間層ニューロン数設定
 18 n_units = 3
 19 # ドロップアウト率
 20 #r_dropout = 0.05
 21 # エポック数
 22 nb_epochs = 2000
 23 # csvファイルパス取得
 24 csvfile = 'dataset/train.csv'

中間ニューロン数などのハイパーパラメータに関する設定を記述しています。値は任意に変更可能です。過学習対策のドロップアウトに関する設定もありますが、今回は簡単のため不使用としています。学習に使用するcsvファイルのパスもここで定義しています。


 86 def dnn_model_maker(n_features, n_outputs):
 87     # 4層ニューラルネットワークを定義
 88     model = Sequential()
 89     # 中間層1(ニューロン=units個)と入力層を定義
 90     model.add(Dense(units=n_units, activation='relu', input_shape=(n_feature    s,)))
 91     # Dropout層を定義
 92     #model.add(Dropout(r_dropout))
 93     # 中間層2(ニューロン=n_units個)を定義
 94     model.add(Dense(units=n_units, activation='relu'))
 95     # Dropout層を定義
 96     #model.add(Dropout(r_dropout))
 97     # 出力層を定義(ニューロン数は1個)
 98     model.add(Dense(units=n_outputs, activation='linear'))
 99     # 回帰学習モデル作成
100     model.compile(loss='mean_squared_error', optimizer='adam')
101     # モデルを返す
102     return model


先述した、4層ニューラルネットワークを作成しているのが、この関数です。kerasで定義されているmodelクラスとその関数を使って、ニューラルネットワークを組み上げているわけですが、ここで中間層1,中間層2の全結合層「Dense」のニューロン数をunits=n_unitsで定義しています。ドロップアウト層は記述していますが簡単のため無効化しています。

Kerasによるニューラルネットワーク実装は以下の書籍が参考になります。

必要な数学だけでわかる ディープラーニングの理論と実装
秀和システム (2019-06-05)
売り上げランキング: 169,082

他にも、データ前処理(正規化・標準化)処理を実装していますが、これについては次の記事で解説していますので、参考にされてください。https://nine-num-98.blogspot.com/2019/12/ai-normalization.html


■deep_regression_predict.py

 43     # 予測結果の取得
 44     result = dnn_model.predict_on_batch(X)

予測プログラムの中で、AIに予測させ結果を得ているのが、この箇所です。kerasのmodelクラス内で定義されている関数の中に、predict_on_batchというものがあります。kerasのマニュアルでは、「サンプルの単一バッチに関する予測を返します.」とありますが、ここの場合だと、テスト項目数1つを入力とし、その予測結果を1つ返すというものです。


■deep_regression_plot.py

 50     # 予測結果の取得
 51     result = dnn_model.predict(X)

一方で、こちらの方で使用しているpredict関数では、複数のテスト項目数の入力に対する予測結果を返すことができます。グラフでいえば、X軸データ(テスト項目数)に対するY軸データ(消化商用日数)をここで一括で作っています。

実行結果


実際に実行してみた結果を記します。


■学習

$ python deep_regression_train.py model/model_2x3.h5
Using Theano backend.
モデル新規作成
Train on 90 samples, validate on 10 samples
Epoch 1/2000
…
Epoch 2000/2000

学習プログラムを実行。学習モデルの保存先ファイルパスを引数に設定したうえで実行します。同名の学習モデルがある場合は、それを読み込んでさらに学習を進ませる(再学習)させることができます。

学習が完了した後、モデルファイルの他、エポック数に対する損失関数の値をプロットしたグラフを出力します。

・train_figure.png



loss(学習データに対する損失関数)、val_loss(評価データに対する損失関数)をそれぞれ示しています。loss、val_lossともにエポックが進むにつれ順調に下がっています。過学習も特におきていません。


■予測

$ python deep_regression_predict.py model/model_2x3.h5 10000
Using Theano backend.
ディープラーニングによる予測消化日数
=82.5613 [日]

学習済モデルを使って予測を行いました。テスト項目10000個の消化にかかる日数を試算したところ、82.5613日かかる見込みです。次のプロットで示しますが、学習に使ったサンプルデータとほぼ同じ値です。現実として83日近くもテストに工数かけすぎな印象ですがw まあ1日100項目消化としたら、単純計算で100日かかるのでこんなものかなと。


■プロット

$ python deep_regression_plot.py model/model_2x3.h5 dataset/plot.csv
Using Theano backend.

テスト項目数に対する予測消化日数をプロットしたグラフ、およびそのデータのcsvファイルを出力。

以下の2つのファイルが生成されます。

・result_figure.png
・result.csv

グラフのresult_figure.pngを示します。




trainが学習データ、predictが予測データを示しています。

完全ではありませんが、実績データ(学習データ)に迫る予測値を出していることが分かります。今回は中間層2、ニューロン数3で試しましたが、これらの数を増やせば、もっと実績値に近づきそうなのは、直感的に分かると思います。
# ただし、計算規模が大きくなるため、所要学習時間、所要予測計算時間がその分かかってしまいます。

ニューロン数を10、20に変更したモデルの予測プロットを以下に示します。


・ニューロン数=10


・ニューロン数=20



ニューロン数が増えるにつれて、元の学習データの形にどんどん近づいていくのが分かります。ニューロン数=20ではほぼ同じプロットを示していますね。

ちょっと堅い話になりますが、一般的にニューロンの数(または中間層の数)を増やせば増やすほどニューラルネットワーク出力の表現度が向上します。理論的にはどんな複雑な関数も表現でき、これは専門用語で普遍性定理と呼ばれています。
relu関数のような非線形関数を多数重ね合わせると、色んな形の関数を作れるというものです。自分も大学数学で学びましたが、三角関数の集合で任意の周期関数を表現する、フーリエ級数と似たような話ですね。

これはつまり、「ある予測したい事象Aと、それに何らかの関係を持つ事象Bとの間にある、どんな相関関係も表現できる」ということです。この普遍性定理が、バックプロパゲーションと並ぶAI(ディープラーニング)の予測精度や認識能力の高さの源泉なのですが、これが実用レベルで使えてきた背景には、

・コンピュータ能力(特にGPU)の飛躍的な向上により莫大な計算量を処理可能となったこと
・学習に必要な大量かつ多種のデータ(ビッグデータ)を収集可能な環境が、ネットワーク性能の向上、クラウドの発達により整ったこと

にあります。

今後、スパコンを超える量子コンピュータや新世代インフラである5Gの登場などで、AIの能力はさらに発展し活躍の場が増えていくと思われます。シンギュラリティは2045年と言われますが、最近の量子コンピュータ研究の進展を見ると、案外2030年くらいに前倒しされるかもしれませんね。

【2019/12/12 追記】
サンプルプログラムの補足説明の記事をアップしました。
AIのデータ前処理(正規化・標準化)方法と実装サンプルプログラム【機械学習・ディープラーニング】 | 9が好きな人のブログ

サンプルプログラムに記述してある学習データの前処理関連について、取り上げています。参考になれば幸いです。

スポンサーリンク