最近ブームのAI(機械学習)に手を出しました。まずは、決定木(Decision Tree)というモデルを使って「ソムリAI(ワインソムリエAI)」を作ってみようと思います。
「機械学習といえばPython」と聞いたことがあったので、ググってみました。
ざっくり言うとPythonとは「Googleなど様々な組織・個人が公開しているライブラリを使うことでイケてる機能を少ないコードで実現できるプログラミング言語」であり、「Anacondaという無料の開発環境が使いやすい」ということでした(PythonもAnacondaもどっちもヘビですね 笑)。ということで、早速PythonとAnacondaをインストールします。Python・Anacondaや各種ライブラリのインストールについてはスクリーンショット付で紹介しているブログが色々あるので、興味のある方はそちらを参考にしていただければと思います(Pythonはversion.3.6を入れるのがよいみたいです)。
【 ワインデータのリンク】 UCI( University of California, Irvine: カリフォルニア大学アーバイン校)
http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv
データの中身はこんな感じで、「酒石酸」から「アルコール度数」までの項目を使って、右端の「評価」をソムリエのごとく算出するモデル(数式)を作って、モデルの妥当性を検証してみようと思います。ちなみに、ダウンロードしたデータはタイトルが英語だったので分かりやすいように日本語化しています(酒石酸とはワインに多く含まれる有機化合物だそうです)。
機械学習のモデルは決定木・ロジスティック回帰・ニューラルネットワークなどいくつかあるのですが、まずは決定木でやってみようと思います。
Source:
まずはUCIからダウンロードした赤ワインリストのデータを読み込んで、ちゃんと読めているか表示してみます。エディタにパチパチ入力して、Shift+Enterで実行します。処理単位ごとに動作確認しながら作業できるのが便利なのです。
今回は元データの70%をモデルを作るためのデータ(訓練データ)・残りの30%をモデルを検証するためのデータ(検証データ)にしました。なんと、ライブラリを使って1行のコードで分割できてしまうのです。
初回の機械学習では訓練データの約57%・検証用データの約51%を正しく分類できたということになります。半分以上は当たっているものの、もうちょっと改善の余地があるかもしれません。
階層を増やすにつれて訓練データの精度は右肩上がりの一方で、検証データの精度は4階層くらいで頭打ちになりました。これは「過学習(Over-fitting)」と呼ばれるもので、モデルが訓練データに最適化され過ぎた状態を表しています。つまり、階層が増えるほど「訓練データを正確に分類できるモデル」にはなったものの、「検証用データではパフォーマンスが出ないモデル」であるということです。「訓練データに個別最適され過ぎたモデル」とも言えます。
ソムリAI的には4階層くらいが最適のようです。約60%の精度であり、まずまずかなという感じです。
例えば、下の画像は決定木の可視化部分を書いていたときのデバッグ画面(うまく動かなくてエラーが出ている画面)です。上の「import」の部分はライブラリの呼び出しで、実際の処理は最後の2行だけです。下のデバッグ画面を見るとエラーは僕が書いたコードの7行目から自動生成されたコードの427行目で発生しています(---->が付いている箇所)。たった2行のコードから400行以上のコードが自動生成されていることになります。レガシー領域のSEとしては驚きなのです。
今回使っている機械学習のライブラリには決定木以外にも、ロジスティック回帰やニューラルネットワークなど複数の機械学習のモデルが入っているようなので、様々なモデルでソムリAIを作って精度を比較検証してみようと思います。専門家から見たら「縄文人が土器作って喜んでいるレベル」なのでしょうが、縄文人なりにいろいろな土器を作ってみようと思います。
AI(機械学習に手を出したきっかけ)
僕の本業はITですが、今話題のIoT・AI・ブロックチェーンのような「デジタル領域」にはとんと無縁で、「レガシー領域」「トラディショナル領域」と呼ばれる金融機関の基幹系システムの経験しかないのです。自分の幅出しのためにAI(機械学習)に手を出してみました。自分への備忘とスキルの棚卸を兼ねて夜な夜なやっていることをまとめてみようと思います。(と向学心あふれる感じで書いていますが、「現状のスキルセットだと定年まで逃げ切れないな」という後ろ向きな気持ちで始めたのが実態です)「機械学習といえばPython」と聞いたことがあったので、ググってみました。
ざっくり言うとPythonとは「Googleなど様々な組織・個人が公開しているライブラリを使うことでイケてる機能を少ないコードで実現できるプログラミング言語」であり、「Anacondaという無料の開発環境が使いやすい」ということでした(PythonもAnacondaもどっちもヘビですね 笑)。ということで、早速PythonとAnacondaをインストールします。Python・Anacondaや各種ライブラリのインストールについてはスクリーンショット付で紹介しているブログが色々あるので、興味のある方はそちらを参考にしていただければと思います(Pythonはversion.3.6を入れるのがよいみたいです)。
ソムリAIを作る(ワインソムリエAI)
機械学習のお題ですが、参考にしたサイトに「UCIのサイトに赤ワイン1600本分のデータが転がっている」と書いてあったので、それを使ってワイン評価を行う「ソムリAI(ソムリエ+AI)」を作ることにしました。http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv
データの中身はこんな感じで、「酒石酸」から「アルコール度数」までの項目を使って、右端の「評価」をソムリエのごとく算出するモデル(数式)を作って、モデルの妥当性を検証してみようと思います。ちなみに、ダウンロードしたデータはタイトルが英語だったので分かりやすいように日本語化しています(酒石酸とはワインに多く含まれる有機化合物だそうです)。
機械学習のモデルは決定木・ロジスティック回帰・ニューラルネットワークなどいくつかあるのですが、まずは決定木でやってみようと思います。
決定木(Decision Tree)とは?
決定木(Decision Tree)とは「条件を使って段階的にデータを分類するモデル」です。樹形図のイメージに近いです。こんなイメージです。Source:
ソムリAI(決定木版)を作ってみる
Step 1: ワインデータを読み込む
早速AnacondaのJupyterというPythonのエディタを起動してやってみようと思います。まずはUCIからダウンロードした赤ワインリストのデータを読み込んで、ちゃんと読めているか表示してみます。エディタにパチパチ入力して、Shift+Enterで実行します。処理単位ごとに動作確認しながら作業できるのが便利なのです。
#入力データセットを読み込み import pandas asうまく表示されました!pd #データハンドリング用ライブラリ呼び出し data =pd . read_csv( 'winequality -red. csv ', encoding='SHIFT-JIS') data. head( ) #先頭5つを表示して読み込まれていることを確認
Step 2: 機械学習用データを用意する
機械学習では「モデル作成に使うインプットデータ」と「モデルを検証するための解答データ」の2つを用意します。統計で言うところの「説明変数」と「目的変数」の関係です。今回の例であれば、「酒石酸」から「アルコール度数」までのデータがインプットデータで「評価」が解答データです。#機械学習で求める解である「評価」以外の項目をdata_Xに、「評価」をdata_Yに格納 data_X = data.copy() del data_X['評価'] data_Y = data['評価'] data_X.head() #評価欄がないことを表示して確認 data_Y.head() #評価欄のみであることを表示して確認インプットデータを表示。「評価」欄が入っていないのでOK!
Step 3: 機械学習用データをモデル構築用・検証用に分ける
データが用意できたので決定木の予測モデルを作って、その精度を検証しようと思います。そのためには元のデータを「モデルを作るためのデータ」と「モデルを検証するためのデータ」に分ける必要があります。訓練データを使ってモデルを構築し、そのモデルを検証データに適用して妥当性を検証するのです。訓練データは教師データとも呼ばれます。今回は元データの70%をモデルを作るためのデータ(訓練データ)・残りの30%をモデルを検証するためのデータ(検証データ)にしました。なんと、ライブラリを使って1行のコードで分割できてしまうのです。
#入力データセットの70%を訓練データ・30%を検証データに分割 from sklearn.model_selection import train_test_split #機械学習用ライブラリ呼び出し X_train, X_test, Y_train, Y_test = train_test_split(data_X, data_Y,random_state=0, test_size=0.3) print(len(X_train)) #訓練用のデータ数を表示(70%) print(len(X_test)) #検証用のデータ数を表示(30%)訓練データと検証用データが7:3くらいの件数になっていることを確認!
Step 4: 決定木を使って機械学習させてみよう
いよいよ決定木のモデル作りとモデルの検証です。こちらもライブラリを使って少ないコードで実現できます。コードの2行目でモデルを定義して、3行目で機械学習を行っています。たった2行なのです!「max_depth」という項目で決定木の階層を指定しています。とりあえず何も考えずに3階層でモデルを作ってみようと思います。また、5行目・6行目では生成されたモデルの訓練データ・検証データそれぞれの精度を表示しています。#決定木の機械学習 from sklearn.tree import DecisionTreeClassifier #機械学習用ライブラリから決定木を呼び出し treeModel = DecisionTreeClassifier(max_depth=5, random_state=0) #決定木モデルの定義 treeModel.fit(X_train, Y_train) #機械学習実行(訓練用データを使ったモデル生成) from sklearn import metrics print(metrics.accuracy_score(Y_train, treeModel.predict(X_train))) #訓練データの精度表示(訓練データ用のモデルでどの程度訓練用データの「評価」を当てられるか) print(metrics.accuracy_score(Y_test, treeModel.predict(X_test))) #検証用データの精度表示(訓練データ用のモデルでどの程度検証用データの「評価」を当てられるか)
初回の機械学習では訓練データの約57%・検証用データの約51%を正しく分類できたということになります。半分以上は当たっているものの、もうちょっと改善の余地があるかもしれません。
Step 5: モデルを最適化する
決定木は木の階層によって精度が変わります。コード2行目の「max_depth」をいじって試してみます。階層を2~10で実験した結果のまとめが下のグラフです。階層を増やすにつれて訓練データの精度は右肩上がりの一方で、検証データの精度は4階層くらいで頭打ちになりました。これは「過学習(Over-fitting)」と呼ばれるもので、モデルが訓練データに最適化され過ぎた状態を表しています。つまり、階層が増えるほど「訓練データを正確に分類できるモデル」にはなったものの、「検証用データではパフォーマンスが出ないモデル」であるということです。「訓練データに個別最適され過ぎたモデル」とも言えます。
ソムリAI的には4階層くらいが最適のようです。約60%の精度であり、まずまずかなという感じです。
Step 6: モデルのカギとなる項目を見つける
モデルの最適化はそれなりにできましたが、モデルの中身がブラックボックス状態です。そのため、インプットデータのどの項目が重要なのかを明らかにしようと思います。こちらもライブラリで用意されている機能に今回作ったモデルを放り込むだけで簡単に分かります。数字が大きいほど重要度が高いことを示しており、今回のモデルでは「アルコール度数」「硫化カリウム密度」「総二酸化硫黄濃度」「酢酸濃度」あたりが重要と位置づけられています。#モデルの決定係数を表示(入力データの各項目に対する重みを表示) Importance=pd.DataFrame({'変数名':data_X.columns,'重要度':treeModel.feature_importances_}) Importance[Importance['重要度']!=0]
Step 7: 決定木を可視化する
作ったモデルを可視化してみます。うまく日本語で出力できなかったので、英語の元ファイルを使いました。「アルコール度数」「硫化カリウム密度」「総二酸化硫黄濃度」「酢酸濃度」のようなモデルのカギとなっている項目が上位の判定条件になっています。from sklearn import tree from graphviz import Source from sklearn.externals.six import StringIO import pydotplus as pdp #決定木モデルの書き出し dot_data = StringIO() tree.export_graphviz(treeModel, out_file="tree.dot", feature_names=data_X.columns, filled=True, rounded=True)
まとめ
ネットの記事などを参考に開発環境をセットアップして見よう見まねで決定木分析をしてみました。正直、とっても少ないコード量で複雑な処理が表現できることに驚きました。分析対象のデータを集められれば、用意された分析モデルのライブラリを使って誰でも機械学習を使える(プログラミングのハードルがこれまでより極端に低い)という点ではブレイクスルーかもしれません。例えば、下の画像は決定木の可視化部分を書いていたときのデバッグ画面(うまく動かなくてエラーが出ている画面)です。上の「import」の部分はライブラリの呼び出しで、実際の処理は最後の2行だけです。下のデバッグ画面を見るとエラーは僕が書いたコードの7行目から自動生成されたコードの427行目で発生しています(---->が付いている箇所)。たった2行のコードから400行以上のコードが自動生成されていることになります。レガシー領域のSEとしては驚きなのです。
今回使っている機械学習のライブラリには決定木以外にも、ロジスティック回帰やニューラルネットワークなど複数の機械学習のモデルが入っているようなので、様々なモデルでソムリAIを作って精度を比較検証してみようと思います。専門家から見たら「縄文人が土器作って喜んでいるレベル」なのでしょうが、縄文人なりにいろいろな土器を作ってみようと思います。