2011年4月26日火曜日

漠然とした不安とmilkモジュール

皆様おはようございます.
今朝の滝沢村は,雨だれの音が音がこだましていて
どんよりとした雲が低く垂れこんでおります.

地震から日が経つに連れ余震の頻度は落ちてきた
はずなのに,正直なところ気持ちは落ち込む一方です.
なにか悪いことが起こるのではないかという,
なんともいえない気持ち悪さが心から離れません.
そんなことは無いさと思ってみても,気を緩める頃には
決まって地震に大地が震え,私は再び悪い予感に
とらわれるという循環になっています.

自分の心に素直に向き合い,本能の声に耳を傾けるならば
「これだけでは済まされない,もう一つ何かが起こるよ」
というささやきが聞こえてくるようです.
その声を無視して日常をやり過ごせばよいのか,それとも
理屈では説明のつかない悪い予感に従えばいいのか,
まだ割り切れずにいながら,時間が過ぎていきます.

ところで,ここまでの話と全く脈略がありませんが,
ここからガラリと話題を変えまして...

先日,少し知的な処理をコンピュータにやらせたいと思いまして,
pythonの機械学習モジュールについて調べてみる機会がありました.
そのとき見つけた「milk」というモジュールについてメモを披露したいと思います.

「milk」は名前の印象とは関係なくって複数の機械学習
アルゴリズムを集めたpythonパッケージのようです.
SVMやboostingなどをお手軽に使えるところが気に入りました.
複数のアルゴリズムを組み合わせて使うことも考慮されています.
残念なことに,milkのドキュメントは2つくらいしか見つかりません.
pypiluispedroです.
インストールは「easy_install milk」でいけました.

使い方ですが,サンプルを引用します.
import numpy as np
import milk
features = np.random.rand(100,10)
labels = np.zeros(100)
features[50:] += .5
labels[50:] = 1
learner = milk.defaultclassifier()
model = learner.train(features, labels)
example = np.random.rand(10)
print model.apply(example)
example2 = np.random.rand(10)
example2 += .5
print model.apply(example2)

milk.defaultclassifier()は,お手軽に使えるように
あらかじめデフォルト設定された学習機となっていて
SVM=Support Vector Machineを使った学習となっています.
教師信号として入力する特徴量(features)と対応するクラスタラベル(label)を
入力してやります.
特徴量の正規化や線形従属な要素の除去なども全自動でやってくれます.
defaultclassifier()では複数のクラスタに分類するためにone-versus-rest手法が
用いられるようになっています.
もちろんこれらの組み合わせを自分で自由に設定することも可能です.
defaultclassifier()の中身は,次のようになっているようです.
defaultclassifier = ctransforms(
   chkfinite(),
   interval_normalise(),
   featureselector(linear_independent_features),
   sda_filter(),
   gridsearch(one_against_one(svm.svm_to_binary(svm.svm_raw())),
   params={
     'C': 2.**np.arange(-9,5),
     'kernel': [svm.rbf_kernel(2.**i) for i in np.arange(-7,4)],
   }
))
ctransforms()というのが複数のフィルタ(学習器)を束ねてくれるmilkのAPIです.
そのなかで1つづつ与えられている引数の要素がそれぞれ別個の学習機や
フィルタとなっています.
・chkfiite()は,特徴量やラベルに無限やNaNなどが含まれていないかチェックするフィルタ.
・interval_normalise()は,特徴量を正規化するフィルタ.
・sda_filter()は,判別分析を行うフィルタ.
・gridsearch()は,多値問題をグリッド検索に基づいて与えられた学習器で学習するフィルタ.
・svm.rbf_kernel()は,Support Vector Machineのradial basis function kernel.

milkのフィルタ(学習器)は,皆 learn_func(features, label)のような引数を持つように
設計されていて,ctransforms()で束ねて与えると,パイプライン処理により1つの
学習機として動作するようになっているようです.

冒頭のサンプルコードに戻りますが,学習器のインスタンスを生成した後,
「train」で特徴量とラベルを与えて学習させます.
learner = milk.defaultclassifier()
model = learner.train(features, labels)
処理には数秒を要します.学習が終わると学習モデルが得られますので,
未知の特徴量を与えれば,学習結果に基づいて分類してくれます.
print model.apply(example)
学習モデルは,pickle化できるのでディスクから読み込むことも可能です.

OpenCVと組み合わせたり,あるいはネットから集めたデータを
自動分類したい時など,お手軽に使えるのではないでしょうか.

2011年4月21日木曜日

近況報告と64bit windows環境でのCython

皆様こんにちは.
どうやら2ヶ月ぶりの更新だったようです.
2月から3月までは,ただブログ更新をサボっていただけなのですが,
3月から4月にかけての1ヶ月間は リアルな生活で精一杯でした.
ようやく余震は,頻度も規模も小さくなってきて3.11以前の日常に戻りつつあります.
大震災で亡くなられた皆様のご無念を思うと切なくてなりません.
亡くなった皆様のご冥福をお祈り致しております.
また被災者の皆様には一日も早く落ち着いた生活を取り戻せますように祈っております.

日本政府の遅々とした対応には憤りを感じるばかりです.
奮闘している現場と対照的に政府にはリーダーシップのかけらも感じられません.
今回の大震災は被災地が広範囲に渡っているとはいえ散々な対応ぶりに見えます.
震災以前は,日本政府の能力は高く国民主体であると漠然と思って疑いませんでしたが,
これが大きな勘違いであったと今回の出来事で思いました.
普段あまり意見の合わないカミさんとさえも,この点においては意気投合しておりましたので,
世の中の皆さんにもこのように感じた方が少なくないのではないかと
勝手ながら想像しているところです.
どうか日本に一刻も早く良きリーダーが与えられて人々が希望を胸に
前に進むことができるようにと強く願い,毎日祈る日々です.

 私の近況ですが..地震の後 3日ほど停電,
