LoginSignup
40
25

More than 5 years have passed since last update.

Pythonで特異値分解してみる

Posted at

やりたいこと:線型代数の特異値分解(singular value decomposition)を確かめてみる

$m$行$n$列の行列$A$に対して、

  • $U$:$m\times m$のユニタリ行列
  • $\Sigma$: $m\times n$の実対角行列(成分は非負)
  • $V$: $n\times n$のユニタリ行列

が存在して、下記が成立

A=U\Sigma \overline{V^T}

ここで上線は複素共役(complex conjugate)、$^T$は転置(transpose)。

(サンプル)行列の定義

A=\left(
\begin{matrix}
1 & 2 \\
3 & 4 
\end{matrix}
\right)
> import numpy as np
> A = np.array([[1,2],[3,4]])

一応、中身のck

> A 
array([[1, 2],
       [3, 4]])

早速、SVDしてみる

U, s, V = np.linalg.svd(A, full_matrices=True)

返り値が3つです。

中身のck

> U
array([[-0.40455358, -0.9145143 ],
       [-0.9145143 ,  0.40455358]])
> s
array([ 5.4649857 ,  0.36596619])
> V
array([[-0.57604844, -0.81741556],
       [ 0.81741556, -0.57604844]])

なんか、$s$が潰れてしまってる感じですが、実体は対角成分だけ、つまり

> np.diag(s)
array([[ 5.4649857 ,  0.        ],
       [ 0.        ,  0.36596619]])

が実体の行列です。

元に戻るか確認

A=U\Sigma \overline{V^T}

を確認してみます。

>np.dot(np.dot(U, np.diag(s)),V)
array([[ 1.,  2.],
       [ 3.,  4.]])

いい感じですね♪
⇒ここで、行列$V$は実行列で求まっているため、複素共役はしなくて良いですが、転置は取らないものが返り値として戻ってきているようですね。

念のための確認

Uがユニタリ行列

> np.dot(U, U.T)
array([[  1.00000000e+00,   2.77555756e-16],
       [  2.77555756e-16,   1.00000000e+00]])

対角成分でないところに$0$でない値が入ってしまうのは数値的に仕方ないですね。

Vもユニタリ行列

> np.dot(V, V.T)
array([[ 1.,  0.],
       [ 0.,  1.]])
40
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
25