実体と情報のはざま

何事にも囚われず。

pandasを使わないで散布図行列をつくる

 とあるデータセットを入手したとして、初めにやることは何か?まずは、そのままの値をグラフ化。次は、散布図行列を見るのではないだろうか?私の手元にある本では、散布図行列をpandasとseabornを使ってわずか数行でグラフ化している。すごく便利なのだが、なんかブラックボックス感があって…。先日も中途半端にpandasに依存したものをつくってしまったのだが、今回は純粋にpyplotだけでつくってみた。Irisデータセットを使用。
開発環境:Spyder(Python 3.6)

import numpy as np
import matplotlib.pyplot as plt

def scmatrix(X,Y,Z):#散布図行列
    n=np.shape(X)
    L=np.zeros(n[0])#ラベルの処理 色々
    k,p=0,False
    for i in range(0,n[0]):
        if p==True:
            k=k+1
        p=False
        for j in range(0,n[0]):
            if Y[i]==Y[j] and L[j]==0:
                L[j]=k
                p=True
    plt.figure(figsize=(10,8))#プロット開始
    k=0
    L=(L-L.min())/(L.max()-L.min())#規格化
    for j in range(0,n[1]):
       for i in range(0,n[1]):
           k=k+1
           plt.subplot(n[1],n[1],k)
           plt.scatter(X[:,i],X[:,j],s=5,alpha=0.7,
                            cmap=plt.cm.rainbow,c=L)
           if j==n[1]-1:plt.xlabel(Z[i])
           if i==0 :plt.ylabel(Z[j])
    plt.subplots_adjust(wspace=0.3,hspace=0.3)
    return

dat=np.genfromtxt('Iris.csv',delimiter=',',dtype=str)#まずは全部読み出し
X=np.copy(dat[1:,1:5])#数値データ行列を抜き出し
X=np.asfarray(X)#型変換str→float64
Y=np.copy(dat[1:,5])#ラベルの抜き出し
Z=np.copy(dat[0,1:])

scmatrix(X,Y,Z)

ラベル毎に色を変えるところが苦労した。。
f:id:myuteru:20170611010942p:plain
はじめのほうで触れた「私の手元にある本」はコレ。

今日はここまで!

PCA(主成分分析)を手中に収める!

 機械学習を学んでいて、やたらと出てくるのがこのPCAというやつ。どの文献でもさらっと事前準備みたいな扱い。「まずはPCAで次元を削減してから・・・」なんてよく出てくる。ありきたりな手法のようですな。しかし、データサイエンス初心者の私としては、なんであれ一通りは理解しながら前へ進みたい!今回は、このPCAの学習と実装について書き残すことにする。
ライブラリを使えば簡単ですが!
 Pythonではおなじみのsckit-learnには簡単に実装可能なライブラリが用意されている。しかし、いつものことながら理論的な部分もしっかり学びたいので、ライブラリは使わないでやりたい。ただ、ここから少し深みにはまった。PCAの理論を解説している文献はいくつもネットに転がっているものの、理論の理解から実装まで導いてくれるものはなかった。理論の部分はネットの参考文献でよさそうなものを数件選んで勉強した。実装の部分は、自分の本棚からPython機械学習プログラミング 達人データサイエンティストによる理論と実践 (impress top gear)を引っ張り出してきて参考にした。参考にはしたものの出来上がったものはちょっと違うものになっている。というのも、自分が理解した理論の流れに沿ってプログラミングをしていくと、どうしても参考文献とは異なってしまうから。ここに自己流が入ることが不安でもあり楽しいところでもある。
できた!けどあってるのか!?
 データセットはデータサイエンスでは有名なIrisとwineを使った。前者は以前kaggleから入手したが、wineはUCI Machine Learning Repositoryから入手した。このサイトも有名。実はIrisデータセットはここにもある。できたPCAのプログラムはこんな感じ。
開発環境:Spyder(Python 3.6)

import numpy as np
import matplotlib.pyplot as plt

Iris=np.genfromtxt('Iris.csv',delimiter=',',dtype=str)#まずは全部読み出し
X=np.copy(Iris[1:,1:5])#データ行列を抜き出し
X=np.asfarray(X)#型変換str→float64

def PCA(X):
    n=X.shape#データ行列数(行,列)を取得
    for j in range(0,n[1]):
        X[:,j]=(X[:,j]-X[:,j].mean())/X[:,j].std()#データの標準化
    cov_X=np.cov(X.T)#共分散行列
    ei_val,ei_vec=np.linalg.eigh(cov_X)#固有値と固有ベクトル
    tot=np.sum(ei_val)#固有値の和
    s_ei_val=sorted(ei_val,reverse=True)#固有値の並べ替え
    ver=s_ei_val/tot#分散説明率
    a=np.zeros(n[1],dtype=np.int32)
    b=np.copy(np.abs(ei_val))
    for i in range(n[1]):#固有値の大きい順に並べ替える
        a[i]=np.argmax(b)#bが最大となるインデックスを格納
        b[a[i]]=0#値を取り出したらゼロにする
    g=np.zeros((n[0],2))
    for i in range(0,n[0]):
        g[i,0]=np.dot(X[i,:],ei_vec[:,a[0]])
        g[i,1]=np.dot(X[i,:],ei_vec[:,a[1]])
    return ver,ei_vec,a,g

