3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

固有値から固有ベクトルを求める

Posted at

今話題の固有値から固有ベクトルを求める論文を実装してみた。
https://arxiv.org/abs/1908.03795

(Twitter 上でRで実装している人をすでに観測しているので、多分 $N$ 番煎じではあることを承知してこの記事を書いてる)

正確には $n$ 次 Hermitian Matrix $A$ に対し、固有ベクトルの各要素の大きさの2乗を求める。
そのため、複素数の位相成分はこの手法では求まらない。
また、Hermitian ではない正方行列にこの手法を適用しても、固有ベクトルの各要素の大きさは求まるとは限らない。
(Hermitian の固有ベクトルは直交するという性質を証明に使っているため)

$A$ の$i$ 番目の固有ベクトル$\mathbf{v}_i$と固有値 $\lambda_i$ と定義する。
また、$A$ の$j$ 行と$j$ 列を削除した行を $M_j$ とする。

M_j = 
\left[ \begin{array}{ccc|ccc}
A_{1,1} &\cdots& A_{1,j-1} & A_{1,j+1} &\cdots& A_{1,n} \\
\vdots & \ddots & \vdots & \vdots & \ddots & \vdots \\
A_{j-1,1} &\cdots& A_{j-1,j-1} & A_{j-1,j+1} &\cdots& A_{j-1,n} \\ \hline
A_{j+1,1} &\cdots& A_{j+1,j-1} & A_{j+1,j+1} &\cdots& A_{j+1,n} \\
\vdots & \ddots & \vdots & \vdots & \ddots & \vdots \\
A_{n,1} &\cdots& A_{n,j-1} & A_{n,j+1} &\cdots& A_{n,n}
\end{array} \right]

$A_{i,j}$ は$A$ の$i$ 行$j$ 番目の要素。
また、$M_j$ の$k$番目の固有値を$\mu^{(j)}_k$ と定義する。

すると$\mathbf{v}_i$ の$j$ 番目の要素$v_{i,j}$ に対して、次のような式が成立する(論文の式(2)にあたる)。

|v_{i,j}|^2 \prod_{k=1,k\neq i}^n (\lambda_i - \lambda_k)
= \prod_{k=1}^{n-1} (\lambda_i - \mu^{(j)}_k)

この式を使えば、固有値 $\lambda_i, \mu^{(j)}_k$ から固有ベクトルの各要素の大きさの2乗$|v_{i,j}|^2$ が求まる。

これを Python3 で実装してみた。

import numpy as np;
import matplotlib.pyplot as plt;


def calc_eigenvector (A, i):
    n,_ = A.shape;
    v = np.zeros ((n,1));   # 求める固有ベクトルの平方
    lams,_ = np.linalg.eig (A);
    
    for j in range (n):
        x = [xx for xx in range (n)];
        x.remove (j);
        Mj = A[:,x][x,:];
        muj, _ = np.linalg.eig (Mj);

        numerator = (lams[i] - muj).prod ();
        denominator = np.delete (lams[i]-lams, i).prod ();

        v[j,0] = numerator / denominator;
    
    return v;

N = 10;
A = np.random.randn (N,N);
A = A + A.T;
_, vs = np.linalg.eig (A);

plt.figure ();
plt.plot([0,1],[0,1]);
v_t = vs[:,0];
v_c = calc_eigenvector (A,0);

plt.scatter (v_t**2, v_c);
plt.show ();

calc_eigenvector が先の数式に基づいて固有ベクトルを求める関数である。
これを実行する。
eigenvector.png
横軸がnumpy.linalg.eig で求めた0番目の固有ベクトルの各要素の大きさの二乗、
縦軸が関数で求めた結果。
$y=x$ の直線上にちゃんと乗ってる。すごい。

全ての固有値でやったものが以下の図になる。
eigenvector2.png
これもちゃんと$y=x$に乗ってることが確認できた。

3
2
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
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?