正方行列の逆行列を求めたい時に、 LinAlgError: Singular matrix
が出て困った時ありませんか?
numpyの線形代数パッケージであるlinalgにある numpy.linalg.inv
を使うと簡単に逆行列を計算できますが、ある条件の元では LinAlgError: Singular matrix
というエラーが出てしまいます。確認用のコードなので、とりあえず逆行列を求めて次に進みたいんだけど、って時ありませんか?
短い一言アンサーとして、
簡単な確認作業を行なっている時には、この関数の代わりに numpy.linalg.pinv
を使って逆行列(っぽいもの)を計算することができます。
例えば以下のような正方行列があった時に逆行列(inverse matrix)を計算させたいことがあるとします。
A = np.array([[ 2., -1., 0., 0.],
[-1., 2., -1., 0.],
[ 0., -1., 1., 0.],
[ 0., 0., 0., 0.]])
numpy.linalg.inv
を使うと簡単に逆行列を計算できます。しかし、上記の行列では以下のエラーになってしまいます。
import numpy as np
np.linalg.inv(A)
---------------------------------------------------------------------------
LinAlgError Traceback (most recent call last)
<ipython-input-12-ae645f97e1f8> in <module>()
----> 1 np.linalg.inv(A)
/opt/conda/lib/python3.6/site-packages/numpy/linalg/linalg.py in inv(a)
524 signature = 'D->D' if isComplexType(t) else 'd->d'
525 extobj = get_linalg_error_extobj(_raise_linalgerror_singular)
--> 526 ainv = _umath_linalg.inv(a, signature=signature, extobj=extobj)
527 return wrap(ainv.astype(result_t, copy=False))
528
/opt/conda/lib/python3.6/site-packages/numpy/linalg/linalg.py in _raise_linalgerror_singular(err, flag)
88
89 def _raise_linalgerror_singular(err, flag):
---> 90 raise LinAlgError("Singular matrix")
91
92 def _raise_linalgerror_nonposdef(err, flag):
LinAlgError: Singular matrix
ところが、np.linalg.pinvを使えば逆行列が求められます。理解せずにとりあえずは進めたい、という時には、pinv関数
を活用するのはありです。
np.linalg.pinv(A)
array([[ 1., 1., 1., 0.],
[ 1., 2., 2., 0.],
[ 1., 2., 3., 0.],
[ 0., 0., 0., 0.]])
ここからは補足です。時間のない人はここまでで十分です。
そもそもなぜエラーが起こるのか、そして、invとpinvの違いはなんなのかという2点についてです。
そもそもLinAlgError: Singular matrix
ってなぜ起こるのでしょうか?
それは、エラーに書かれている通り、 この行列がSingular Matrix(特異行列)だからです。Singular Matrixとは、行列式(determinant)がゼロになる行列で、逆行列が存在しません。エラーどおりですよね・・・逆行列が存在しないので計算しようとするとエラーになるのはあたりまえですよね。
逆行列が存在する行列を Regular Matrix (正則行列)と呼びます。正則行列は行列式がゼロにならない特徴も持ちます。
でも、正則行列でない行列でも逆行列を計算して次に進めたい、何かの手順の途中だったりすることがあります。私がそうでした。では、このエラーを乗り越えて次に進めたい時、どうしたら良いでしょうか。ここでpinv関数を理解しておきましょう。
pinv関数が求めるものは、擬似逆行列 (pseudo-inverse matrix) と呼ばれる行列です。これは、正則でない行列でも、逆行列のような都合のよい行列として擬逆的に正則行列のように扱えるようにして、逆行列を求めたのです。
pinvを使うことで擬似的に正則行列でない行列を正則行列として扱い、逆行列を求めているのですね。理論を正しく理解するにはもう少し文献を読む必要があると思いますが、コードの確認などしたい場合はとりあえずは pinv
を使っておきましょうね、というお話でした。