実体と情報のはざま

何事にも囚われず。

Irisデータセット事始め

 データサイエンスの世界では有名なIrisデータセット(花の形状データ4種を変量とする150個の個体とその種類が入っている。)を使ってデータサイエンティストっぽいことをやってみたいと思い、少しデータをいじってみた。しかし、まだまだPythonとそのエコシステムが全く身についていない自分に愕然とした。。今回やったことはエクセルでやれば15分もあればできると思われる作業にすぎない。しかし、多分5時間ぐらいはかかってしまった~。
読み込みで苦戦
 今回使ったIrisのデータは最近アカウントを取得したKaggleからダウンロードしたのだが、本やネットによるとAnacondaにも同梱されているとのこと。しかし、同梱されているファイルから読み出せるのは限られたデータであって、通常は外部からCSVとしてゲットするものだ。私は汎用的な方法を身に着けたいと考えているので、今回はダウンロードしたCSVファイルを使った。
f:id:myuteru:20170528234950p:plain
 しかし、ここで困ったことが。デフォルト設定でNumpyの配列として読み込もうとしたところ、テキスト部分が読み込めない。しょうがないのでデータを文字列として読み込んだ後、数値部分はもう一度フロートに変換しなおして使うことにした。要するに、色んなデータ型が混在したNumpy配列を作れなくて苦労したって話。。いまだに分からないが時間切れということで、手持ちの技術で進める。
Pyplotには慣れてきた!
 とりあえず読み込みは完了したので、そのままプロットして様子を見る。Pyplotに関してはちょっと前に、できたのできないのでギャーギャーしながらもなんとか勝手が分かってきたので、今回はすんなりプロットできた。
まずは、生データをID順にプロットしてみた。
f:id:myuteru:20170529000542p:plain
同様に、標準化したデータをプロット。
f:id:myuteru:20170529001000p:plain
 標準化は過去にブログで書いた気がする。たった一行で標準化ができちゃうなんて、行列が直接扱えるPythonならではだな。グラフから、データセットに50個おきに段差があるということかな。概観するってデータ処理には大事なことだから、些細な情報も大切にしなくちゃね。
Pandasとseabornって!?
 次にやってみたのは、データ間の相関関係を概観するための散布図行列の作成。そのスマートなやり方が、こないだ買った本に出ていていいなと思って。仕事で似たようなことをエクセルを使ってやったことがあるんだけど、まあ、時間がかかって仕方がなかった。グラフ枚数が増えるとちょっとバグってきてたしね。それがちょいちょいってできるんなら嬉しいなと。
 だが、簡単ではなかった。まず、Pandasのデータフレームなるものの存在になかなか気づかず、seabornとの連携がうまくできずにいた。どこが難しかったかというと、軸にラベルを入れるやりかたが分からなかった。でも、最初からPandasのデータフレームでデータを読み込んでいれば簡単だった。軸のラベルが自動的についてくるから。ただ、Pandasによる読み込みがどこか邪道な気がしてしまい今回はパス。
 そんなこんなでできたのがコレ。
f:id:myuteru:20170529003122p:plain
 実はseabornのギャラリーに同じものがある。有名なデータセットだとこういうことが起きるんだね。このグラフを眺めてみると、PetalLengthとPetalWidthに相関関係がありそうなことが見て取れる。花びらの長さと幅ね。今回はお試しだからIris(アヤメ)という花の実体について詳しく知ろうとはしないけど、本来は情報が実体の何を示しているのかを注意深く考察することが大切だと思うな。
 一連のグラフは下記プログラムで生成した。
開発環境:Spyder(Python 3.6)

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

Iris=np.genfromtxt('Iris.csv',delimiter=',',dtype=str)#まずは全部読み出し
X=np.copy(Iris[1:,1:5])#データ行列を抜き出し
X=np.asfarray(X)#型変換str→float64
Y=np.copy(Iris[1:,5])#品種の列
n=X.shape#データ行列数(行,列)
c=np.array(['b','c','r','g'])#プロット用の色を準備
#生データのプロット
fig1=plt.figure(1)
for j in range(0,n[1]):
    plt.scatter(np.arange(0,n[0]),X[:,j],
                    c=c[j],alpha=0.6,s=50,label=Iris[0,1+j])
plt.legend(loc=2)#左上に凡例を表示
plt.xlabel('Id')#X軸のラベルを指定
plt.ylabel('std data')#Y軸のラベルを指定
#標準化したデータのプロット
fig2=plt.figure(2)
for j in range(0,n[1]):
    X[:,j]=(X[:,j]-X[:,j].mean())/X[:,j].std()#データの標準化
    plt.scatter(np.arange(0,n[0]),X[:,j],
                c=c[j],alpha=0.6,s=50,label=Iris[0,1+j])
plt.legend(loc=2)#左上に凡例を表示
plt.xlabel('Id')#X軸のラベルを指定
plt.ylabel('std data')#Y軸のラベルを指定

df=pd.DataFrame(X)#pandasのデータフレームに変換
df.columns=[Iris[0,1],Iris[0,2],Iris[0,3],Iris[0,4]]#カラム名を付ける
g=sns.PairGrid(df)#散布図行列
g=g.map(plt.scatter,edgecolor='w',s=30,color='g')

 今回は良く知られているデータをよく知られた手法で概観した。次は機械学習をやってみたい。今週末は嫁と子供が実家に遊びに行ったりして勉強する時間が取れたので、ニューラルネットワークの自動微分とか勉強できたし。下記の本にはPythonを用いてディープラーニングの実装を丁寧に分かり易く書いてある。自動微分という文言は用いてないが、計算グラフを用いた誤差逆伝播法という形で解説している。また、活性化関数や損失関数を実装する際の簡潔なコードや注意点が書かれていて、初心者(私)やライブラリを使わないでやりたい人には良いと思う。ReLU関数が一行で定義できることとかソフトマックスの実装時の注意点を守らないとまともな値が出力できないこともあるなど、事前に知っておいて良かったと思える事柄を学べた。

 *アフィリエイトの画像が貼ってあるブログってカッコイイと前から思っていて申し込みをした。ついにアマゾンのリンクが貼れて嬉しい!お気に入りの本も紹介できて嬉しい!会社関係含めて身近に紹介できる人なんていないし。。
今日は、ここまで!