やりたいこと:線型代数の特異値分解(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.]])