Scikit-learnを使って主成分分析などを中心に遊んだ

Machine Learning Advent Calendar 2014の企画で書いているブログ記事です.最近私生活で使ってたことや,そのときに躓いたことをまとめました.

主成分分析

名前は聞いたことる方が多いと思いますが,できるだけデータの情報を損失することなく新しい軸を作るための手法です.高次元ベクトルデータなどは現実に可視化することは不可能ですが,2次元や3次元ぐらいまでに落としてあげると可視化することが出来ますし,タスクに依っては低次元部分だけのデータで十分なこともあります.
outputよくある例ではこのような二次元データからoutput2このように第一主成分(青破線)と第二主成分(黒破線)を求めます.そうするとデータ間のユークリッド距離は,青線上で測った場合でも概ね元のデータの特徴を保持している,ということが言えます.PCAはscikit-learnに実装されているものを利用するか,自分で固有値分解をすると計算可能です.
x = np.linspace(-3, 3, n)
y = 2.5 * x + np.random.randn(n)

data = np.c_[x, y]
dim  = 1
pca  = sklearn.decomposition.PCA(dim)
result = pca.fit_transform(data)
print data.shape      # (n, 2)
print result.shape    # (n, 1)

完全に余談ですが固有ベクトル計算は縦に出てきます.
cov_data = np.cov(data)
[values, vectors] = scipy.linalg.eigh(cov_data)
sorted_ix = np.argsort(values)[::-1] # 昇順から降順へ(PCAの場合,大きい固有値に対応する固有ベクトルを使う)
values_sorted  = evs[sorted_ix]
vectors_sorted = evc[:,sorted_ix] # ←ココ!!

一週間このミスでハマりました.それはともかく,意外と大事です.データ全部ぶち込んで自動で上手く行けばいいですが,現実にはなかなかそうは上手くいきません.データをじっくり眺めるために敢えて基本的な手法に通してみるのも大事だと思います.

MDS

主成分分析と似たような形でデータを低次元空間で可視化できる手法は他にもたくさんあり,お手軽なものは多次元尺度構成法 – Wikipediaというものがあります(英語版の方が詳しい; Multidimensional scaling – Wikipedia, the free encyclopedia).MDSでは

  • 似ているデータ→近くに置く
  • 似ていないデータ→遠く置く
という凄い単純な原則に則った可視化を行ってくれます.関係パッケージはsklearn.manifoldにあります.同時にsklearn.metrics当たりを使うといい感じに使うことができます.もし距離を計算してある場合には,metrics関係のパッケージは使わなくて良いです.

# 距離行列が計算済み(http://www1.doshisha.ac.jp/~mjin/R/27/27.html)
lbls = ["Hyogo", "Wakayama", "Osaka", "Nara", "Shiga", "Kyoto"]
data = np.matrix([[0, 134,85, 116, 118, 60],
                  [134, 0, 68, 66, 145, 141],
                  [85, 68, 0, 32, 83, 75],
                  [116, 66, 32, 0, 79, 95],
                  [118, 145, 83, 79, 0, 63],
                  [60,141, 75, 95, 63, 0]])
mds = skm.MDS(n_components = 2, \
              dissimilarity='precomputed')
y = mds.fit_transform(data)

こんな図が生成されます.

mds

上のMDSが入っているmanifoldパッケージには他にも面白い手法がたくさん実装されていて,例えば非線形な次元圧縮手法で恐らく一番有名なIsomapが実装されています.いろいろ調べていましたが,結局全部scikit-learnのスタイルで実装されているので,使い方はMDSとだいたい同じです(パラメータを設定,fit, predict/transformをする.終わり).下で使います.

まとめ.scikit-learn内のメソッドはだいたい
  • fit()
  • fit_predict()
  • fit_transform()
といった関数を持っています.ですので何か試したい手法が会った場合,そのクラスコンストラクタに渡す必要があるパラメータをよく読み,fit/fit_predict/fit_transformなどを実行するとだいたい望んだ結果を得る事ができます.またndarrayを操作するとき,スライスや既に実装されているviewの取得方法を上手く使うことで,ムダな計算を省くことができるようです.

オマケ

せっかくなので小ネタとして使ってみます.データとしては今季最高のアニメとごく一部のクラスタで名高い,TVアニメ「結城友奈は勇者である」公式サイトのスペシャルからアイコンダウンロード(ここです→アイコンダウンロード | TVアニメ「結城友奈は勇者である」公式サイト)へ行って取ってきます.全部jpgファイルなので,前処理でpngに変換してあります.

wget ICON_URL_BASE{001..124}.jpg
for v in `ls`; do;
    convert $v ${v%.*}.png;
done;

numpy/scipyから画像を読み込む方法などについてはドキュメントがある(6. 画像の取扱い — 2012.ProgramingLanguage 0.1 documentation),それを利用してみようと思います.

yuyuyu1


返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です