SE_BOKUのまとめノート的ブログ

SE_BOKUが知ってること・勉強したこと・考えたことetc

アヤメ(iris)データで特徴選択(feature selection)の練習をとりあえずやってみる

目次

特徴選択(feature selection)

2019年最初のブログです。

今回は「特徴選択(feature selection)」がテーマです。

ニューラルネットワークを含む機械学習で予測をしたいとき、予測対象の変数のことを「目的変数」、目的変数を説明する変数を「説明変数」とか「特徴量」といいます。

例えば、未来の売上げを予測したいとした場合。

目的変数になるのは「過去の売上データ」であり、売上に影響をあたえる可能性のある諸々・・例えば、曜日や気温、店舗周辺イベント、セールの有無、広告費、チラシ枚数などなど・・が説明変数/特徴量となると考えるとイメージしやすいと思います。

なので、特徴選択とは、予測したい目的変数の決定に影響が大きい特徴量の組み合わせがどれかを探索するプロセスのことです。

今回は、それを触り程度にやってみようと思います。

PythonのPandaを使って、データはアヤメ(iris)を使います。

ただ、あくまで練習なので、とりあえず、本とかでよく紹介されているパターンをなぞっていく感じでやります。

 

アヤメ(iris)のデータを使ってジャブ程度にやる

使うのは、超有名な「アヤメ(iris)」データです。

sklearn.datasetsから取得します。

 

上から10行だけデータを見てみる

そのDataFrameで上から10行だけ表示してみます。 

import numpy as np
import pandas as pd
from sklearn.datasets import load_iris

class MyDataFrame():
    def get_iris(self):
        iris = load_iris()
        return pd.DataFrame(data= np.c_[iris['data'], iris['target']],columns=iris['feature_names'] + ['target'])

mdf = MyDataFrame()
mpd = mdf.get_iris()
print(mpd.head(10))

f:id:arakan_no_boku:20181228001457j:plain

  • sepal length :萼片(がくへん)の長さ
  • sepal width: 萼片(がくへん)の幅
  • petal length:花びらの長さ
  • petal width:花びらの幅

の4つの特徴変数を使って、target 0,1,2 の3分類を識別するデータです。

それぞれが、アヤメ属に含まれる種類の名前に対応しています。

0 :setosa(ヒオウギアヤメ

1 :versicolor

2 :virginica

 

件数・平均・標準偏差・分散等を確認

データの基本情報として、件数・平均・標準偏差・分散等を確認します。

pandasのDataFrameにしてるので、この辺は簡単に取得できます。

mpd.describe()

こうすれば、下記表の情報が全部取得できます。

 

  sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
件数 150 150 150 150
平均 5.843333 3.054 3.758667 1.198667
分散 0.681122 0.186751 3.092425 0.578532
標準偏差 0.825301 0.432147 1.758529 0.760613
最小値 4.3 2 1 0.1
四分位(25%) 5.1 2.8 1.6 0.3
中央値(50%) 5.8 3 4.35 1.3
四分位(75%) 6.4 3.3 5.1 1.8
最大値 7.9 4.4 6.9 2.5

上記の形で出力されるわけではないですが・・。

いちおう、タイトルを日本語に変更してわかりやすくしたり、分散(var)と標準偏差(std)の値だけは、以下の出力と置き換えたりしてますけれども、そのへんはご容赦ください。

mpd.var(ddof=False)
mpd.std(ddof=False)

見る限り、数字自体に特に変わった部分はありません。

petal length (cm)のバラつき(分散)が大きい(約3.09)くらいです。

正直、これで何か判断をする・・ってのも難しいです。

 

分布の状況をヒストグラムで視覚化してみる

分布の感じを視覚化してみます。

下記のグラフを表示するソースは、最後にまとめてのせます。

 

まずは、王道のヒストグラムから。

f:id:arakan_no_boku:20181228012523j:plain

データの各値の分布具合はわかりやすくなりました。

でも、これだけ見て、目的変数(0,1,2に分類)するのに意味のある部分と、そうでない部分の判断は、まだつきません。

 

2つの特徴変数の組合せの散布図で重なり具合を見る

2つの特徴変数の組合せで散布図を描いて、目的変数(0,1,2)毎に色を変えた散布図を使ってやってみます。

f:id:arakan_no_boku:20181228181659j:plain

それぞれ以下の組合せのグラフです。

  • sepal length (cm) とsepal width (cm) :上段左のグラフ
  • sepal length (cm) とpetal length (cm) :上段右のグラフ
  • sepal length (cm) とpetal width (cm) :下段左のグラフ
  • petal length (cm) とpetal width (cm) :下段右のグラフ

 こうやって見ると、上段左の「sepal length (cm) とsepal width (cm)」の組合せ以外は、非常にきれいに分布してます。

なので。

そのままでもそこそこ精度はでるが、「sepal width (cm)」を特徴変数から外すした方がより精度がでるんじゃないか?

そんな仮説は立てられそうかな?

 

やってみたけど・・うーーん

なんとなく、やってみましたが。

やっぱり、意図をもってやったわけではないので、いまいち漠然としてます。

とはいえ。

最初の一歩としてはこんなものかもしれないです。

 

グラフを書いた部分のpythonソース

最後にpythonソースコードを書いておきます。 

ヒストグラムの表示の部分です。 

import matplotlib.pyplot as plt

# mpdにpandasのDataFrameでirisのデータがある前提です
x = mpd['sepal length (cm)']
plt.subplot(221)
plt.hist(x,bins=6)
plt.xlabel('sepal length (cm)')
plt.subplot(222)
x1 = mpd['sepal width (cm)']
plt.hist(x1,bins=6)
plt.xlabel('sepal width (cm)')
plt.subplot(223)
x2 = mpd['petal length (cm)']
plt.hist(x2,bins=6)
plt.xlabel('petal length (cm)')
plt.subplot(224)
x3 = mpd['petal width (cm)']
plt.hist(x3,bins=6)
plt.xlabel('petal width (cm)')
plt.show()

次に散布図の表示の部分です 

plt.subplot(221)
x = mpd['sepal length (cm)']
y = mpd['sepal width (cm)']
t = mpd['target']
plt.scatter(x,y,c=t)
plt.xlabel('sepal length (cm)')
plt.ylabel('sepal width (cm)')

plt.subplot(222)
x1 = mpd['sepal length (cm)']
y1 = mpd['petal length (cm)']
t1 = mpd['target']
plt.scatter(x1,y1,c=t1)
plt.xlabel('sepal length (cm)')
plt.ylabel('petal length (cm)')

plt.subplot(223)
x2 = mpd['sepal length (cm)']
y2 = mpd['petal width (cm)']
t2 = mpd['target']
plt.scatter(x2,y2,c=t2)
plt.xlabel('sepal length (cm)')
plt.ylabel('petal width (cm)')

plt.subplot(224)
x3 = mpd['petal length (cm)']
y3 = mpd['petal width (cm)']
t3 = mpd['target']
plt.scatter(x3,y3,c=t3)
plt.xlabel('petal length (cm)')
plt.ylabel('petal width (cm)')
plt.show()

ではでは。