読者です 読者をやめる 読者になる 読者になる

numpyのndarrayを使った行列操作練習帳 その1

python

このエントリーをはてなブックマークに追加

pythonのnumpyパッケージで操作の中心となるのはndarrayクラスです。ndarrayクラスは1次元配列にも2次元配列にもそれ以上の次元の配列にもなりますが、ここでは2次元配列、つまり行列として利用する場合に焦点を絞って、操作法を練習します。

行列の作成

行列の作成法はいろいろあります。まずは要素を全列挙する方法。以下は2x5の行列を作成したところです。

>>> numpy.array([[1,2,3,4,5], [6,7,8,9,10]])
array([[ 1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10]])

3x4の零行列を作成するにはzeros()です。

>>> numpy.zeros([3,4])
array([[ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.]])

同様に3x4の、1埋めの行列を作るにはones()を使います。

>>> numpy.ones([3, 4])
array([[ 1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.]])

5で埋めたければ*5すればOKです。

>>> numpy.ones([3,4]) * 2
array([[ 2.,  2.,  2.,  2.],
       [ 2.,  2.,  2.,  2.],
       [ 2.,  2.,  2.,  2.]])

3x3の単位行列の作成にはidentity()を使います

>>> numpy.identity(3)
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])

非正方行列で、対角成分が1でその他が0の行列を作るにはeye()を使います

>>> numpy.eye(4, 3)
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 0.,  0.,  0.]])

ランダムな数字で行列の要素を埋めることもできます。[0, 1)の一様乱数で2x3の行列を作るにはrandom.rand()を使います。

>>> numpy.random.rand(2,3)
array([[ 0.06884044,  0.90537231,  0.43847367],
       [ 0.91323392,  0.22344938,  0.39933672]])

同様に、[10, 13)の範囲の整数で2x3の行列を作るにはrandom.randint()を使います。

>>> numpy.random.randint(10,13,(2,3))
array([[11, 12, 12],
       [10, 10, 10]])

乱数系はNumpyによる乱数生成まとめ - Qiitaに詳しく載っています。

長さ12のベクトルを作って、reshape()で3x4の行列に形を変えます

>>> numpy.arange(12).reshape(3,4)
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

他の行列をクローンコピーします。単にb = aとすると同じオブジェクトを参照してしまうので注意

>>> a = numpy.arange(12).reshape(3,4)
>>> b = a.copy()
>>> b
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

行列同士の演算

説明用に行列を2つ生成します。

>>> a = numpy.arange(12).reshape(3,4)
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> b = numpy.arange(5, 17).reshape(3,4)
>>> b
array([[ 5,  6,  7,  8],
       [ 9, 10, 11, 12],
       [13, 14, 15, 16]])

a + bは予想通り各要素を足し算します。

>>> a + b
array([[ 5,  7,  9, 11],
       [13, 15, 17, 19],
       [21, 23, 25, 27]])

a * bとすると、もしかすると予想に反した動きかもしれませんが、各要素の積を取ります。

>>> a * b
array([[  0,   6,  14,  24],
       [ 36,  50,  66,  84],
       [104, 126, 150, 176]])

a - b, a / bも同様に、各要素ごとに演算を行います。

行列の積をとるにはdot()を使います。行列aと、行列bの転置b.Tの積をとってみます。

>>> a.dot(b.T)
array([[ 44,  68,  92],
       [148, 236, 324],
       [252, 404, 556]])

余談ですが、Python 3.5では行列の積を計算する演算子'@'が使えるようになるようです。参考:PEP 465 -- A dedicated infix operator for matrix multiplication

numpyのndarrayを使った行列操作練習帳 その2 - minus9d's diary に続きます。

補足

numpyにはndarrayの他に、行列に特化したクラス(matrixクラス)も用意しているようですが、あまり使われていないようです。参考:python - Matrix and array multiplication in numpy - Stack Overflow

参考