ver,ei_vec,a,g=PCA(X)
n=X.shape
##############以下、グラフ化作業
#rmd=np.dot(np.dot(ei_vec[:,a[1]],cov_X),ei_vec[:,a[1]])
plt.figure(0)
plt.bar(np.arange(n[1]),ver[0:n[1]])
plt.xlabel("principal components")
plt.ylabel("explained variance ratio")
plt.figure(1)
plt.bar(np.arange(n[1]),ei_vec[:,a[0]])
plt.xlabel("PC1")
plt.ylabel("Y")
plt.figure(2)
plt.bar(np.arange(n[1]),ei_vec[:,a[1]])
plt.xlabel("PC2")
plt.ylabel("Y")
plt.figure(3)
for i in range(0,n[0]):
    if Iris[i+1,5]=='Iris-setosa':
        plt.scatter(g[i,0],g[i,1],color='b',alpha=0.7)
    elif Iris[i+1,5]=='Iris-versicolor':
        plt.scatter(g[i,0],g[i,1],color='r',alpha=0.7)
    elif Iris[i+1,5]=='Iris-virginica':
        plt.scatter(g[i,0],g[i,1],color='g',alpha=0.7)
plt.xlabel("PC1")
plt.ylabel("PC2")
plt.legend()

 結果はこんな感じ。次元削減というよりは教師なし分類として見ると、グラフが単色で見分けがつくのは青いやつだけかな。ところで、他のサイトで同じことをやっているはずのプロットと若干異なる。なんで?よく見ると、ネットに転がっている同様の結果どうしも若干違っている!そんなものなのか?今はいいや。いつか振り返ってみよう。プログラム中には分散説明率のグラフも入っているので忘備録として解説を入れたいが説明が長くなりそうなので省略。
f:id:myuteru:20170607232450p:plain
 つぎに、wineデータセットを使った場合の結果。これも教師なし分類としてみると単色で見分けがつくのは緑だけかな。ちなみに、上のプログラムのdef以外の部分をwineデータセットに合わせてちょいといじるだけでできる。
f:id:myuteru:20170607233029p:plain
 今回は使い古されてなお現役で機械学習の前座で重宝されているPCAを実装した。この手法自体をちょっと軽んじてたけど、実際に四苦八苦しながらやってみると、初めに考えた人のすごさや奥深さを知ることになり大変に勉強になった。。
 おっと、日付が変わってしまう!今日はここまで!

kaggleと日経BigDataのサイトについて

 今日は一旦プログラミングから目を離して、最近の情報の中で私のアンテナに引っかかったもの2点について書いておきたい。

①kaggleにPrizeMoney $1,200,000 のCompetitionが出たこと。

②「日経ビッグデータ」ってやつの存在を知ったこと。

 数日前に、kaggleのサイトを楽しんでいたらコンペにとんでもない数字が並んでいてドキッとした。それが①の件。他と桁が違うじゃないっすか!Overviewを読んでみると、Zillowというアメリカの有名不動産会社の住宅価格を予測する懸賞案件らしい。金額の大きさから話題性を引き出したいという狙いもあるのではないかとは思うが、データサイエンス業界にとっては嬉しいこと。どんどんやってほしい。

 kaggleではすでに突っ込んだdiscussionが行われている様子で、Zillowの担当者がKagglerたちの疑問に答えるなど活発な意見交換もあるようだ。読んでいてすごくワクワクする。私も早く参加できるレベルになりたい!英語力も含めて。。このブログでもちゃんとした翻訳で面白いやりとりのポイントを紹介したいのだけれど、英訳に確信が持てないので今はまだ無理。面白そうな議論てのは例えば、predictionに他から持ってきたデータを使っちゃっている人を指摘しているやつとかね。

 次は②の話。データサイエンティストを志す者としては常識がないと思われても仕方ないのだが、日経ビッグデータというメジャー誌の存在をつい先日まで知らなかった。たまたま勤めている会社(非IT系)のリサーチ部門が書いたレポートにその名前があったのがきっかけでサイトを見てみた。

 できれば定期購読したいところだけど、私のような平均的な会社員が個人で契約するのはちょっとハードル(嫁のご機嫌)が高すぎる。なので、今はサイトのトップページ右側にあるMostPopularの記事ランキングをチェックしている。これだけでも結構面白い。

 基本的に産業向けなので、学術的に最新の技術がどうとかは出てこない。それはそれで良かったりする。どんなに高度な技術であっても、広く社会に普及し世の中で役に立たなくては面白くないからね。私の場合、相対性理論がGPS技術で活用されていることを知ったときは一瞬テンションが上がって再学習した経験がある。

 上記2つのサイトには、データサイエンスはデータがあってなんぼの世界であることをあらためて気づかされる。あたりまえだが。データがあって初めて成立する。課題が先かデータが先かは両方よくある話で、課題を克服するためにデータをとって解析する場合とデータを分析した結果を見て課題を発見する場合の両方とも世間では散見される。私は、十分な実力が身についた暁には、与えられたデータからではなく、課題からデータを見つけ場合によっては必要なデータを取りに行く(とってもらうよう要請する)ような積極的な問題解決法としてデータサイエンスを使いたいと考えている。…思想は立派ですね。実力は序の口なのにね。。

 今日はここまで!

