研究で線形な方程式を扱う場面は非常に多いですよね。
これは線形な問題は非常に扱いやすく,支配方程式自体が非線形でもテイラー展開などによって線形近似して扱うことが多いためです。
更に近年は機械学習が流行になっていることもあって益々行列やベクトル(配列)を扱う場面は増加している傾向にあると思われます。
このような実情の中,「行列演算をどの言語の何のモジュールで行おう…」と悩んでいる方もいらっしゃるのではないでしょうか。
それならnumpy一択です!!そういう訳です。理由は聞かず今すぐnumpyをインストールしてください(過激派)
実は僕は学生時代,機械学習を研究していたのですが,C++を使ってました。
勿論for文いっぱい書くような人はC++凄く便利なのですが,行列を扱うなら話は変わってきます。
行列演算はpythonやMATLABが便利です!
更にpython, MATLABはインタプリタ型の言語なので試作の段階ではかなり効率が良いため近年では企業でも盛んに取り入れられています。
目次
環境構築
環境構築については特に拘りが無ければAnacondaをインストールするのが良いかと思います。インストール方法は以下の記事をご参照ください。
Anacondaにはnumpyが標準で含まれておりますので入れてしまえば直ぐに使えます。
もしAnacondaを使いたくないという方はpythonを入れている状態で以下のコマンドを実行して下さい。
$ pip install numpy
これでnumpyが入りました。
numpyで行列・ベクトルを作ろう!
以降対話モードかプログラムファイルで実行して下さい。
他のライブラリでもそうですが,まずはインポートしましょう。
>>> import numpy as np
これで使える状態になりました。as npという部分は「np」という名前でnumpyを使いますよという宣言です。
別にnpでなくてもいいのですが,殆どの書籍や記事でnpとしているので合わせるのが無難だと思います。
次に配列(ベクトル)を定義してみましょう。例として$\boldsymbol{x} = \begin{pmatrix} 5 & 6 & 3 \end{pmatrix}^{T}$という配列を作ってみます。
>>> x = np.array([5, 6, 3])
これで配列が作れました。では次に行列を作ってみましょう。例として$\boldsymbol{A} = \begin{pmatrix} 5 & 6 & 3 \\ 3 & 1 & 5 \end{pmatrix}^{T}$という行列を作ってみます。
>>> A = np.array([[5, 6, 3], [3, 1, 5]])
できましたか?これは配列という視点で見ると2次元配列ということになります。
多次元配列になってくると括弧が多くなって間違えやすいので気をつけて下さい。
次に配列の形を見る方法です。先程作った$\boldsymbol{A}$の形を見てみましょう。
>>> print(A.shape) (2, 3)
こんな形で$2\times 3$ということがわかります。これは行列で言うところの(行数)×(列数)となっています。
例えば行数だけ欲しいというときは
>>> A.shape[0]
のようにしたら抽出できます。
では次に少し特殊な配列の作り方です。
要素が全て0の配列は以下のようにして生成できます。($2\times 3$の2次元配列の例です)
>>> A = np.zeros([2,3])
次は要素が全て1の配列です。サイズは同様です。
>>> A = np.ones([2,3])
要素が全て$a$のものを作りたかったらこれに$\times a$したらいいですね。
では次は全ての要素が$[0, 1]$の区間の乱数となる配列の生成です。
>>> A = np.random.rand(2,3)
これは大括弧がつかないので注意してください。
最後に数字は入れずに領域だけ確保する方法をご紹介します。この方法のほうが上2つに比べて速いです。
>>> A = np.empty([2,3])
ここで一つだけ注意です。
最初のうちはあまり意識しなくていいかもしれませんが,慣れてきたら型を先に指定する方がベターです。
その場合は配列のサイズを指定した後に型を指定してあげましょう。emptyの例をあげます。
>>> A = np.empty([2,3], dtype=np.float64)
この例では64bitのfloat(浮動小数点数)型に指定してみました。
型指定をする意識することはプログラミング力向上につながりますので余裕がある方は少し意識してみましょう。
行列演算してみよう!
ではメインの行列演算です。
足し算・引き算
足し算です。これはスカラーと同様の演算子で実行できます。行列のサイズが違うもの同士で実行しようとするとエラーになりますのでご注意ください。
以下ランダムな行列$\boldsymbol{A, B}$に対して加算・減算をする例です。
A = np.random.rand(2,3) B = np.random.rand(2,3) # 足し算 A + B # 引き算 A - B
簡単ですね。因みに行列(若しくはベクトル)の全ての要素に同じ数を足す(引く),または掛ける(割る)場合には
A+3 A*3
のように書いても大丈夫です。わざわざonesを使わなくていいんですね。便利!
ちなみに数学でいうとスカラーと行列との演算ですね。
内積・行列の掛け算(作用)
pythonは1次元の配列(ベクトル)については列ベクトルなのか行ベクトルなのかということをあまり気にせずに演算ができます。
内積と行列の掛け算は関数としては同じものを使うのですが,ベクトルの内積を取る際に(行ベクトル)×(列ベクトル)にしなきゃということは考える必要がないのです。
ではまずは内積の例です。一応復習すると内積はベクトルの要素同士の掛け算を足し合わせたものでしたね。
x = np.random.rand(3) y = np.random.rand(3) # 内積 np.dot(x, y)
次に行列の掛け算です。ここでの注意は($m\times n$行列)($ n\times k$行列)のように作用させる行列の列数と作用される行列の行数が一致しなければなりません。
以下は行列の掛け算の例になります。
A = np.random.rand(2, 3) B = np.random.rand(3, 5) # 行列の掛け算 np.dot(A, B)
このように内積と同じ関数で実現できます。
実はここまでの例ではdotという関数を使っていましたが,matmulという殆ど同じような関数があります。
dotの方がよく使われている気がしますが,matmulの方が少し計算が速い気がします(ちゃんと調べてない)。
もし興味がある方は試してみて下さい。
まとめ
今回はnumpyを使った行列・ベクトルの定義と行列演算の方法をご紹介しました。
numpyは非常に手軽に行列を扱えるためかなり便利だと思っています。
参考書としては以下のものがオススメです。numpyの細かなテクニックが多く載っており,研究等でpythonを使う方は手元に置いておいて損はないと思います。
それではお疲れ様でした!