バナナでもわかる話

開設当初は計量経済学・統計学が専門の大学院生でした。今はデータを扱うお仕事をしています。統計学・経済学・投資理論・マーケティング等々に関する勉強・解説ブログ。ときどき趣味も。極力数式は使わずイメージで説明出来るよう心掛けていますが、時々暴走します。

python入門 Numpyを使った行列の計算

今日はNumpyパッケージに入っているndarray型変数の扱いについてやっていきます。


目次

スポンサーリンク


Numpy

Rと違って、pythonは行列計算の基盤が通常整っていません。
例えば、リストで行列っぽいものを以下のように作ってみたとしても

M1 = [[1,2,3],[2,3,4],[5,6,7]]
M2 = [[2,3,4],[3,4,5],[6,7,8]]

足し算さえできません。

In : M1 + M2
Out : [[1, 2, 3], [2, 3, 4], [5, 6, 7], [2, 3, 4], [3, 4, 5], [6, 7, 8]]

まあ、リストなので。


そういうわけで、こうした問題を回避するために利用するのがNumpyです。
Numpyは次のようにインポートします。
npという名前をつけるのが慣例です。

import numpy as np

ndarray

では、行列計算を行うにはどうしたら良いのでしょう。
先ほどのリストを使って計算してみます。

M1 = [[1,2,3],[2,3,4],[5,6,7]]
M2 = [[2,3,4],[3,4,5],[6,7,8]]

行列計算はNumpyのndarrayによって行います。

In : M1 = np.array(M1)
     M2 = np.array(M2)
     print(M2)
Out : 
array([[2, 3, 4],
       [3, 4, 5],
       [6, 7, 8]])

このように変換してやると、例えば先ほどの足し算も正しく計算できます。

In : M1 + M2
Out : 
array([[ 3,  5,  7],
       [ 5,  7,  9],
       [11, 13, 15]])
色々なarrayの生成

様々な方法でndarrayを生成することができます。

arrangeによるベクトルの生成

In : arange(1,5)
Out : array([1, 2, 3, 4])

zerosによる零ベクトルの生成

In : zeros(3)
Out : array([ 0.,  0.,  0.])

eyeによる単位行列の生成

In : eye(3)
Out : 
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])

reshapeによるベクトルから行列への変換

In : zeros(10).reshape(2,5)
Out : 
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.]])

他にもいろいろありますが、要はこんな感じで色々な行列やベクトルを生成できるということを知っておくことが重要です。

whereによる特殊な行列の生成

例えば、M1の5以上のところだけ1,それ以外は0になっている行列を生成したいと言った状況があるかもしれません。
そのような場合はwhereメソッドを利用します。

In : where(M1>=5,1,0)
Out : 
array([[0, 0, 0],
       [0, 0, 0],
       [1, 1, 1]])

M1>=5の部分は実は次のような行列になっています。

In : print(M1>=5)
Out : 
array([[False, False, False],
       [False, False, False],
       [ True,  True,  True]], dtype=bool)

つまり、whereはTrue or Falseが入っている行列に対して、Trueの部分に2個目の引数、Falseの部分に3個目の引数が入るわけですね。



計算例

足し算だけでなく、行列っぽい計算はだいたいできます。
例えば転置したければTを利用します。

In : print(M1)
Out : 
array([[1, 2, 3],
       [2, 3, 4],
       [5, 6, 7]])

In : M1.T
Out: 
array([[1, 2, 5],
       [2, 3, 6],
       [3, 4, 7]])

内積はdotでいけます。

In : print(M2)
Out : 
array([[2, 3, 4],
       [3, 4, 5],
       [6, 7, 8]])

In : np.dot(M1,M2)
Out : 
array([[ 26,  32,  38],
       [ 37,  46,  55],
       [ 70,  88, 106]])

全体にルートをかけたりexpの中に入れたりすることも簡単です。

In : np.sqrt(M1)
Out : 
array([[ 1.        ,  1.41421356,  1.73205081],
       [ 1.41421356,  1.73205081,  2.        ],
       [ 2.23606798,  2.44948974,  2.64575131]])
In : np.exp(M1)
Out :
array([[    2.71828183,     7.3890561 ,    20.08553692],
       [    7.3890561 ,    20.08553692,    54.59815003],
       [  148.4131591 ,   403.42879349,  1096.63315843]])

Rユーザーからすると、行列計算でわざわざパッケージを使わないといけないなんて!となるかもしれませんが、まあ最初にNumpyをimportするだけで済む話なので、あまり気にせず使っていきましょう。