データセットの分割

 データサイエンスの初めの一歩として、有名なIrisデータセットをいじり始めている。先日はデータの中身をプロットしたり散布図行列をつくってみたりした。データが俯瞰できたので、さっそく何かしらの機械学習をやってみようと思ったのだが、その前にやることがあった。
Numpyに最適なコマンドが!
 機械学習に入る前にデータセットをトレーニング用とテスト用に分割しなくてはならないようだ。そりゃそうか。以前Kaggleからダウンロードしてちょっと覗いてみたTitanicのデータセットチュートリアル用だからトレーニングとテストが初めから分割されていた。しかし、通常は一連のデータがぶわ~と並んでいるだけである。
 そこで、どうやってデータを分割するかあれこれ考えてはみたものの、すっきりしたアルゴリズムになかなかならなくて。。Numpy配列のデータ型の扱いづらさ(私が不慣れなだけですが。。)も拍車をかけて、も~こんなところで時間を浪費するなんて~!と、参考文献(一番下で紹介)を丸パクリも頭によぎったが、本のテクニックはテクニカルすぎて勉強にならんと思い直し、原点に戻って試行錯誤した。その結果、振り返ってみれば大したことはなく、Numpyの"shuffle"というコマンドを使うと自分としては見通しの良いデータの分割ができた。”shuffle”はデータ行列を勝手にシャッフルしてくれる!
 その結果を反映したデータ分割プログラムがコレ。元データを丸々読み込んで、データ部分のみをシャッフル(1行!)し、分割する簡単なプログラム。これで十分。
開発環境:Spyder(Python 3.6)

import numpy as np
import matplotlib.pyplot as plt

Iris=np.genfromtxt('Iris.csv',delimiter=',',dtype=str)#まずは全部読み出し
IrisR=np.copy(Iris)
np.random.shuffle(IrisR[1:,:])#シャッフル!
n=np.shape(Iris)             

A,B=8,2#全データを A:B=training:test に分割
a=np.uint32(n[0]*A/(A+B))
Iris_train=np.copy(IrisR[0:a+1,:])#トレーニングデータ
Iris_test=np.copy(IrisR[a:,:])#テストデータ部分
Iris_test[0,:]=np.copy(IrisR[0,:])#テストデータ完成
np.savetxt('Iris_training.csv',Iris_train,delimiter=',',fmt='%20s')#出力
np.savetxt('Iris_test.csv',Iris_test,delimiter=',',fmt='%20s')#出力

 このあと続くグラフ化プログラムはのせてないけど、グラフで内容を説明するとこんな感じ。
 まずは、元データ。50個おきに値が異なるグループがある。
f:id:myuteru:20170603090750p:plain
 で、次がシャッフル後のプロット。この初めの8割をトレーニングデータ、残り2割をテストデータとしてCSV形式で保存するようにしてある。
f:id:myuteru:20170603090847p:plain

 今回の件に関してデータサイエンスのエキスパートがどのように取り組んでいるかが垣間見れるのが、下記の本である。

 この本はscikit-learn(機械学習ライブラリ)などをフル活用して、実務的な部分でデータとどう向き合うかを教えてくれる。内容のレベルが高いのでまだ理解できていないことが多いが、要所とデータ処理の流れは特に分かり易くかかれていて頼りになる。例えば、今回のようにデータを分割する際に、どれくらいの割合で分割すべきかの勘所なんかも書いてあって興味深い。