その後の余震でも1日程度停電があった事などで
仕事にも多少の影響はでておりましたが,
事前の計画を遅れなく実現すべく開発業務に勤しんでいます.
 この頃は,もっぱら物理現象を観察しその現象をある程度再現する
なるべく簡略なモデル式とパラメータを探すといった地味な仕事をしております.
地味な仕事とはいえ このような最適化の作業は,物理の教科書をほっくりかえしつつ,
過去にサボったツケを実感しながら,
試行錯誤の繰り返しと計算の待ち時間のやり過ごし方など
ストレスの多い作業となっています.
 数時間かかった最適化計算が収束せず,良く調べてみたら計算プログラムのバグに
行き着いたときに感じる無気力感を 気持ちの隅に追いやりながら
作業を継続せねばなりません.
 以前は最適化計算をさせるためにC++やCを使っていましたが,
この頃は Python+SciPy+Numpyの組み合わせが気にいております.
特に「scipy.optimizeパッケージ」に感謝です.
 私は普段,Intel T7600(Core2duo 2.3GHz)+32bitVistaのノートPCを
持ち歩いて仕事しているのですが,最適化の計算だけは時間がかかってしまうので,
その時だけちょっと速そうなデスクトップパソコンを起動して計算させています.
例えばAMD PhenomII3GHz+Vista64bitなどにPythonスクリプトを走らせると,
T7600ノートPCでは及びもつかないスピードで計算してくれます.
当初は,私もこれだけで満足していたのですが,どんどんフィッティング対象の式が
複雑怪奇なものに成長するにしたがってPhenomマシンでも待ち時間が長くなり
どうしたものかと悩むようになりました.
 JITで早いとウワサのPyPyを試してみようと思いましたが,残念なことに
NumpyもScipyもPyPyでは動きませんので箸にも棒にもかかりません.
 そこで,Cythonを試してみることにしました.
Cythonは,Pythonもどきのスクリプトを書いてあげるとCに変換してくれて
pythonからimport可能なDLLを生成してくれるものですが,
現時点におけるpython高速化の確実なソリューションといえると思います.
 しかし普段やらないことにとりかかるのは億劫なものです.
ドキュメントも読まねばなりません.
こういうパッケージを追加していざ取り組んでみると落とし穴にハマって
抜け出せないことが多々あります.Cythonも例外ではありませんでした.

 結論からいうと,Vista32bit環境でCythonを使うことは全く問題ありませんでした.
Vista32bitではVisual Studio2005をインストールしているけれども,
mingwでコンパイルする設定を追加しておりますが問題もなく動きました.
きっとVCでもサクっとコンパイル出来るに違いありません.
私のVista32bit環境python27にあるLIB/distutils/distutils.cfgの中身を書いておきます.
[build]
compiler = mingw32
Cythonスクリプトをコンパイルしたときのsetup.pyは次のとおりです.
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
ext_modules = [Extension("hoge_func", ["hoge_func.pyx"], include_dirs=["C:/cygwin/usr/local/Python27/Lib/site-packages/numpy/core/include"])]
setup(
  name = 'hoge function',
  cmdclass = {'build_ext': build_ext},
  ext_modules = ext_modules
)
これでhoge_func.pyxにCythonスクリプトを書いておいて
"python setup.py build_ext --inplace"を実行すればサクっとコンパイルされて
pythonから"import hoge_func"できて恩恵に預かることができました.
ただしVista32bit環境だけです.
 Vista64bit環境のCython設定でハマりました.
正しく言えばdistutilの設定ということでしょうか.
Vista32環境+Cythonで十分早くって64bitで動かすことをしなくてもいいぐらい
高速化されたんですが,欲が出まして Vista64でも scipy+numpy+cythonの
最適化計算環境がどうしても欲しくなりました.
そこで 64bitネイティブなmingw64でもないかと探して"x86_64-w64-mingw32-gcc"なるものを
見つけインストールしsetup.pyを走らせましたがエラーを吐きます.
エラーの内容はもはや思い出せませんが,多数のエラーにブチ当たりました.
行き着いた先が,「Compiling 64-bit extension modules on Windows」というドキュメント.
64bitでcythonを楽しむためには次の条件を揃えねばならないようです.
1.Python2.6か2.7もしくは3.1
2.Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1が必須
 つまり,mingw64は使えないということです.
先程のドキュメントにはSDKバージョンは"Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1"以降となっていますが,最新版をインストールしてもコンパイルできませんでした.
SDKのダウンロードも結構かかった上に2種類もインストールしたり,
インストール中にフリーズしたりとハマリにハマってやっとコンパイルできました.
コンパイル時の呪文も書いておきます.
これをバッチファイルやMakefileなどに書いておくといいかもしれません
C:\Program Files\Microsoft SDKs\Windows\v7.0>set DISTUTILS_USE_SDK=1
C:\Program Files\Microsoft SDKs\Windows\v7.0>setenv /x64 /release
python setup.py build_ext --inplace
 苦労した割に,振り返ってみると大した事ではなかったのに
いったい何でハマってしまうのかと毎回思うのですが,
知らないもんは知らないのですからしょうがないと諦めます.
 ちなみにCythonの高速化は,ハンパではありませんでした.
正確にベンチマークとったら報告したいと思いますが,
体感スピードでは100倍以上早くなったといっても大げさではないと思っています.