アイリスデータであやめの種類を決定木分析で分類してみた
かれこれ10年近く分析業界に関わっていますが、実に様々なデータを扱ってきました。私の場合、新しい手法などを試すときはまずはサンプルデータで試してから実データに適用するといったことをしてきました。会社の実データを自宅からアクセスできる環境がなく、自宅でサンプルデータを利用し分析やモデリングのプログラムを書いていました。
サンプルデータは実データに近い内容を自分で作ったり、ウェブ上で公開されているデータを利用していました。実際はサンプルデータで動いても実データでは予想外に実行時間がかかったりノイズが含まれていたりして上手く動かないことも多々ありましたが、分かりやすいデータでプログラムを動かして結果を確認するということが新しい知識を得るうえで大切だと感じました。
今回からPythonのデータ可視化用ライブラリのseabornを利用してサンプルデータを用いて集計や分析をしていこうと思います。分析仮設を立てて検証するという能力を錆びらせないためにやっていきます。
1. 利用データ説明
何のデータか
今回見ていくデータはフィッシャーのアイリス(アヤメ)データセットです。 分類問題やクラスタリングのサンプルコード紹介でよく利用されるデータです。フィッシャーという方が論文で紹介したのが始めだったんですね。
The Iris flower data set or Fisher's Iris data set is a multivariate data set introduced by the British statistician and biologist Ronald Fisher in his 1936 paper The use of multiple measurements in taxonomic problems as an example of linear discriminant analysis. ("Iris_flower_data_set" Wikipedia: The Free Encyclopedia)
アヤメって?
下記表の一番上にあるのが、アヤメのようです。 色・形はカキツバタやハナショウブと似ていますが花びらに模様があるので分かりやすいですね。
抜粋元: https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%A4%E3%83%A1
データ取得先はどこ
seabornにてデータセットが用意されているので、今回はseabornのload_dataset関数を使ってデータを取得します。 seaborn.load_dataset
# irisデータセットの読み込み # seabornで用意されているので、すぐにデータ確認することができる import seaborn as sns df = sns.load_dataset("iris") #dfはdataframeの略
どのようなデータか
データ数: 150レコード
変数一覧:
英名 | 日本語訳 | 備考 |
---|---|---|
sepal_length | がく片の縦幅 | |
sepal_width | がく片の横幅 | |
petal_length | 花びらの縦幅 | |
petal_width | 花びらの横幅 | |
species | アヤメの種類 | setosa、versicolor、virginicaの三種類 |
データセットに含まれるアヤメの種類
下記三種類のアヤメのがく片と花びらの長さの情報を集めたデータセットのようです。
1.setosa
2.versicolor
3.virginica
2. どのような分析ができそうか
- がく片と花びらの長さからアヤメの種別を分類する
3. Checking iris dataset using seaborn
テーマは、「アヤメの種別を分類するモデルを作成する」という目的にして分析してみます。
データ読み込み
# irisデータセットの読み込み # seabornで用意されているので、すぐにデータ確認することができる import seaborn as sns df = sns.load_dataset("iris") #dfはdataframeの略
データ確認
ざっくり全体的にデータの基礎情報を確認しておきます。
# describe関数で各変数の概要を確認
df.describe()
sepal_length | sepal_width | petal_length | petal_width | |
---|---|---|---|---|
count | 150.000000 | 150.000000 | 150.000000 | 150.000000 |
mean | 5.843333 | 3.057333 | 3.758000 | 1.199333 |
std | 0.828066 | 0.435866 | 1.765298 | 0.762238 |
min | 4.300000 | 2.000000 | 1.000000 | 0.100000 |
25% | 5.100000 | 2.800000 | 1.600000 | 0.300000 |
50% | 5.800000 | 3.000000 | 4.350000 | 1.300000 |
75% | 6.400000 | 3.300000 | 5.100000 | 1.800000 |
max | 7.900000 | 4.400000 | 6.900000 | 2.500000 |
※ describe関数で表示される各項目の意味
英名 | 日本語訳 |
---|---|
count | レコード数 |
mean | 平均 |
std | 標準偏差 |
min | 最小値 |
25% | 25%パーセンタイル |
50% | 中央値 (50%パーセンタイル) |
75% | 75%パーセンタイル |
max | 最大値 |
ざっくりと全体的にどのようなデータになっているか確認します。 がく片の方が花びらより長いんだななど分析対象の前提知識がない場合はデータを見て想像力を働かせます。
デフォルトだとアウトプット画像のサイズが小さいので設定変更します。
# 出力画像のデザイン変更 from matplotlib import rcParams rcParams['xtick.labelsize'] = 12 # x軸のラベルのフォントサイズ rcParams['ytick.labelsize'] = 12 # y軸のラベルのフォントサイズ rcParams['figure.figsize'] = 18,8 # 画像サイズの変更(inch)
相関係数をざっくり確認しておきます。
# 相関係数確認 sns.heatmap(df.corr(), vmax=1, vmin=-1, center=0,annot=True)
次に各アヤメの種別ごとにがく片や花びらの長さに違いがあるのかを集計します。
df[["sepal_length","species"]].groupby("species").describe()
sepal_length | ||||||||
---|---|---|---|---|---|---|---|---|
count | mean | std | min | 25% | 50% | 75% | max | |
species | ||||||||
setosa | 50.0 | 5.006 | 0.352490 | 4.3 | 4.800 | 5.0 | 5.2 | 5.8 |
versicolor | 50.0 | 5.936 | 0.516171 | 4.9 | 5.600 | 5.9 | 6.3 | 7.0 |
virginica | 50.0 | 6.588 | 0.635880 | 4.9 | 6.225 | 6.5 | 6.9 | 7.9 |
df[["sepal_width","species"]].groupby("species").describe()
sepal_width | ||||||||
---|---|---|---|---|---|---|---|---|
count | mean | std | min | 25% | 50% | 75% | max | |
species | ||||||||
setosa | 50.0 | 3.428 | 0.379064 | 2.3 | 3.200 | 3.4 | 3.675 | 4.4 |
versicolor | 50.0 | 2.770 | 0.313798 | 2.0 | 2.525 | 2.8 | 3.000 | 3.4 |
virginica | 50.0 | 2.974 | 0.322497 | 2.2 | 2.800 | 3.0 | 3.175 | 3.8 |
df[["petal_length","species"]].groupby("species").describe()
petal_length | ||||||||
---|---|---|---|---|---|---|---|---|
count | mean | std | min | 25% | 50% | 75% | max | |
species | ||||||||
setosa | 50.0 | 1.462 | 0.173664 | 1.0 | 1.4 | 1.50 | 1.575 | 1.9 |
versicolor | 50.0 | 4.260 | 0.469911 | 3.0 | 4.0 | 4.35 | 4.600 | 5.1 |
virginica | 50.0 | 5.552 | 0.551895 | 4.5 | 5.1 | 5.55 | 5.875 | 6.9 |
df[["petal_width","species"]].groupby("species").describe()
petal_width | ||||||||
---|---|---|---|---|---|---|---|---|
count | mean | std | min | 25% | 50% | 75% | max | |
species | ||||||||
setosa | 50.0 | 0.246 | 0.105386 | 0.1 | 0.2 | 0.2 | 0.3 | 0.6 |
versicolor | 50.0 | 1.326 | 0.197753 | 1.0 | 1.2 | 1.3 | 1.5 | 1.8 |
virginica | 50.0 | 2.026 | 0.274650 | 1.4 | 1.8 | 2.0 | 2.3 | 2.5 |
setosaは他の二種類のアヤメと比べると花びらが短そうですね。これは分類する上で重要なファクターとして採用されそうです。
データクリーニング
Feature Engineering
クラスタリングなど
モデリング
決定木を使ってアヤメの種類を分類します。
今回はsklearnを使います。モデリングをするときはだいたいsklearnを利用することが多いです。決定木以外にも様々な機械学習ができるようにパッケージングされています。
from sklearn import tree clf = tree.DecisionTreeClassifier(random_state=0, max_depth=4) X=df[["sepal_length","petal_length","sepal_width","petal_width"]] Y=df["species"] tree.plot_tree( clf.fit(X,Y) ,feature_names=["sepal_length","petal_length","sepal_width","petal_width"] ,class_names=["setosa","versicolor","virginica"] ,filled=True, rounded=True )
setosaは正答率100%で分類できることがわかる。他の種類よりも花びらの縦幅が小さいのできれいに境界線がわかれると思われる。versicolorとvirtinicaも花びらの縦幅と横幅でほとんど分類可能ということが分かる。(少なくとも今回のサンプルデータ上は)
4. check package versions
分析環境はanaconda macosです。 conda --version の結果はconda 4.7.12です。
今回利用したパッケージのバージョンは下記です。
import seaborn import matplotlib import sklearn import pandas import numpy print("seaborn:"+ seaborn.__version__) print("matplotlib:"+ matplotlib.__version__) print("sklearn:"+ sklearn.__version__) print("pandas:"+ pandas.__version__) print("numpy:"+ numpy.__version__)
seaborn:0.9.0 matplotlib:3.1.0 sklearn:0.21.2 pandas:0.24.2 numpy:1.16.4
plot_treeは ver0.21から導入されたので 古いバージョンのsklearnだと使えません。 sklearn.tree.plot_tree
古いバージョンを使っているときはgraphvizのフォーマットに変更して描画していましたが、plot_treeのおかげでかなり楽になりました。
5. 考察
今まで何となく利用していたirisデータですが、改めてデータの内容を確認してみると何を分析しようとしていたのか明確になりました。データの理解が分析をする上で非常に重要なポーションを占めているということが再認識できました。今回初めてjupyter notebookのコード内容をブログに載せましたが、もう少し手作業を含めずに寄稿することができないか要検討です。