葉山の釣り場で思いついたこと

 昨日は中二の息子と久々の海釣りに行ってきた。平日だが息子は学校行事の振替休日で、私はそれに合わせて休暇を取った。天気は良好で風も穏やか、海はべた凪状態でやや物足りない条件ではあったが、そこそこ釣果もあり、楽しめた。最近データサイエンスを夢中で勉強してきた頭の疲労を癒す狙いもあったのだが、釣り場でもふと考え事をしてしまっていた。

 糸を垂らしながら考えていたことは、釣りがらみで何かデータサイエンスに向いているネタはないものかということ。思いついたことは、釣れる魚の数を予測するニューラルネットワークである。魚釣りのだいご味は日々変わる自然条件のなかでどんな仕掛けが最適でどんな餌が効果的かということを手探りで見つけていくプロセスにあると私は思っている。しかし、おおよその釣果は魚が釣り場近くにいるかいないかで決まると考えられるそれは環境と魚の生態に依存し、我々がどうこうできることではない。つまり、釣り人側が平均的なな腕前であるならば、釣果は環境と魚の生態で決定される。

 ということは、多くの釣り人が訪れてなおかつ日々の釣果が数値データとして残っていれば機械学習が活用できる可能性がある。でも、日々の釣果なんてデータはどこにあるのか。実は、”海釣り施設”にあるんです。特に、私も時々お世話になっている本牧海づり施設の釣果情報には、天気/水温/潮汐/入場者数と魚種毎の釣果数が毎日掲載されている!これは、なかなかのデータなのではないですか?これをニューラルネットワークに学習させて、いつ行けば何の魚がどれくらい釣れそうかが予測できれば、ボウズ(方言?一匹も釣れないことを指す。)で帰宅なんてことにはならない。かも。

 じゃあ、どんなニューラルネットワークになるかというと、まだ素人の私にはちょっと見通せないところがある。天気(晴れ/雨/曇り)ってどうやって数値化して入力データにすればいいんだろ。波高/風速/気温なんかはそのまま入れればよさそうだけど…。あと、出力データと教師データは、魚種(アイナメとかサバとか)毎の数にしたいんだけど、そうすると30種類ぐらいの出力ノードがいるってことになる。私が知っているニューラルネットワークはせいぜい10ノード程度なのだが、この数が多くて問題になることはなんだろか。ちょっと難しそうなニオイがしてきた。

 できたら面白そうだと思ったけど、初心者が手を出すのはどうかな。おとなしくIrisデータセットに戻って、基本的なところを積み重ねてから挑戦してみようかな。そうしよう。

 ちなみに、今回行ってきたのは神奈川県葉山町にある某漁港である。天気次第だが、富士山(この日は見えず)と裕次郎灯台(白いやつ)と鳥居(灯台の左側)と江ノ島(灯台の右側にうっすら)が一望できて眺めが良い。

f:id:myuteru:20170531221754j:plain

釣れた魚はメバル↓、他数種。

f:id:myuteru:20170531222808j:plain

 私が釣り場を選ぶ時は、まず下記の本で調べることから始める。

 

 必ず駐車場とトイレをチェックする。近くにないと不便でしょうがないからね。たくさん釣れるとクーラーボックスが重たくなるし(めったにないが。。)。あと、近くに釣具屋があると安心。コマセが切れたところにサバの群れが来た~とかね。

 本に記載されている釣果は私の実績と若干ずれてきている気がするが、そこは自然環境の変化というものだろうか。実際、ここ10年くらいで海の環境が変化していると思う。地球温暖化が影響しているのか何なのかはわからないが、関東よりずっと南方に生息する魚が時々釣れるようになった。

 そうそう、温暖化もしているのかしていないのか、本当のところは賛否両論なんですって?政治的な意図が入るとデータの解釈が変えられてしまうことがあるからね。生データから自分なりの結論を導けるデータサイエンティストになりたいな。

 今日はここまで!

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関数が一行で定義できることとかソフトマックスの実装時の注意点を守らないとまともな値が出力できないこともあるなど、事前に知っておいて良かったと思える事柄を学べた。

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

Kaggleにアカウント

 Kaggleのアカウントを取得した。相変わらずの英語力なので読むのは遅いが、エキスパートたちのやりとりが面白くてついつい投稿を読んでしまう。。
 サインインして初めにやったことは、タイタニックの件のチュートリアルの読み込みとデータセットのダウンロード。日本のサイトにもこれに挑戦した様子などを自分でレポートした記事が何件かあり、私がその記事を読んで大体の内容は知ってしまっている。なので、謎解きというか課題解決的な面白さは全くない。でも、実際にデータを手にしてみるとやっぱり嬉しい~。解析とかはまだやってないけど、徐々にやっていくつもり。
 もう一つダウンロードしたものが、Irisのデータセット。アヤメの花の形状データから品種を分類するという有名な課題。コンペのレベルとは程遠いけど、有名なデータセットにはすべて触れてみたいし、比較的簡単そうでいい練習になるかなと。
 金曜日を待たずして仕事とデータサイエンスの勉強疲れが出てきた。
 今日はここまで!