2011年4月15日金曜日

Python で行列演算 = numpy

python で行列演算をしたい.

ちょうど待ち行列MAP/G/1の系内客数分布を数値計算しようとしていて, どうせなので汎用性高い物にしようと思ったの動機.
まぁありきたりな話, 新しいライブラリを使うと大抵最初はまる.

・numpy のインストール
と思ったらすでにnumpy は入っていた. バージョンは1.2.
古いようなので, easy-install でupgrade する.

% sudo easy_install --upgrade numpy
とここで, 鬼のようにwarning と error っぽいメッセージが. 萎える.

・numpy を使う

matrixってのが行列の定義のようだ.

>>> C_matrix = [
...  [-0.2,0.2],
...  [0.0, -0.2]
...  ]
>>> C_matrix = matrix(C_matrix)
>>> D_matrix = [
...     [0,0],
...     [0.2,0]
...     ]
>>> 
>>> C_matrix = matrix(C_matrix)
>>> D_matrix = matrix(D_matrix)
>>> C_matrix 
matrix([[-0.2,  0.2],
        [ 0. , -0.2]])
>>> D_matrix
matrix([[ 0. ,  0. ],
        [ 0.2,  0. ]])

のように定義できた. array ってのもあるが, これは完全に転置っぽいので直感的でないため, やめる.
(注) matrix で[[1,2],[3,4]] は array では [[1,3],[2,4]] と列で定義するとうこと.

演算もらくらくで便利そうだ.

>>> E_VEC = matrix([[1],]*2)
>>> E_VEC
matrix([[1],
        [1]])

>>> C_matrix + D_matrix
matrix([[-0.2,  0.2],
        [ 0.2, -0.2]])
>>> (C_matrix + D_matrix) * E_VEC
matrix([[ 0.],
        [ 0.]])
>>> dot((C_matrix + D_matrix), E_VEC)
matrix([[ 0.],
        [ 0.]])

* は各成分の掛け算になるらしい. dot()で行列のかけざん.


で, solve ってのが連立方程式の解のよう.
とりあえず, 行ベクトルPI * (C + D) = 0, PI*e = 0 を解いてCおよびDで構成される, (C+Dをジェネレータとして持つ)マルコフ連鎖の定常状態確率を解くことにする.



ここではまった.


solve は正方行列でないと扱えないらしく, おそらくフルランクでないと無理だろう.
とりあえず, C+Dは明らかにフルランクではなく, PI*e = 0と組み合わせることでようやく解ける.
どうしようかと思ったけどとりあえず暫定的に, C+Dの一列を抜いてeへ替える. そして右辺は[0,...,0,1]とおく.

以下のようになる.

from numpy.linalg import solve

def calculate_pi():
    sumC_D = C_matrix + D_matrix 
    pi_solver = []
    for column in sumC_D.tolist():
        column.append(1)
        pi_solver.append(column[1:])

    zeros_plus1 = [0] * (M_SIZE -1) + [1]    
    pi_solver = mat(pi_solver)
    zeros = mat(zeros_plus1)

あまりに煩雑すぎるが, 特にメソッドもなさそうなので暫定的に...
pi_solverは最左行を省く. (まぁこれがのちのち問題だと思う)
zeros はさっきかいた[0,...,0, 1]の行ベクトル.

で, 早速solve.

>>> pipi = solve(t,zeros)
Traceback (most recent call last):
  File "", line 1, in 
  File "/Library/Python/2.6/site-packages/numpy-1.5.1-py2.6-macosx-10.6-universal.egg/numpy/linalg/linalg.py", line 316, in solve
    raise LinAlgError, 'Incompatible dimensions'
numpy.linalg.linalg.LinAlgError: Incompatible dimensions

はーなんでやーと思って, 色々やってみると, 同じことを matrix のかわりに arrayなら通る.
で, もしかたしらとちょっと不安だったが, どうやら

行* 行列 = 行

はだめで

行列 * 列 = 列

しかやってくれないぽい.

ふざけんなよーと思って, またもや暫定的に

def calculate_pi():
    sumC_D = C_matrix + D_matrix 
    pi_solver = []
    for column in sumC_D.tolist():
        column.append(1)
        pi_solver.append(column[1:])
    zeros_plus1 = [0] * (M_SIZE -1) + [1]
        
    pi_solver = mat(pi_solver)
    zeros_plus1 = mat(zeros_plus1)
    pi_vec = solve(pi_solver.T,zeros_plus1.T)

    return  pi_vec.T
とした. Tで転置らしい.


これは先が思いやられるな...

2011年4月13日水曜日

最近読んだ本 2011/1 ~ 2011/3

なかなか最近 Hadoop も触ってないな...

最近読んだ本

1,  Webを支える技術
2,  プログラムはなぜ動くのか
3,  TCP/IPソケットプログラミング Java編
4,  TCP/IPアナライザ作成とパケット解析
5, Web開発者のための大規模サービス技術入門
6, 基礎からのMySQL


[感想]
>> 1
RESTって何?ってところだったので, 歴史からその界隈の用語等を俯瞰できてよかった.

>> 2
情報学科出身ながらこのへんの話を全く勉強できなかったので, これはおもしろくためになった. とは言え, Cのfizzbuzは解けることが前提だろうか. レジスタ, アセンブラって言葉さえ意味を知らない人におすすめ (笑)

>> 3
ソケットって何? というところから読み始めた. Javaは初心者. 要はソケットTCPの実装ね, というとこで落ち着いた. さすがに古いということで, 今のJavaでSocket APIを叩くならネットから情報集めてやればよいか, というところ.

>> 4
wireshark, tshark, tcpdump  などという便利なpcap解析ソフトがある. これらの仕組みがわかる?!というかpcapってどうなってんの?みたいなノリで読んだ. 結局は (というかそういうもんだが) Cのpcapライブラリの使い方が分かって落ち着いた. 丁寧だが, Cの構造体, ポインタ, 配列, アドレスなどそのへんの用語が一瞬で結びつかないとピンとこないかも.
あんまりC使わない気がするので参考にならないやも...

>> 5
これは面白かった. 実際の大規模サービスをやってるはてなでのインターン内容ってことで, そういった企業がどんな思い (?) でここまできたかがわかる. また, サービスを実践するためにどういった知識を必要としたか, など. これまで一切興味がなかった"検索", "形態素解析"などの言葉を覚えたのと, OS, DBってものがなんなのか分かった. なかでもDBサーバはほぼオンメモリで考えるところはへーというかんじだった.


>> 6
DBって何? って話から, 一応構文くらい知っておこうと思って読んだ. 「joinが重いんだ...」とか「**GBのファイルから "select * from ..."で結果こない」とかの意味が分かった.  とそれだけかよってかんじですが... 丁寧で分かりやすかったですが, Mac, Linux向けの情報がなかったのでインストールらへんのページ数がもったいなかったかなぁと. PHPも読み書きできるようにしておこう.