機械学習/Pythonで決定木を使う のバックアップソース(No.5)

*はじめに [#qa786736]

ここでは、Pythonのデータ分析ライブラリーであるpandas、機械学習ライブラリーであるscikit-learn、実行環境であるJupyter Notebookを用いて、決定木による分類を行います。

分類とは、答えがある機械学習である教師付き機械学習のうち、答えがカテゴリー、ラベル、クラスと行った離散値であるもののことです。

scikit-learnに付属するデータを用いているサンプルはたくさんありますが、自分で実践するときは、データ・ファイルの読み込みからやらないといけません。
そこで、ここでは、DeepAnalyticsフォーマットのファイルを想定して、データ・ファイルの読み込みから予測結果の出力まで、一通りやります。


この内容は、以下の環境で確認しました。
-Python 3.5.1
-pandas 0.20.2
-NumPy 1.13.0
-scikit-learn 0.18.1
-Jupyter Notebook 5.0.0
-IPython 6.1.0
-Graphviz 2.36.0
-pydotplus 2.0.2


*データ [#fa7b2541]
ここでは、irisデータをサンプルとして用います。

このデータセットは,アヤメの種類(class)を花びらの長さ(sepal length),幅(sepal width),がくの長さ(petal length),幅(petal width)によって分類する問題です. 長さと幅は連続値,種類はIris-setosa, Iris-versicolor, Iris-virginicaのいずれかをとる離散値です.

DeepAnalyticsのフォーマットに倣って、訓練データを train.tsv、テストデータを test_X.tsvとして、タブ区切りのCSVファイルで保存されているものとします。

今回のサンプルファイルはこれです。
-&ref(./train.tsv);
-&ref(./test_X.tsv);

**train.tsv [#gee0ea9e]
train.tsvはこんな感じです。
|id|sepal lentgh|sepal width|petal length|petal width|class|h
|2|4.9|3|1.4|0.2|Iris-setosa|
|52|6.4|3.2|4.5|1.5|Iris-versicolor|
|101|6.3|3.3|6|2.5|Iris-virginica|
|...|...|...|...|...|...|

**test_X.tsv [#sa17a203]
test_X.tsvはこんな感じです。
|id|sepal length|sepal width|petal length|petal width|h
|1|5.1|3.5|1.4|0.2|
|51|7|3.2|4.7|1.4|
|103|7.1|3|5.9|2.1|
|...|...|...|...|...|



*データの読み込み [#x9791a6c]
pandasのread_csvを使って、タブ区切りのCSVファイルを読み込みます。
タブ区切りなのでdelimiterオプションを、先頭の列がインデックスなのでindex_colオプションを指定します。
#geshi(python){{
import pandas as pd
df_iris_train = pd.read_csv('train.tsv',  delimiter='\t', index_col=0)
df_iris_test  = pd.read_csv('test_X.tsv', delimiter='\t', index_col=0)
}}

読み込んだデータは、pandasのDataFrameとなります。
次のようにすると、Jupyter Notebook上でDataFrameを確認できます。
#geshi(python){{
df_iris_train
}}
#geshi(python){{
df_iris_test
}}


*決定木の学習 [#eec03914]
まず、訓練データから、入力Xと出力yをNumPy.Arrayで取り出します。
#geshi(python){{
X = df_iris_train.drop('class', axis=1).values
y = np.array(list(df_iris_train['class']))
}}
dropはDataFrameから行または列を取り除きます(axisオプションで行か列かを指定します)。
valuesはDataFrameをNumPy.Arrayに変換します。

Scikit-learnで決定木学習を使うには、sklearn.tree.DecisionTreeClassifierクラスを使います。
fitでモデル(ここでは決定木)を学習します。
#geshi(python){{
from sklearn import tree
clf = tree.DecisionTreeClassifier()
clf.fit(X, y)
}}

学習したモデルのスコアを確認します。
sklearn.tree.DecisionTreeClassifierのスコアは、正解率 (mean accuracy) です。
#geshi(python){{
clf.score(X, y)
}}


*学習した決定木の可視化 [#fc6641eb]
可視化にはGraphvizとPythonのpydotplusパッケージを使います。

Graphvizはグラフ描画ソフトウェアで、下記のサイトからダウンロードできます。
(macOS Sierraの場合、mountainlion版のgraphviz-2.36.0.pkgをダウンロードします。)
-http://www.graphviz.org

pydotplusパッケージがインストールされていない場合は、ターミナルでpip3を使ってインストールします。
#geshi(sh){{
$ sudo pip3 install pydotplus
}}


インストールができたら、Jupyter Notebook上でグラフを作成して描画します。
#geshi(python){{
import pydotplus
from IPython.display import Image
from sklearn.externals.six import StringIO
dot = StringIO()
tree.export_graphviz(clf, out_file=dot,
                     feature_names=df_iris_test.columns,
                     class_names=df_iris_train['class'].unique(),
                     filled=True, rounded=True,)
graph = pydotplus.graph_from_dot_data(dot.getvalue())
Image(graph.create_png())
}}

次のような決定木が表示されます。

&ref(./decision_tree_1.png,75%,nolink);

この決定木は、ノードの1行目に書かれた条件が満たされるときは左の枝に、そうでないときは右の枝に進みます。
葉にたどり着いたら、その葉が表すクラスに分類します。

したがって、この決定木は、以下のようなルールを表していることになります。
-petal lengthの値が2.45以下ならば、Iris-setosa
-petal lengthの値が2.45より大きい、かつ、petal widthの値が1.7以下、かつ、petal lengthの値が5.0以下ならば、Iris-versicolor
-petal lengthの値が2.45より大きい、かつ、petal widthの値が1.7以下、かつ、petal lengthの値が5.0より大きい、かつ、sepal widthの値が2.75以下ならば、Iris-versicolor
-petal lengthの値が2.45より大きい、かつ、petal widthの値が1.7以下、かつ、petal lengthの値が5.0より大きい、かつ、sepal widthの値が2.75より大きいならば、Iris-virginica
-petal lengthの値が2.45より大きい、かつ、petal widthの値が1.7より大きいならば、Iris-virginica


*学習した決定木による予測 [#s3f9c91b]
まず、テストデータの入力XをNumPy.Array形式に変換します。
#geshi(python){{
X = df_iris_test.values
}}
ここでは、訓練データの入力Xを上書きしていますので、注意しましょう。

predictメソッドで学習したモデルに基づいてラベルを予測します。
#geshi(python){{
p = clf.predict(X)
}}


*予測したラベルの出力 [#d7a5ac0c]

DeepAnalyticsでは、予測した結果をヘッダなしのCSV形式のファイルとしてアップロードします。

そこで、予測したラベルをCSV形式で出力します。
このとき、テストデータを参照してインデックスとします。
#geshi(python){{
pd.DataFrame(p, index=df_iris_test.index).to_csv('predict.csv', header=False)
}}


*sklearn.tree.DecisionTreeClassifierのオプション [#r3b471aa]

上の例ではデフォルトのパラメーターで決定木を学習しましたが、いくつかのオプションが用意されています。
-http://scikit-learn.org/dev/modules/generated/sklearn.tree.DecisionTreeClassifier.html

例えば、評価基準 (criterion) を情報量利得 (entropy) に、木の深さの最大値 (max_depth) を3にして実行すると、次のようになります。
#geshi(python){{
clf = tree.DecisionTreeClassifier(criterion='entropy',
                                  max_depth=3)
}}

&ref(./decision_tree_2.png,75%,nolink);

irisデータでは学習パラメーターを変更してもあまり効果がありませんが、実際のデータを分析するときには学習パラメーターを調整する必要があります。
トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS