<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>固有値問題 - まったり勉強ノート</title>
	<atom:link href="https://www.mattari-benkyo-note.com/tag/%E5%9B%BA%E6%9C%89%E5%80%A4%E5%95%8F%E9%A1%8C/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.mattari-benkyo-note.com</link>
	<description>shuの日々の勉強まとめ</description>
	<lastBuildDate>Mon, 04 Apr 2022 00:02:45 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.3</generator>
<site xmlns="com-wordpress:feed-additions:1">189243286</site>	<item>
		<title>[勉強ノート] 「線形計算の数理」 7.7.1 Arnoldi法</title>
		<link>https://www.mattari-benkyo-note.com/2022/04/04/theoretical-numerical-linear-algebra-arnoldi-method/</link>
					<comments>https://www.mattari-benkyo-note.com/2022/04/04/theoretical-numerical-linear-algebra-arnoldi-method/#respond</comments>
		
		<dc:creator><![CDATA[Shuji Suzuki (shu)]]></dc:creator>
		<pubDate>Sun, 03 Apr 2022 23:48:06 +0000</pubDate>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[numpy]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[固有値問題]]></category>
		<category><![CDATA[線形計算の数理]]></category>
		<guid isPermaLink="false">https://www.mattari-benkyo-note.com/?p=1299</guid>

					<description><![CDATA[<p>前回に引き続き線形計算の数理の固有値問題で紹介されていたアルゴリズムについての解説になります。今日はその中のArnoldi法についての説明です。 このArnoldi法をはじめとしたRayleigh-Ritzの技法ベースの [&#8230;]</p>
<p>The post <a href="https://www.mattari-benkyo-note.com/2022/04/04/theoretical-numerical-linear-algebra-arnoldi-method/">[勉強ノート] 「線形計算の数理」 7.7.1 Arnoldi法</a> first appeared on <a href="https://www.mattari-benkyo-note.com">まったり勉強ノート</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>前回に引き続き線形計算の数理の固有値問題で紹介されていたアルゴリズムについての解説になります。今日はその中のArnoldi法についての説明です。</p>



<p>このArnoldi法をはじめとしたRayleigh-Ritzの技法ベースの手法は個人的には初見で「どれもアルゴリズムはわかるけど、なんでそれでうまくいくのさっぱり」という感じだったので、本の解説の中で自分のわからなかった部分を補足しながら説明をしていければと思います。</p>



<p>Pythonの実装はこちらにあります。<br><a href="https://github.com/shu65/theoretical-numerical-linear-algebra/blob/main/%E7%B7%9A%E5%BD%A2%E8%A8%88%E7%AE%97%E3%81%AE%E6%95%B0%E7%90%86_7_7_1_Arnoldi%E6%B3%95.ipynb" title="">https://github.com/shu65/theoretical-numerical-linear-algebra/blob/main/%E7%B7%9A%E5%BD%A2%E8%A8%88%E7%AE%97%E3%81%AE%E6%95%B0%E7%90%86_7_7_1_Arnoldi%E6%B3%95.ipynb</a></p>



<h2 class="wp-block-heading">Arnoldi法とは</h2>



<p>ある次元の不変部分空間\(E\)の近似空間\(F\)が与えられたとき、\(E\)に対応する固有値と固有ベクトルの近似値を近似空間\(F\)を使って求めるRayleigh-Ritzの技法というものがあります。</p>



<p>このRayleigh-Ritzの技法ベースの手法の一つで、Krylov部分空間と呼ばれる空間で近似空間を作る手法がArnoldi法です。大規模な行列の際、QR法などの固有値、固有ベクトルを求めるアルゴリズムを直接適用すると計算量や必要なメモリサイズの観点で適用が難しい場合があります。このような場合にArnoldi法は利用されます。</p>



<p>Arnoldi法のアルゴリズムやRayleigh-Ritzの技法、Krylov部分空間についてはこの後より詳しく説明していきます。</p>



<h2 class="wp-block-heading">Arnoldi法のアルゴリズム</h2>



<p>まずはArnoldi法のアルゴリズム説明します。本ではアルゴリズム全体についてちゃんと書かれておらず、いろいろなサイトを調べましたが、ちょっとずつ違うので、今回は近似固有値、近似固有ベクトルまで求めるシンプルなものを説明します。</p>



<p>Arnoldi法は入力として以下のものを取ります。</p>



<ul class="wp-block-list"><li>\( A\): 固有値、固有ベクトルを計算する複素\( n \)次正方行列</li><li>\(\boldsymbol{x}_0\): \(\boldsymbol{x}_0 \ne 0\)の\( n \)次元ベクトル</li><li>\(m\): 生成する部分空間の次元数。\(m \le n\)</li></ul>



<p>これらを入力として以下のように計算していきます。</p>



<ol class="wp-block-list"><li>\( A \) と \(\boldsymbol{x}_0\)を入力に取る。</li><li>\(H\)をすべての要素が0の行列として初期化する。</li><li>\(\boldsymbol{v}_0 := \boldsymbol{x}_0/||\boldsymbol{x}_0|| \)</li><li>\(k\)を\(0\) から \(m-1\)まで以下を繰り返す。<ol><li>\(\boldsymbol{w} := A\boldsymbol{v}_k\)</li><li>\(i\)を\(0\) から \(k\)まで以下を繰り返す。<ol><li>\(H_{i,k} := \boldsymbol{v}_i^H \boldsymbol{w}\)</li><li>\(\boldsymbol{w} := \boldsymbol{w} &#8211; H_{i,k} \boldsymbol{v}_i\)</li></ol></li><li>\(H_{k+1,k} := || \boldsymbol{w} ||\)</li><li>\(\boldsymbol{v}_{k+1} := \boldsymbol{w} / H_{k+1,k}\)</li></ol></li><li>\(H\)の固有値と固有ベクトルを求め、それぞれをRitz値(\(\theta_0, &#8230;, \theta_m\))とRitzベクトル(\( \boldsymbol{y}_0, &#8230;, \boldsymbol{y}_m\))とする</li><li>\( V = [\boldsymbol{v_0}, &#8230;, \boldsymbol{v}_m]\) とし、以下の計算を(k)が(0) から (m)まで繰り返す。<ol><li>\(\boldsymbol{z}_k = \boldsymbol{V}y_k\)</li></ol></li><li>Ritz値(\(\theta_0, &#8230;, \theta_m\))を\(A\)の固有値の近似値、\(\boldsymbol{z}_k\)を\(A\)の固有値の近似固有ベクトルとして出力する</li></ol>



<p>1-4は正規直交基底を生成しつつ、\(H\)を作っているためわかりにくいですが、正規直交基底を作っている部分は\( \boldsymbol{x}_0, A\boldsymbol{x}_0, A^2\boldsymbol{x}_0, &#8230;, A^{m-1}\boldsymbol{x}_0\) に対してグラムシュミットの正規直交化法を適用しているだけです。</p>



<p>なので、アルゴリズム自体は難しいものではないと思っています。</p>



<p>ちなみにこのアルゴリズムで\(H\)は対角成分の一つ下の要素も値が埋まっている上三角行列であるHessenberg行列になります。この際、アルゴリズムの4.3.行目が対角成分の一つ下の要素を代入しているところになります。ここで、この4.3.行目で代入する値は、ここまで生成した正規直交基底\(\boldsymbol{v}_0, &#8230;, \boldsymbol{v}_k\)で\(A^k\boldsymbol{x}_0\)を表しきれなかったベクトルのノルムを代入していると見ることができます。実はこのノルムが0に近ければ、ここまでで生成した正規直交基底\(\boldsymbol{v}_0, &#8230;, \boldsymbol{v}_k\)で\(A^k\boldsymbol{x}_0\)を表現できるとみることができ、これ以降のKrylov列の要素も表現できます。このため、アルゴリズムのバリエーションとしては4.3.行目のノルムの値をチェックして、0に近ければそこで正規直交基底の生成をストップするというものもあります。</p>



<p>このアルゴリズムにおいて\(m\)は何個の固有値、固有ベクトルを求めるかや近似精度をどこまで上げるか？など重要なものを決定づけています。ただ、実際にArnoldi法でいろいろ実験をしてみればわかりますが、\(m\)を事前に決めておくのは難しく、実用を考えると後ほど紹介する残差ベクトルを使って、近似空間を拡大するかどうか判断するようなアルゴリズムのほうが使い勝手は良いかと思います。</p>



<p>ちなみに1-4までの処理を指してArnoldi法と言っているサイトや講義資料もありました。なので、一体どこからどこまでの処理がArnoldi法かはわからないですが、今回は固有値を求めるところまでをArnoldi法と呼びます。</p>



<h2 class="wp-block-heading">Arnoldi法によってなぜ固有値、固有ベクトルの近似値が求まるのか？</h2>



<p>先ほど説明した通り、Arnoldi法のアルゴリズム自体は難しいことをしてないのですが、それがなぜうまくいくのかは本を読んでもわからないことが多かったので詳しく説明していきます。</p>



<h3 class="wp-block-heading">Rayleigh-Ritzの技法 / 射影法</h3>



<p>Arnoldi法がなぜうまくいくかを説明するために、Rayleigh-Ritzの技法（または射影法と呼ぶ場合もあります)をまずは説明していきます。</p>



<p>Rayleigh-Ritzの技法は不変部分空間\(E\)の近似空間\(F\)が与えられたとき、\(E\)に対する固有値、固有ベクトルの近似値を\(F\)を使って求める手法全般を指します。</p>



<p>もう少し具体的に説明していきます。ある\(m\)次元不変部分空間\(E\)を\(A\)の\(m\)本の固有ベクトル \(\boldsymbol{z}_{i_1}, &#8230; ,\boldsymbol{z}_{i_m}\)で張られた空間であるとします。ここでポイントですが、\(E\)は\(A\)のすべての固有ベクトルで張られた空間である必要はなく、一部の固有ベクトルだけで張られた空間であることを注意してください。また、\(\boldsymbol{z}_{i_1}, &#8230;, \boldsymbol{z}_{i_m}\)に対応する\(A\)の固有値を\(\lambda_{i_1}, &#8230; \lambda_{i_m}\)とします。このとき、固有値、固有ベクトルの性質から以下の関係が成り立ちます。</p>



<p>$$ \begin{align*} <br>AZ_m = Z_m\Lambda_m \tag{7.42.1}<br>\end{align*} $$</p>



<p>ただし、\(Z_m = [\boldsymbol{z}_{i_1}, &#8230; \boldsymbol{z}_{i_m}]\)、\(\Lambda_m = \text{diag}(\lambda_{i_1}, &#8230; \lambda_{i_m})\)です。</p>



<p>次に\(E\)の任意の正規直交基底\( \boldsymbol{u}_1, &#8230; , \boldsymbol{u}_m\)をとって、\(U=[\boldsymbol{u}_{1}, &#8230; \boldsymbol{u}_{m}]\)とします。\( \boldsymbol{u}_1, &#8230; , \boldsymbol{u}_m\)はAの固有ベクトルとは別もので大丈夫です。\(U\)は正規直交基底なので以下が成り立ちます。</p>



<p>$$ \begin{align*} <br>U^HU = I_m \tag{7.42.2}<br>\end{align*} $$</p>



<p>この\(U\)を使うと\(Z_m\)はある\(m\)次行列\(Y\)を使って以下のように書けます。</p>



<p>$$ \begin{align*} <br>Z_m = UY \tag{7.42.3}<br>\end{align*} $$</p>



<p>これは単純に\(Z_m\)を\(\boldsymbol{u}_{1}, &#8230; \boldsymbol{u}_{m}\)を使って表すことができることを指しています。</p>



<p>そして、式(7.42.1)の左から\(U^H\)を掛け、式(7.42.2)、(7.42.3)を使って変形すると以下のようになります。</p>



<p>$$ \begin{align*} <br>U^HAZ_m =&amp; U^HZ_m\Lambda_m \\<br>U^HAUY =&amp; U^HUY\Lambda_m \\<br>U^HAUY =&amp; I_mY\Lambda_m \\<br>U^HAUY =&amp; Y\Lambda_m<br>\tag{7.42}<br>\end{align*} $$</p>



<p>ここで分かりやすいように\(U^HAU=B\)と置くと以下のようになります。</p>



<p>$$ \begin{align*} <br>BY =&amp; Y\Lambda_m<br>\tag{7.42.4}<br>\end{align*} $$</p>



<p>これは\(m\)次行列\(B\)に対する固有値問題の形になっています(\(Y\)の列ベクトルが固有ベクトル、\(\Lambda_m\)の対角成分が固有値)。ここで\(m \le n\)であることを思い出すと、\(A\)よりも小さい行列\(B\)の固有値を求めれば\(A\)の固有値の一部がわかることを示しています。また、\(A\)の固有ベクトルに関しても、式(7.42.3)から簡単に求めることができます。</p>



<p>ここまでは不変部分空間\(E\)を使っていましたが、実際には\(E\)は未知です。なので、\(E\)を近似する部分空間\(F\)を適当に選ぶことにします。\(F\)の正規直交基底\(\boldsymbol{v}_{1}, &#8230; \boldsymbol{v}_{m}\)を並べた行列\(V=[\boldsymbol{v}_{1}, &#8230; \boldsymbol{v}_{m}]\)とします。この\(V\)を使って式(7.42)の\(U\)を\(V\)に置き換えたような以下の式を考えます。</p>



<p>$$ \begin{align*} <br>V^HAV\boldsymbol{y} =&amp; \theta\boldsymbol{y}<br>\tag{7.42}<br>\end{align*} $$</p>



<p>これは\(m\)次行列\(V^HAV\)の固有値問題になっています。この\(V^HAV\)の固有値問題を何等かの方法(QR法など)で解き、\(\theta\)を\(A\)の固有値の近似値、\(\boldsymbol{z} = V\boldsymbol{y}\)を\(A\)の固有ベクトルの近似とします。</p>



<p>これをRayleigh-Ritzの技法といい、近似固有値\(\theta\)はRitz値、近似固有ベクトル\(\boldsymbol{z}\)をRitzベクトルといいます。</p>



<p>通常は\(m\)を事前に決めておくのではなく、以下の残差ベクトル\(\boldsymbol{r}\)を導入して近似部分空間\(F\)を拡大するかどうかを判断します。</p>



<p>$$ \begin{align*} <br>\boldsymbol{r} =&amp; A\boldsymbol{z} &#8211; \theta\boldsymbol{z}<br>\tag{7.43.1}<br>\end{align*} $$</p>



<p>\(\theta\)と\(\boldsymbol{z}\)がAの固有値、固有ベクトルに十分近ければ\(r\)は十分小さくなります。このため、\(r\)が十分小さければ\(\theta\)と\(\boldsymbol{z}\)を採用し、\(r\)が大きいときは近似部分空間\(F\)を拡大します。</p>



<p>ちなみにRayleigh-Ritzの技法は近似部分空間をどういう風に作るかは特に言及されていません。ただ、このRayleigh-Ritzの技法ではどういう部分空間を作るかによって、\(A\)の固有値のどの部分の固有値を近似するのか（絶対値が最大となる固有値など）や近似精度などが決定いします。このため、この近似部分空間をどう作るかは重要なポイントになります。</p>



<p>Arnoldi法はこの近似部分空間としてKrylov部分空間を利用している手法になります。また、Arnoldi法以外のRayleigh-Ritzの技法ベースの手法としては以下のものがあります。</p>



<ul class="wp-block-list"><li>Lanczos法: エルミート行列に対するArnoldi法</li><li>Jacobi-Davidson法: Krylov部分空間を使わずに部分空間の列を構成する手法</li></ul>



<h3 class="wp-block-heading">Krylov部分空間</h3>



<p>ここではArnoldi法で利用されているKrylov部分空間について説明します。</p>



<p>ベクトル\(\boldsymbol{x}\)に行列\(A\)のべき乗掛けて生成される列 \( \boldsymbol{x}, A\boldsymbol{x}, A^2\boldsymbol{x},&#8230;\) (Krylov列と言います)の最初の\(k\)個のベクトルの張る部分空間</p>



<p>$$ \begin{align*} <br>\mathcal{K}_k(A, \boldsymbol{x}) = \text{span}(\boldsymbol{x}, A\boldsymbol{x}, A^2\boldsymbol{x}, &#8230;, A^{k-1}\boldsymbol{x})<br>\tag{4.94}<br>\end{align*} $$</p>



<p>を\(k\)次のKrylov部分空間と呼びます。</p>



<p>Krylov部分空間の特徴として本で紹介されていることとしてはKrylov部分空間は\(\boldsymbol{x}\)を含む最小の\(A\)不変部分空間に達するまで単調増加するという特徴があります。(詳しくは「線形計算の数理」の4.3 Krylov部分空間を参照)</p>



<p>これに加え、固有値問題を解くアルゴリズムの一つであるべき乗法ではKrylov列のベクトルを正規化したものが\(A\)の固有ベクトルに収束することを利用していることからわかる通り、Krylov部分空間は\(A\)の固有ベクトル（特に絶対値が最大となる固有値の固有ベクトル）の成分を多く持つような空間を生成することができます。</p>



<p>べき乗法についてはこちらで詳しく紹介していますので、参考にしてみてください。</p>



<figure class="wp-block-embed is-type-wp-embed is-provider-まったり勉強ノート wp-block-embed-まったり勉強ノート"><div class="wp-block-embed__wrapper">
<blockquote class="wp-embedded-content" data-secret="rKhLtn7uym"><a href="https://www.mattari-benkyo-note.com/2022/03/24/theoretical-numerical-linear-algebra-power-method/">[勉強ノート] 「線形計算の数理」 7.2.1 べき乗法 基本形</a></blockquote><iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted"  title="&#8220;[勉強ノート] 「線形計算の数理」 7.2.1 べき乗法 基本形&#8221; &#8212; まったり勉強ノート" src="https://www.mattari-benkyo-note.com/2022/03/24/theoretical-numerical-linear-algebra-power-method/embed/#?secret=GJBXXnK25e#?secret=rKhLtn7uym" data-secret="rKhLtn7uym" width="600" height="338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
</div></figure>



<p>この二つの特性からKrylov部分空間を利用することでArnoldi法は\(A\)の固有値、固有ベクトルを\(A\)の次元よりもはるかに小さい行列を利用して計算することが可能となります。</p>



<p>また、Krylov列からグラムシュミットの正規直交化法によって正規直交基底\(\boldsymbol{v}_{1}, &#8230; \boldsymbol{v}_{m}\)を並べた行列\(V=[\boldsymbol{v}_{1}, &#8230; \boldsymbol{v}_{m}]\)とします。このとき、</p>



<p>$$ \begin{align*} <br>H = V^HAV <br>\tag{4.50}<br>\end{align*} $$</p>



<p>という風に作った\(H\)は\(m \times m\)のHessenberg行列で，上三角行列に下1行を追加した形の行列になることが知られています。Arnoldi法のアルゴリズムでは式(4.50)計算を直接やらずに、Krylov列のグラムシュミットの正規直交化を計算しながら\(H\)の生成も同時にやっています。ちなみに、この\(H\)と\(V\)を求める部分のアルゴリズムを本ではArnoldi算法という名前で紹介しています。<br>この\(H\)はHessenberg行列であるため、行列の対角成分の2つ以下が0になっています。このため、QR法なで固有値を求める際、QR分解で0の部分をスキップするなど高速化が可能となり、固有値を求めるには都合の良い行列になっています。</p>



<p>QR法についてはこちらの記事で紹介していますので、参考にしてみてください。</p>



<figure class="wp-block-embed is-type-wp-embed is-provider-まったり勉強ノート wp-block-embed-まったり勉強ノート"><div class="wp-block-embed__wrapper">
<blockquote class="wp-embedded-content" data-secret="xQCpPw62w6"><a href="https://www.mattari-benkyo-note.com/2022/03/29/theoretical-numerical-linear-algebra-qr-method/">[勉強ノート] 「線形計算の数理」7.4 QR法</a></blockquote><iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted"  title="&#8220;[勉強ノート] 「線形計算の数理」7.4 QR法&#8221; &#8212; まったり勉強ノート" src="https://www.mattari-benkyo-note.com/2022/03/29/theoretical-numerical-linear-algebra-qr-method/embed/#?secret=dhT00Hc3Bc#?secret=xQCpPw62w6" data-secret="xQCpPw62w6" width="600" height="338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
</div></figure>



<h2 class="wp-block-heading">Pythonによる実装</h2>



<p>ここからは紹介したアルゴリズムをPythonで実装したものを説明します。</p>



<p>実装は以下の通りです。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-python" data-file="arnoldi_iteration" data-lang="Python"><code>import numpy as np

def arnoldi_method(a, x0, m):
  if m &gt; a.shape[0]:
    raise ValueError
  n = a.shape[0]
  h = np.zeros((m, m))
  v = np.zeros((n, m))

  v0 = x0 / np.linalg.norm(x0)
  v[:, 0] = v0

  k = 0
  for k in range(m):
    k = k
    w = a @ v[:, k]
    for j in range(k+1):
        v_j = v[:, j]
        h[j,k] = v_j.T @ w
        w = w - h[j,k]*v_j

    if k+1 &lt; m:
        h[k+1, k] = np.linalg.norm(w)
        v[:, k+1] = w/h[k+1, k]
  
  ritz_values, ritz_vectors = np.linalg.eig(h)
  eigenvectors = v @ ritz_vectors
  return ritz_values, eigenvectors</code></pre></div>



<p>これを以下のように実行して絶対値最大となる固有値とその固有ベクトル、そのときの残差のノルムを出力してみます。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-python" data-file="arnoldi_iteration_main" data-lang="Python"><code>import numpy as np

np.random.seed(1)
a_matrix = np.random.rand(8, 8)

n = a_matrix.shape[0]
x0 = np.ones(n)
eigenvalues, eigenvectors = arnoldi_method(a_matrix, x0, 4)
orders = np.argsort(-np.abs(eigenvalues))

print(&quot;eigenvalue:&quot;, eigenvalues[orders[0]])
print(&quot;eigenvector:&quot;)
print(eigenvectors[:, orders[0]])
r = a_matrix @ eigenvectors[:, orders[0]] - eigenvalues[orders[0]] * eigenvectors[:, orders[0]]
norm_r = np.linalg.norm(r)
print(&quot;||r||:&quot;, norm_r)</code></pre></div>



<p>この出力は以下のようになります。</p>



<pre class="wp-block-preformatted">eigenvalue: (3.4995258474334907+0j)
eigenvector:
[0.2046176 +0.j 0.38710413+0.j 0.42003848+0.j 0.32821558+0.j
 0.48492918+0.j 0.38776328+0.j 0.18715778+0.j 0.32183775+0.j]
||r||: 0.004572773990371693</pre>



<p>また、\(m\)を変化させると近似固有値、近似固有ベクトルの近似精度が良くなるのでそれも見てみます。以下のように\(m\)を変化させながら、絶対値が最大となる固有値の残差ノルムをプロットすると以下のようになります。</p>



<div class="wp-block-image"><figure class="aligncenter size-full is-resized"><img fetchpriority="high" decoding="async" src="https://www.mattari-benkyo-note.com/wp-content/uploads/2022/04/norm_r_plot.png" alt="" class="wp-image-1380" width="415" height="275" srcset="https://www.mattari-benkyo-note.com/wp-content/uploads/2022/04/norm_r_plot.png 395w, https://www.mattari-benkyo-note.com/wp-content/uploads/2022/04/norm_r_plot-300x199.png 300w" sizes="(max-width: 415px) 100vw, 415px" /><figcaption>絶対値が最大となる近似固有値の残差ノルム</figcaption></figure></div>



<p>このように\(m\)が大きくなるにつれて残差が0に近づいていくことがわかります。</p>



<h2 class="wp-block-heading">終わりに</h2>



<p>今回はArnoldi法について紹介しました。今回のArnoldi法は読んだだけではわからないことが多く、実際に実装していろいろ値を変えてみてわかることが多かった印象があります。このため、実装まで作ってよかったと考えています。</p><p>The post <a href="https://www.mattari-benkyo-note.com/2022/04/04/theoretical-numerical-linear-algebra-arnoldi-method/">[勉強ノート] 「線形計算の数理」 7.7.1 Arnoldi法</a> first appeared on <a href="https://www.mattari-benkyo-note.com">まったり勉強ノート</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.mattari-benkyo-note.com/2022/04/04/theoretical-numerical-linear-algebra-arnoldi-method/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1299</post-id>	</item>
		<item>
		<title>[勉強ノート] 「線形計算の数理」7.4 QR法</title>
		<link>https://www.mattari-benkyo-note.com/2022/03/29/theoretical-numerical-linear-algebra-qr-method/</link>
					<comments>https://www.mattari-benkyo-note.com/2022/03/29/theoretical-numerical-linear-algebra-qr-method/#respond</comments>
		
		<dc:creator><![CDATA[Shuji Suzuki (shu)]]></dc:creator>
		<pubDate>Mon, 28 Mar 2022 23:19:52 +0000</pubDate>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[固有値問題]]></category>
		<category><![CDATA[線形計算の数理]]></category>
		<guid isPermaLink="false">https://www.mattari-benkyo-note.com/?p=1250</guid>

					<description><![CDATA[<p>今日の記事は前回に引き続き「線形計算の数理」の固有値問題パートの内容です。今回は7.4 「QR法」についてアルゴリズムの概要となぜそれがうまくいくのか？、Pythonによる実装の3つについて説明していきます。 pytho [&#8230;]</p>
<p>The post <a href="https://www.mattari-benkyo-note.com/2022/03/29/theoretical-numerical-linear-algebra-qr-method/">[勉強ノート] 「線形計算の数理」7.4 QR法</a> first appeared on <a href="https://www.mattari-benkyo-note.com">まったり勉強ノート</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>今日の記事は前回に引き続き「線形計算の数理」の固有値問題パートの内容です。今回は7.4 「QR法」についてアルゴリズムの概要となぜそれがうまくいくのか？、Pythonによる実装の3つについて説明していきます。<br><br>python実装に関してはこちらに公開してあります。<br><a href="https://github.com/shu65/theoretical-numerical-linear-algebra/blob/main/%E7%B7%9A%E5%BD%A2%E8%A8%88%E7%AE%97%E3%81%AE%E6%95%B0%E7%90%86_7_4_QR%E6%B3%95.ipynb" target="_blank" rel="noreferrer noopener">https://github.com/shu65/theoretical-numerical-linear-algebra/blob/main/%E7%B7%9A%E5%BD%A2%E8%A8%88%E7%AE%97%E3%81%AE%E6%95%B0%E7%90%86_7_4_QR%E6%B3%95.ipynb</a></p>



<h2 class="wp-block-heading">QR法</h2>



<p>QR法は複数の固有値、固有ベクトルを同時に求める手法で、前回紹介した同時反復法の計算を少し改良した手法です。同時反復法についてはこちらの記事で詳しく扱っていますので、参考にしてみてください。</p>



<figure class="wp-block-embed is-type-wp-embed is-provider-まったり勉強ノート wp-block-embed-まったり勉強ノート"><div class="wp-block-embed__wrapper">
<blockquote class="wp-embedded-content" data-secret="tJuhwZUE2l"><a href="https://www.mattari-benkyo-note.com/2022/03/28/theoretical-numerical-linear-algebra-simultaneous-iteration/">[勉強ノート] 「線形計算の数理」7.3 同時反復法</a></blockquote><iframe loading="lazy" class="wp-embedded-content" sandbox="allow-scripts" security="restricted"  title="&#8220;[勉強ノート] 「線形計算の数理」7.3 同時反復法&#8221; &#8212; まったり勉強ノート" src="https://www.mattari-benkyo-note.com/2022/03/28/theoretical-numerical-linear-algebra-simultaneous-iteration/embed/#?secret=y1mnqm9Gix#?secret=tJuhwZUE2l" data-secret="tJuhwZUE2l" width="600" height="338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
</div></figure>



<p>アルゴリズムとしては基本的にはQR分解して出力される行列から次の行列を作り、またQR分解を行うということを収束するまで繰り返すということしていきます。</p>



<p>次にアルゴリズムについて詳しく説明していきます。</p>



<h2 class="wp-block-heading">QR法のアルゴリズム</h2>



<p>まずはQR法のアルゴリズムについて説明します。QR法は入力として以下のものを取ります。</p>



<ul class="wp-block-list"><li>\( A\): 固有値、固有ベクトルを計算する複素\( n \)次正方行列</li></ul>



<p>これらを入力として以下のように計算していきます。</p>



<ol class="wp-block-list"><li>\( A \) を入力にとり、\( A_0 \) とする</li><li>以下を\( A_k \) の対角成分が収束するまで繰り返す<ol><li>\(A_k = Q_k R_k\) にQR分解する </li><li>\(A_{k+1} = R_kQ_k\) とする</li></ol></li><li>\( A_k \) の対角成分を固有値として出力する</li></ol>



<p>QR分解をご存じない方に簡単に説明するとQR分解は行列\( M \) を以下のように \(Q \) と \( R \) に分解する操作です。<br>$$ \begin{align*} <br>M = QR <br>\end{align*} $$</p>



<p>ここで\( Q\) の列ベクトルは互いに独立な単位ベクトルで、Qは\( n \times m \) 行列です。( ただし、\( m \le n \) ) つまり \( Q^H Q = I_m \) が成り立ちます。また、\( R \) は\( m \) 次上三角行列です。  今回は\( m= n \) となっています。</p>



<p>本のほうにちゃんとした言及がないのでここでは固有値だけを求めるアルゴリズムを示していますが、後ほどおまけのところに書いたように上のアルゴリズムを改良すると固有ベクトルも求めることができます。</p>



<h2 class="wp-block-heading">QR法のアルゴリズムでなぜ固有値が求められるのか？</h2>



<p>次にQR法がなぜ固有値を出力できるのか？について説明していきます。</p>



<p>基本的には同時反復法の\(A_k\)からQR法の以下の漸化式に式変形できることができることを示します。</p>



<p>$$ \begin{align*} <br>A_k = Q_k R_k \tag{7.22.1}\\<br>A_{k+1} = R_k Q_k \tag{7.22.2} \\<br>\end{align*} $$</p>



<p>これを示すことができれば、\(A_k\)の対角成分が固有値に収束する証明は同時反復法のときと同じになります。<br>まずは同時反復法の\(A_k\)は以下の通りです。</p>



<p>$$ \begin{align*} <br>A_k = X_k^H A X_k \tag{7.21.1}<br>\end{align*} $$</p>



<p>ここで、QR法の場合は\(X_0 = I\) です。また同時反復法では\(X_k\)と\(X_{k+1}\)の間には以下の関係が成り立っています。</p>



<p>$$ \begin{align*} <br>A X_k= X_{k+1}R_k \tag{7.19}<br>\end{align*} $$</p>



<p>同時反復法の証明のときに示した通り、\( X_k \) と\( X_{k+1} \)はユニタリ行列です。この式に対して左から\(X_k^H\)をかけると<br>$$ \begin{align*} <br>X_k^H A X_k= X_k^H X_{k+1}R_k \tag{7.19.1}<br>\end{align*} $$</p>



<p>ここで\(Q_k\) を以下のように置きます。</p>



<p>$$ \begin{align*} <br>Q_k = X_k^H X_{k+1} \tag{7.20}<br>\end{align*} $$</p>



<p>この式(7.20)と式(7.21.1)を使うと以下のような関係が導けます。</p>



<p>$$ \begin{align*} <br>A_k =&amp; X_k^H A X_k \\<br>=&amp; X_k^H X_{k+1}R_k \\<br>=&amp; Q_k R_k\tag{7.20.1}<br>\end{align*} $$</p>



<p>この式(7.20.1)は示したかった式の一つの(7.22.1)と同じです。</p>



<p>次に\( X_k \) と\( X_{k+1} \)はユニタリ行列であるため\(Q_k \)はユニタリ行列であるということを利用して、式(7.20)を式変形します。</p>



<p>$$ \begin{align*} <br>X_k^H X_{k+1} = Q_k  \\<br>X_{k+1} = X_k Q_k<br>\tag{7.20.2}<br>\end{align*} $$</p>



<p>これを利用すると式(7.21.1)から\(A_{k+1}\)と\(A_k\)の間に以下のような関係があることがわかります。</p>



<p>$$ \begin{align*} <br>A_{k+1} =&amp; X_{k+1}^H A X_{k+1} \\<br>=&amp; (X_k Q_k)^H A (X_k Q_k) \\<br>=&amp; Q_k^H X_k^H A X_k Q_k \\<br>=&amp; Q_k^H A_k Q_k \\<br>\tag{7.21}<br>\end{align*} $$</p>



<p>また、式(7.22.1)から以下の式が導けます。</p>



<p>$$ \begin{align*} <br>Q_k R_k =&amp; A_k \\<br>R_k =&amp; Q_k^H A_k \tag{7.22.3}<br>\end{align*} $$</p>



<p>そして式(7.21)と式(7.22.3)を利用すると</p>



<p>$$ \begin{align*}<br>A_{k+1} =&amp; Q_k^H A_k Q_k \\<br>=&amp; R_k Q_k \\<br>\tag{7.22.4}<br>\end{align*} $$</p>



<p>式(7.22.4)は示したかった式(7.22.2)と同じ式です。</p>



<p>これで同時反復法の\(A_k\)からQR法の以下の漸化式に式変形できることがわかりました。このため、QR法がなぜ固有値を求められるのか？という証明は同時反復法の証明と同じになります。</p>



<h2 class="wp-block-heading">Pythonによる実装</h2>



<p>アルゴリズムをPythonで具体的に書いたものを紹介します。今回は複素数ではなく実数のみ対応しています。また、簡単な行列演算はnumpyを使用しています。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-python" data-file="qr_method" data-lang="Python"><code>import numpy as np


def qr_method(a, eps=1e-7, max_iterations=100):
  a_k = a
  q_km1 = np.identity(a_k.shape[0])
  for i in range(max_iterations):
    q_k, r_k = np.linalg.qr(a_k)
    relative_residual_norm = np.linalg.norm(q_km1 - q_k)
    if relative_residual_norm &lt; eps:
      break
    a_k = r_k @ q_k
    q_km1 = q_k
  eigenvalues = np.diag(a_k)
  return eigenvalues</code></pre></div>



<p>このコードを実行すると以下のようになります。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-python" data-lang="Python" data-line="qr_method_main"><code>#入力Aの行列
import numpy as np


a_matrix = np.array([
      [1., 0., 0.,],
      [0., 2., 1.,],
      [0., 1., 1.],
  ])
eigenvalues = qr_method(a_matrix)
print(&quot;eigenvalues:&quot;, eigenvalues)</code></pre></div>



<p>実行した際の出力は以下のようになります。</p>



<pre class="wp-block-preformatted">#出力
eigenvalues: [1.         2.61803399 0.38196601]</pre>



<p>numpyの固有値と固有ベクトルを求める <code>np.linalg.eig()</code>でも近い値が得られているので想定通りの動作をしていると考えています。</p>



<h2 class="wp-block-heading">おまけ：固有ベクトルを求めるには？</h2>



<p>本では\(A_{k+1}\)についてしか書かれておらず、QR法では固有ベクトルを求められないというネットの記事も見つかるので、私は最初、固有ベクトルが求められないのかと思っていました。</p>



<p>ただ、同時反復法では\(X_k\)が固有ベクトルに収束することが示されているので、\(X_k\)を求めることができれば固有ベクトルを求めることできるはずです。そう思って式を見直していると式(7.20.2)で以下のような関係が導けています。</p>



<p>$$ \begin{align*} <br>X_{k+1} = X_k Q_k<br>\tag{7.20.2}<br>\end{align*} $$</p>



<p>ここで\(X_0\)はQR法では単位ベクトルとなっています。つまり以下のようにアルゴリズムを変更すれば\(X_k\)を求め、\(X_k\)が固有ベクトルに収束することを利用して、固有ベクトルも出力することができます。</p>



<ol class="wp-block-list"><li>\( A \) を入力にとり、\( A_0 \) とする</li><li>\(X_0 = I \) とする</li><li>以下を\( A_k \) の対角成分が収束するまで繰り返す<ol><li>\(A_k = Q_k R_k\) にQR分解する </li><li>\(A_{k+1} = R_kQ_k\) とする</li><li>\(X_{k+1} = X_k Q_k\) とする</li></ol></li><li>\( A_k \) の対角成分を固有値、\(X_k\)を固有値に対応する固有ベクトルとして出力する</li></ol>



<p>上記のアルゴリズムでは\(X_k\)に関係する部分が追加されています。</p>



<p>実際にPythonで実装すると以下のようになります。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-python" data-file="qr_method_with_eigenvectors" data-lang="Python"><code>import numpy as np


def qr_method_with_eigenvectors(a, eps=1e-7, max_iterations=100):
  a_k = a
  n = a_k.shape[0]
  eigenvectors = np.identity(n)
  for i in range(max_iterations):
    q_k, r_k = np.linalg.qr(a_k)
    eigenvectors = np.dot(q_k, eigenvectors)
    a_kp1 = r_k @ q_k
    relative_residual_norm = np.linalg.norm(np.diag(a_kp1) - np.diag(a_k))
    if relative_residual_norm &lt; eps:
      break
    a_k = a_kp1
  eigenvalues = np.diag(a_kp1)
  return eigenvalues, eigenvectors</code></pre></div>



<p>これを以下のように実行すると</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-python" data-file="qr_method_with_eigenvectors_main" data-lang="Python"><code>import numpy as np

a_matrix = np.array([
      [1., 0., 0.,],
      [0., 2., 1.,],
      [0., 1., 1.],
  ])

eigenvalues, eigenvectors = qr_method_with_eigenvectors(a_matrix)
print(&quot;eigenvalues:&quot;, eigenvalues)
print(&quot;eigenvectors:&quot;)
print(eigenvectors)</code></pre></div>



<p>出力は以下のようになります。</p>



<pre class="wp-block-preformatted">#出力
eigenvalues: [1.         2.61803399 0.38196601]
eigenvectors:
[[ 1.          0.          0.        ]
 [ 0.          0.85065394  0.52572604]
 [ 0.         -0.52572604  0.85065394]]</pre>



<p>なので、正しい固有ベクトルが求められている気がします。</p>



<p>QR法と言った際は固有ベクトルは求めない手法を指すのか、単純に本で言及してないだけなのかはわかりませんが、少し改良すれば固有ベクトルは求められることがわかりました。</p>



<h2 class="wp-block-heading">終わりに</h2>



<p>今回はQR法について説明しました。同時反復法がわかっていればQR法は比較的簡単にわかるかと思いますが、本では式変形が飛びすぎてて少し苦労しました。同じような方の参考になれば幸いです。</p><p>The post <a href="https://www.mattari-benkyo-note.com/2022/03/29/theoretical-numerical-linear-algebra-qr-method/">[勉強ノート] 「線形計算の数理」7.4 QR法</a> first appeared on <a href="https://www.mattari-benkyo-note.com">まったり勉強ノート</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.mattari-benkyo-note.com/2022/03/29/theoretical-numerical-linear-algebra-qr-method/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1250</post-id>	</item>
		<item>
		<title>[勉強ノート] 「線形計算の数理」7.3 同時反復法</title>
		<link>https://www.mattari-benkyo-note.com/2022/03/28/theoretical-numerical-linear-algebra-simultaneous-iteration/</link>
					<comments>https://www.mattari-benkyo-note.com/2022/03/28/theoretical-numerical-linear-algebra-simultaneous-iteration/#respond</comments>
		
		<dc:creator><![CDATA[Shuji Suzuki (shu)]]></dc:creator>
		<pubDate>Sun, 27 Mar 2022 23:08:18 +0000</pubDate>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[固有値問題]]></category>
		<category><![CDATA[線形計算の数理]]></category>
		<guid isPermaLink="false">https://www.mattari-benkyo-note.com/?p=982</guid>

					<description><![CDATA[<p>今日の記事では「線形計算の数理」の7.3で紹介されている固有値問題のアルゴリズムの同時反復法についてのアルゴリズムの説明と固有ベクトル、固有値に収束することの証明を説明します。 個人的には初見で全然収束の証明の意味がわか [&#8230;]</p>
<p>The post <a href="https://www.mattari-benkyo-note.com/2022/03/28/theoretical-numerical-linear-algebra-simultaneous-iteration/">[勉強ノート] 「線形計算の数理」7.3 同時反復法</a> first appeared on <a href="https://www.mattari-benkyo-note.com">まったり勉強ノート</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>今日の記事では「線形計算の数理」の7.3で紹介されている固有値問題のアルゴリズムの同時反復法についてのアルゴリズムの説明と固有ベクトル、固有値に収束することの証明を説明します。</p>



<p>個人的には初見で全然収束の証明の意味がわからず、しかもネットで調べてもわかりやすい証明を見つけることができなかった部分なので、同様にわからない方の参考になれば幸いです。<br>証明が長いのでPython実装に関しては別の記事にします。</p>



<h2 class="wp-block-heading">同時反復法とは</h2>



<p>同時反復法は複数の固有値、固有ベクトルを同時に求める手法です。固有値問題の基本的な手法であるべき乗法は、固有値の絶対値が最大となる固有値とそれに対応する固有ベクトルを求める手法でした。一方、同時反復法はこれを拡張し、固有値の絶対値が大きい順に任意の数の固有値とそれに対応する固有ベクトルを求める手法になります。ちなみに、固有値問題のアルゴリズムとしてよく目にするQR法は同時反復法の計算を少し変えたもので、基本的な考え方は同じものになっています。</p>



<p>同時反復法の証明ではべき乗法と似たような流れがでてきます。べき乗法については以下の記事で説明していますので、よければ参考にしてください。</p>



<figure class="wp-block-embed is-type-wp-embed is-provider-まったり勉強ノート wp-block-embed-まったり勉強ノート"><div class="wp-block-embed__wrapper">
<blockquote class="wp-embedded-content" data-secret="x5jzIUFrUv"><a href="https://www.mattari-benkyo-note.com/2022/03/24/theoretical-numerical-linear-algebra-power-method/">[勉強ノート] 「線形計算の数理」 7.2.1 べき乗法 基本形</a></blockquote><iframe loading="lazy" class="wp-embedded-content" sandbox="allow-scripts" security="restricted"  title="&#8220;[勉強ノート] 「線形計算の数理」 7.2.1 べき乗法 基本形&#8221; &#8212; まったり勉強ノート" src="https://www.mattari-benkyo-note.com/2022/03/24/theoretical-numerical-linear-algebra-power-method/embed/#?secret=OZg98EWSCF#?secret=x5jzIUFrUv" data-secret="x5jzIUFrUv" width="600" height="338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
</div></figure>



<h2 class="wp-block-heading">アルゴリズムの概要</h2>



<p>まずは同時反復法のアルゴリズムについて説明します。同時反復法は入力として以下のものを取ります。</p>



<ul class="wp-block-list"><li>\( A\): 固有値、固有ベクトルを計算する複素\( n \)次正方行列</li><li>\( X_0 \): 独立な単位列ベクトルを持つ任意の\( n \times m \)行列 \(X_0^H X_0 = I_m \)<ul><li>ただし、\( m \)は求める固有値、固有ベクトルの数で \( (m \le n) \)</li></ul></li></ul>



<p>これらを入力として以下のように計算していきます。</p>



<ol class="wp-block-list"><li>\( A \) と\( X_0 \)を入力に取る</li><li>以下を\( X_{k} \) が収束するまで繰り返す<ol><li>\( Y_{k + 1} := AX_k \)</li><li>\( Y_{k + 1} = X_{k+1}R_k\) にQR分解する</li></ol></li><li>\( A_k := X_k^H A X_k\) を計算する</li><li>\( A_k \) の対角成分を絶対値が大きい\( m \)個の固有値、\( X_k\) の列ベクトルが順に対応する固有ベクトルとして出力する</li></ol>



<p>QR分解をご存じない方に簡単に説明するとQR分解は行列\( M \) を以下のように \(Q \) と \( R \) に分解する操作です。<br>$$ \begin{align*} <br>M = QR \tag{7.10.1}<br>\end{align*} $$</p>



<p>ここで\( Q\) の列ベクトルは互いに独立な単位ベクトルで、Qは\( n \times m \) 行列です。( ただし、\( m \le n \) ) つまり \( Q^H Q = I_m \) が成り立ちます。また、\( R \) は\( m \) 次上三角行列です。  </p>



<p>こちらのアルゴリズム、私は初見でなんでうまくいくのかわからなかったので、次から頑張って説明します。</p>



<h2 class="wp-block-heading">同時反復法でなぜ固有ベクトルが求められるのか？</h2>



<p>ここから同時反復法によって固有ベクトルが求められる証明をやっていきます。まず、固有値を絶対値が大きい順に番号を振り、以下のようにします。</p>



<p>$$ \begin{align*} <br>|\lambda_1| \geq  |\lambda_2|  \geq &#8230; \geq |\lambda_n|\tag{7.11} <br>\end{align*} $$</p>



<p>また、固有ベクトルを単位ベクトルとし、それぞれの固有値に対応する固有ベクトルを固有値の絶対値が大きい順に \( \boldsymbol{z}_{1}, \boldsymbol{z}_{2}, &#8230;, \boldsymbol{z}_{n} \) とします。そして、\(A\) が対角化可能(つまり\(n\)個の1次独立な固有ベクトルを持つ)という仮定がおけるとします。つまり、\(n\)個の固有ベクトルを用いると、\(n\)次元の任意のベクトルを固有値ベクトルを使って表すことができます。</p>



<p>また、ここからある行列の列ベクトルに注目することが多くなるので、ある行列Xの\( j \) 列目のベクトルを \( X_{:, j}\) で表します。例えば、固有ベクトルを列ベクトルとして並べた行列\( Z = [\boldsymbol{z}_1,&#8230;, \boldsymbol{z}_m] \)の\(j\)列目は\(Z_{:,j}=\boldsymbol{z}_j \) となります。</p>



<p>さて、まずはアルゴリズムを繰り返すと\( X_k \) がどのような行列になるかを追ってみます。アルゴリズムより、以下のような漸化式が成り立つことがわかります。</p>



<p>$$ \begin{align*} <br>AX_k = X_{k+1}R_k \tag{7.10.2}<br>\end{align*} $$</p>



<p>この漸化式を使って\(A^kX_0\)を\(k=1\)から順番に見ていくと以下のようになることがわかります。</p>



<p>$$ \begin{align*} <br>AX_0 =&amp; X_1R_0 \\<br>A^2X_0 =&amp; A(AX_0) = AX_1R_0 = X_2R_1R_0 \\<br>&#8230;&amp;\\<br>A^kX_0 =&amp; A(X_{k-1}) = AX_{k-1}R_{k-2}&#8230;R_0 = X_{k}R_{k-1}&#8230;R_0 \\<br>=&amp; X_{k} \Gamma_k \tag{7.10}<br>\end{align*} $$</p>



<p>ここで\( \Gamma_k = R_{k-1}&#8230;R_0\) と置きました。\( X_{k}\) と\(\Gamma_k\) がどういう形の行列か順にみていくと、\( X_{k}\) はQR分解した結果、列ベクトル同士が互いに直交している行列、つまり、\( X_{k}^H X_{k} = I_m\)となります。また、 \( R_k \) はQR分解により上三角行列なので、この\( R_k \) を順番にかけていった \(\Gamma_k\)も上三角行列になります。（上三角行列同士の積は上三角行列になります。）</p>



<p>このため、同時反復法のアルゴリズムは\( A^kX_0 \) に対して直接QR分解を適用して \(X_{k}\) と\( \Gamma_k\) に分解したのと同じ状態になっています。このため、この後は\( A^kX_0 \) を直接QR分解したとして考えます。</p>



<p>では、\( A^kX_0 \) をQR分解したときに \(X_{k}\)がどういう行列になっているかを見てみます。</p>



<p>QR分解のアルゴリズムとしてはいくつかありますが、今回はグラム・シュミットの正規直交化法を利用したＱR分解をするとします。</p>



<p>グラム・シュミットの正規直交化法はWikipediaがわかりやすい漸化式になっていたので、これを参考に今回の変数表記でQR分解の漸化式を示します。<br><a href="https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%A9%E3%83%A0%E3%83%BB%E3%82%B7%E3%83%A5%E3%83%9F%E3%83%83%E3%83%88%E3%81%AE%E6%AD%A3%E8%A6%8F%E7%9B%B4%E4%BA%A4%E5%8C%96%E6%B3%95" target="_blank" rel="noreferrer noopener">https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%A9%E3%83%A0%E3%83%BB%E3%82%B7%E3%83%A5%E3%83%9F%E3%83%83%E3%83%88%E3%81%AE%E6%AD%A3%E8%A6%8F%E7%9B%B4%E4%BA%A4%E5%8C%96%E6%B3%95</a></p>



<p>$$ \begin{align*} <br>U_{k,:,1} =&amp; A^kX_{0,:,1} \tag{7.10.3} \\<br>X_{k,:,1} =&amp; \frac{U_{k,:,1}}{||U_{k,:,1}||} \tag{7.10.4}\\<br>U_{k,:,2} =&amp; A^kX_{0,:,2} &#8211; (X_{k,:,1}^HA^kX_{0,:,2})X_{k,:,1} \tag{7.10.5}\\<br>X_{k,:,2} =&amp; \frac{U_{k,:,2}}{||U_{k,:,2}||} \tag{7.10.6}\\<br>&#8230;&amp;\\<br>U_{k,:,m} =&amp; A^kX_{0,:,m} &#8211; \sum_{j=1}^{m} (X_{k,:,j}^HA^kX_{0,:,m})X_{k,:,j} \tag{7.10.7}\\<br>X_{k,:,m} =&amp; \frac{U_{k,:,m}}{||U_{k,:,m}||} \tag{7.10.8}\\<br>\end{align*} $$</p>



<p>\( \Gamma_k\)に関してはここからの証明で利用しないため、上の漸化式から省略しています。<br>\(X_{k,:,j}\)を順に見ていく前に、\( X_0 \) について見ていきます。固有ベクトルを利用すると、入力の\( X_0 \) を以下のように固有ベクトルを列ベクトルとする行列\(Z = [\boldsymbol{z}_1,&#8230;, \boldsymbol{z}_m]\)と複素数を要素に持つ \( C \) に分解できます。<br>$$ \begin{align*} <br>X_0 = ZC \tag{7.10.9}<br>\end{align*} $$</p>



<p>\(X_0\) の一つの列ベクトルに注目するとわかりやすいかと思うので、\(X_0\)の\( j \) 番目の列ベクトルを固有ベクトルで展開した場合の式を以下に示します。</p>



<p>$$ \begin{align*} <br>X_{0,:,j} =&amp; c_{1, j} \boldsymbol{z}_1 + &#8230; + c_{n, j} \boldsymbol{z}_n \\<br>=&amp; \sum_{i=1}^{m} c_{i, j} \boldsymbol{z}_i \tag{7.10.10}\\ <br>\end{align*} $$</p>



<p>ここで\( c_{i,j} \) は \( C \) の\( {i, j }\) 番目の要素です。これを利用すると\( A^kX_{0,:j} \) は以下のようになります。</p>



<p>$$ \begin{align*}<br>A^k X_{0,:,j} =&amp; \sum_{i=1}^n c_{i, j} A^k \boldsymbol{z}_i \\<br>=&amp; \sum_{i=1}^n c_{i, j} \lambda_i^k \boldsymbol{z}_i <br>\tag{7.10.11}<br>\end{align*} $$</p>



<p>これらを利用して、ここから\( X_{k,:,1}\) から順に\( k \to \infty \) のときにどういうベクトルに収束していくのかを見ていきます。ここからはべき乗法と一部似た変形をしていきます。まずは、\( X_{k,:,1}\)のベクトルがアルゴリズムに従うとどういう形になるかを見ていきます。グラム・シュミットの正規直交化法の漸化式より以下のようになります。</p>



<p>$$ \begin{align*} <br>X_{k,:,1} =&amp; \frac{U_{k,:,1}}{||U_{k,:,1}||} \\<br>=&amp; \frac{A^kX_{0,:,1}}{||A^kX_{0,:,1}||} \tag{7.10.12}<br>\end{align*} $$</p>



<p>この式はべき乗法のときに出てきた式と同じ式になっています。このため、同じように\( |\frac{\lambda_j}{\lambda_1} |&lt; 1\) と固有ベクトルが単位ベクトルであることを利用すると、以下のように\( X_{k,:,1} \) は\( k \to \infty \) のときに\(\boldsymbol{z}_1 \)に収束します。</p>



<p>$$ \begin{align*}<br>\lim_{k \to \infty} X_{k,:,1} =&amp; \lim_{k \to \infty} \frac{A^kX_{0,:,1}}{||A^kX_{0,:,1}||} \\<br>=&amp; \lim_{k \to \infty} \frac{\sum_{i=1}^n c_{i, 1} \lambda_i^k \boldsymbol{z}_i }{||\sum_{i=1}^n c_{i, 1} \lambda_i^k \boldsymbol{z}_i ||} \\<br>=&amp; \lim_{k \to \infty} \frac{c_{1,1} \lambda_1^k \boldsymbol{z}_1 + \sum_{i=2}^n c_{i, 1} \lambda_i^k \boldsymbol{z}_i }{||c_{1, 1} \lambda_1^k \boldsymbol{z}_1 +\sum_{i=2}^n c_{i, 1} \lambda_i^k \boldsymbol{z}_i ||} \\<br>=&amp; \lim_{k \to \infty} \frac{\lambda_1^k \left[ c_{1, 1}  \boldsymbol{z}_1 + \sum_{i=2}^n c_{i, 1} \left( \frac{\lambda_i}{\lambda_1}\right)^k \boldsymbol{z}_i \right]}{\lambda_1^k||\left[ c_{1, 1}  \boldsymbol{z}_1 +\sum_{i=2}^n c_{i, 1} \left( \frac{\lambda_i}{\lambda_1}\right)^k \boldsymbol{z}_i \right] ||} \\<br> =&amp; \lim_{k \to \infty} \frac{\left[ c_{1, 1}  \boldsymbol{z}_1 + \sum_{i=2}^n c_{i, 1} \left( \frac{\lambda_i}{\lambda_1}\right)^k \boldsymbol{z}_i \right]}{||\left[ c_{1, 1}  \boldsymbol{z}_1 +\sum_{i=2}^n c_{i, 1} \left( \frac{\lambda_i}{\lambda_1}\right)^k \boldsymbol{z}_i \right] ||} \\<br>=&amp; \lim_{k \to \infty} \frac{\left[ c_{1, 1}  \boldsymbol{z}_1 + \sum_{i=2}^n c_{i, 1} \left( \frac{\lambda_i}{\lambda_1}\right)^k \boldsymbol{z}_i \right]}{||\left[ c_{1, 1}  \boldsymbol{z}_1 +\sum_{i=2}^n c_{i, 1} \left( \frac{\lambda_i}{\lambda_1}\right)^k \boldsymbol{z}_i \right] ||} \\<br>=&amp;\frac{c_{1, 1}  \boldsymbol{z}_1}{||c_{1, 1}  \boldsymbol{z}_1||} \\<br>=&amp;\frac{\boldsymbol{z}_1}{||\boldsymbol{z}_1||} \\<br>=&amp;\boldsymbol{z}_1<br>\tag{7.10.13}<br>\end{align*}$$</p>



<p>ここまではある程度本にある証明ですが、ここから先は本に説明が書いてないので、間違っている可能性がありますが、ご了承ください。</p>



<p>次に\( X_{k,:,2} \)が\( k \to \infty \)のときにどのような値に収束していくか見ていきます。</p>



<p>まず、\( X_{k,:,2} \) のベクトルがグラム・シュミットの正規直交化法に従うとどのような形なのかを詳しく見ていきます。</p>



<p>$$ \begin{align*}<br>X_{k,:,2} =&amp; \frac{U_{k,:,2}}{||U_{k,:,2}||} \\<br>=&amp; \frac{A^kX_{0,:,2} &#8211; (X_{k,:,1}^HA^kX_{0,:,2})X_{k,:,1}}{||A^kX_{0,:,2} &#8211; (X_{k,:,1}^HA^kX_{0,:,2})X_{k,:,1}||}<br>\tag{7.10.14}<br>\end{align*}$$</p>



<p>ここで、グラム・シュミットの正規直交化法では\(X_{k,:,1} \) と \( X_{k,:,2} \) が直交になるように変形されています。つまり、内積が0になるため以下のような関係が成り立ちます。</p>



<p>$$ \begin{align*}<br>X_{k,:,1}^HX_{k,:,2} =&amp; \frac{U_{k,:,1}^HU_{k,:,2}}{||U_{k,:,1}||||U_{k,:,2}||} = 0 <br>\tag{7.10.15}<br>\end{align*}$$</p>



<p>また\( k \to \infty \)のとき、\(X_{k,:,1}\) が\(\boldsymbol{z}_1\)に収束します。\(X_{k,:,1} \) と \( X_{k,:,2} \) が直交関係にあることと、\(X_{k,:,1}\) が\(\boldsymbol{z}_1\)に収束することから、\( k \to \infty \)のとき\(U_{k,:,2}\) の中にある\(\boldsymbol{z}_1\)にかかっている係数は0に収束するということがわかります。</p>



<p>この結果を利用しつつ、\( k \to \infty \)のときに\( U_{k,:,2}\) がどのようなベクトルに収束するか説明しやすいように以下のように変形します。</p>



<p>$$ \begin{align*}<br>U_{k,:,2} =&amp; A^kX_{0,:,2} &#8211; (X_{k,:,1}^HA^kX_{0,:,2})X_{k,:,1} \\<br>=&amp; \sum_{i=1}^n c_{i, 2} \lambda_i^k \boldsymbol{z}_i &#8211; (X_{k,:,1}^HA^kX_{0,:,2})X_{k,:,1} \\<br>=&amp; c_{1, 2} \lambda_1^k \boldsymbol{z}_i1+ c_{2, 2} \lambda_2^k \boldsymbol{z}_2 + \sum_{i=3}^n c_{i, 2} \lambda_i^k \boldsymbol{z}_i \\<br>&amp; &#8211; (X_{k,:,1}^HA^kX_{0,:,2})X_{k,:,1} \\<br>=&amp; \lambda_2^k \left[ c_{2, 2} \boldsymbol{z}_2 + \sum_{i=3}^n c_{i, 2} \left( \frac{\lambda_i}{\lambda_2}\right)^k \boldsymbol{z}_i \right. \\<br>&amp; \left. + \frac{1}{\lambda_2^k} \left( c_{1, 2} \lambda_1^k \boldsymbol{z}_1 &#8211; (X_{k,:,1}^HA^kX_{0,:,2})X_{k,:,1} \right) \right]<br>\tag{7.10.16}<br>\end{align*}$$</p>



<p>式変形した結果、\( k \to \infty \)のときに括弧の中の各項がどうなるかを順番に見ていきます。まず、1つ目の\(  c_{2, 2} \boldsymbol{z}_2 \) は \( k \) に依存してないのでそのままです。二つ目のsumの項に関しては\( i=3 \) からになっているため、\( |\frac{\lambda_i}{\lambda_2} |&lt; 1 \) が成り立ちます。このため、0に収束します。最後に3項目ですが、\( (X_{k,:,1}^HA^kX_{0,:,2}) \) は内積の計算に相当するため、スカラになります。また、\( k \to \infty \)のとき\( X_{k,:,1} \) は\( \boldsymbol{z}_1 \) に収束します。このため、3項目は\( k \to \infty \)のときに\( \boldsymbol{z}_1 \) に関するベクトルだけとなります。ここで、\(U_{k,:,2}\) の中にある\(\boldsymbol{z}_1\)にかかっている係数は0に収束するということを思い出すと3項目の部分が0に収束することがわかります。この結果、\( k \to \infty \)のときに1つ目の項だけが残ることがわかります。</p>



<p>ここで、\( k \to \infty \)のときに0に収束する部分をまとめて\( \boldsymbol{e}_{k,2} \) と置きます。そしてこの結果から、\( X_{k,:,2} \) は以下のようになります。</p>



<p>$$ \begin{align*}<br>\lim_{k \to \infty} X_{k,:,2} =&amp; \frac{U_{k,:,2}}{||U_{k,:,2}||} \\<br>=&amp; \lim_{k \to \infty} \frac{\lambda_2^k \left[ c_{2, 2} \boldsymbol{z}_2 + \boldsymbol{e}_{k,2} \right] }{||\lambda_2^k \left[ c_{2, 2} \boldsymbol{z}_2 + \boldsymbol{e}_{k,2} \right]||} \\<br>=&amp; \lim_{k \to \infty} \frac{c_{2, 2} \boldsymbol{z}_2 + \boldsymbol{e}_{k,2} }{||c_{2, 2} \boldsymbol{z}_2 + \boldsymbol{e}_{k,2}||} \\<br>=&amp; \frac{c_{2, 2} \boldsymbol{z}_2 }{||c_{2, 2} \boldsymbol{z}_2||} \\<br>=&amp; \frac{\boldsymbol{z}_2 }{||\boldsymbol{z}_2||} \\<br>=&amp; \boldsymbol{z}_2<br>\tag{7.10.17} <br>\end{align*}$$</p>



<p>これで\( X_{k,:,2} \) についても示すことができました。\( j \ge 2 \) のとき \( X_{k,:,j} \) は同じような証明になります。つまり、\( U_{k,:,j} \) を以下のように変形すると</p>



<p>$$ \begin{align*}<br>U_{k,:,j} =&amp; A^kX_{0,:,j} &#8211; \sum_{j^{\prime}=1}^{m} (X_{k,:,j^{\prime}}^HA^kX_{0,:,j})X_{k,:,j^{\prime}} \\<br>=&amp; \lambda_j^k \left[ c_{j, j} \boldsymbol{z}_j + \sum_{i=j+1}^n c_{i, j} \left( \frac{\lambda_i}{\lambda_j}\right)^k \boldsymbol{z}_i \right. \\<br>&amp; \left. + \frac{1}{\lambda_j^k} \sum_{j^{\prime}=1}^{j-1} \left( c_{j^{\prime}, j} \lambda_{j^{\prime}}^k \boldsymbol{z}_{j^{\prime}} &#8211; (X_{k,:,j^{\prime}}^HA^kX_{0,:,j})X_{k,:,j^{\prime}} \right) \right]<br>\tag{7.10.18} <br>\end{align*}$$</p>



<p>括弧の中の2項目と3項目は先ほどと同じ流れによって0に収束します。このため、\( k \to \infty \)のときに0に収束する部分をまとめて\( \boldsymbol{e}_{k,j} \) と置きます。そして、この結果から、\( X_{k,:,j} \) は以下のようになります。</p>



<p>$$ \begin{align*}<br>\lim_{k \to \infty} X_{k,:,j} =&amp; \frac{U_{k,:,j}}{||U_{k,:,j}||} \\<br>=&amp; \lim_{k \to \infty} \frac{\lambda_j^k \left[ c_{j, j} \boldsymbol{z}_j + \boldsymbol{e}_{k,j} \right] }{||\lambda_j^k \left[ c_{j, j} \boldsymbol{z}_j + \boldsymbol{e}_{k,j} \right]||} \\<br>=&amp; \lim_{k \to \infty} \frac{c_{j, j} \boldsymbol{z}_j + \boldsymbol{e}_{k,j} }{||c_{j, j} \boldsymbol{z}_2 + \boldsymbol{e}_{k,j}||} \\<br>=&amp; \frac{c_{j, j} \boldsymbol{z}_j }{||c_{j, j} \boldsymbol{z}_j||} \\<br>=&amp; \frac{\boldsymbol{z}_j}{||\boldsymbol{z}_j||} \\<br>=&amp; \boldsymbol{z}_j<br>\tag{7.10.19} <br>\end{align*}$$</p>



<p>以上の結果から \( \lim_{k \to \infty} X_k = Z \) 、つまり、\(  X_k \) の各列が絶対値が大きい固有値の固有ベクトルに収束することが示されました。</p>



<h2 class="wp-block-heading">同時反復法でなぜ固有値が求められるのか？</h2>



<p>次に同時反復法でなぜ固有値が求められるか？を説明します。同時反復法では\(X_k^H A X_k\)の行列の対角成分が絶対値の大きい\( m \) 個の固有値に収束します。本にこの証明が書かれていますが、私がぱっと分からなかったところを補足しながら説明します。ここからは本と同じように\(m=n \) として説明します。</p>



<p>まず、固有ベクトルを先ほどと同じように\( Z = [\boldsymbol{z}_1, &#8230; ,\boldsymbol{z}_n]\) と置き、固有値を対角成分とする行列を\( \Lambda = \text{diag}(\lambda_1,&#8230;,\lambda_n ) \) と置きます。こようにすると以下のような関係になります。</p>



<p>$$ \begin{align*} <br>A = Z \Lambda Z^{-1} \tag{7.14.1}<br>\end{align*} $$</p>



<p>また、\( Z \) をQR分解して以下のような行列に分解できるとします。</p>



<p>$$ \begin{align*} <br>Z = QR \tag{7.14.2}<br>\end{align*} $$</p>



<p>そして、固有ベクトルの収束の証明の時と同じように\(X_0 \) を以下のように複素数を要素に持つ\( C\)と\(Z\) を使って以下のように表せられるとします。</p>



<p>$$ \begin{align*} <br>X_0 = ZC \tag{7.14.3}<br>\end{align*} $$</p>



<p>また、\(C \) はLU分解によって以下のように分解できるとします。</p>



<p>$$ \begin{align*} <br>C = LU \tag{7.14.4}<br>\end{align*} $$</p>



<p>LU分解は\( L \) (下三角行列。ただし、対角成分は1)と\( U \) (上三角行列)に分ける操作です。</p>



<p>これらを使うと\(A^k X_0 \) は以下のように変形できます。</p>



<p>$$ \begin{align*} <br>A^kX_0 =&amp; Z \Lambda^k Z^{-1} X_0 \\ <br>=&amp; Z \Lambda^k Z^{-1} ZC \\ <br>=&amp; Z \Lambda^k C \\ <br>=&amp; Z \Lambda^k LU \\ <br>=&amp; Z \Lambda^k L(R\Lambda^k)^{-1}(R\Lambda^k)U \\<br>=&amp; Z \Lambda^k L\Lambda^{-k}R^{-1}R\Lambda^kU \\<br>=&amp; QR \Lambda^k L\Lambda^{-k}R^{-1}R\Lambda^kU \\<br>=&amp; Q \cdot R (\Lambda^k L\Lambda^{-k})R^{-1} \cdot R\Lambda^kU <br>\tag{7.14}<br>\end{align*} $$</p>



<p>ここで\( R (\Lambda^k L\Lambda^{-k})R^{-1}\) を部分を以下のようにQR分解します。</p>



<p>$$ \begin{align*} <br>R (\Lambda^k L\Lambda^{-k})R^{-1} = G_k P_k \tag{7.15}<br>\end{align*} $$</p>



<p>ここで\( G_k^H G_k = I\) であり、\( P_k \) は上三角行列です。これを式(7.14) に代入します。</p>



<p> $$ \begin{align*} <br>A^kX_0 =&amp; Q \cdot R (\Lambda^k L\Lambda^{-k})R^{-1} \cdot R\Lambda^kU \\<br>=&amp; Q \cdot G_k P_k \cdot R\Lambda^kU <br>\tag{7.15.1}<br>\end{align*} $$</p>



<p>上の式(7.15.1)と固有ベクトルの収束の時に使った式(7.10)を利用すると以下のような関係が成り立ちます。</p>



<p>$$ \begin{align*} <br>A^kX_0 =&amp; Q \cdot G_k P_k \cdot R\Lambda^kU \\<br>=&amp; X_k \Gamma_k<br>\tag{7.15.2}<br>\end{align*} $$</p>



<p>この式の\( Q G_k P_k R\Lambda^kU <br>= X_k \Gamma_k \) の両辺を以下のように変形します。</p>



<p>$$ \begin{align*} <br>Q G_k P_k R\Lambda^kU =&amp; X_k \Gamma_k \\<br>P_k R\Lambda^kU \Gamma_k^{-1}=&amp; (QG_k)^HX_k <br>\tag{7.15.3}<br>\end{align*} $$</p>



<p>ここで\(Q, G_k\)はQR分解で計算されるユニタリ行列部分であり、ユニタリ行列同士の積はユニタリ行列です。また、\( QG_k\) はユニタリ行列なので、逆行列は\( (QG_k)^H\)になっています。</p>



<p>この式(7.15.3)の式変形の結果の左辺と右辺のそれぞれに注目します。まず、左辺の\( P_k, R, U , \Gamma_k \)は上三角行列です。また、上三角行列の逆行列もまた上三角行列であるため\( \Gamma_k^{-1} \) も上三角行列です。また、\( \Lambda^k \) は対角行列です。そして、上三角行列と上三角行列、上三角行列と対角行列はすべて上三角行列になります。このため、左辺は上三角行列になっています。</p>



<p>一方、右辺を見ていきます。\( Q, G_k, X_k \) はすべてQR分解の結果のユニタリ行列になっています。ユニタリ行列とユニタリ行列の積はユニタリ行列であるため右辺はユニタリ行列です。</p>



<p>つまり、式(7.15.3)の行列は左辺が上三角行列であり、右辺はユニタリ行列であるため、この二つの性質を併せ持つユニタリ対角行列（すなわち対角成分以外は0で対角要素の絶対値が1の対角行列）となっています。このユニタリ対角行列を\(D_k\)と置きます。これを使うと式(7.15.3)は以下のように成り立ちます。</p>



<p>$$ \begin{align*} <br>(QG_k)^HX_k =&amp; P_k R\Lambda^kU \Gamma_k^{-1} \\<br>(QG_k)^HX_k =&amp; D_k \\ <br>X_k = QG_kD_k <br>\tag{7.15.4}<br>\end{align*} $$</p>



<p>ここで\( Q, G_k \) はQR分解によるユニタリ行列であるため、この積の\(QG_k\) もユニタリ行列です。そして、\(QG_k\) の逆行列は\((QG_k)^H\)です。 </p>



<p>次に式(7.15)に出てきた\(\Lambda^k L\Lambda^{-k}\)について考えます。\(L\)はLU分解の下三角行列であり、対角成分は1になっています。また、\( \Lambda \) は対角行列であり、対角行列の逆行列は元の対角行列の対角成分の逆数です。このため、\(\Lambda^k L\Lambda^{-k}\)の対角成分は1になっています。また、対角行列と下三角行列の積は下三角行列です。このため、\(\Lambda^k L\Lambda^{-k}\)は下三角行列です。ただ、対角行列以外 (\( i &gt; j \))の要素は\(L\) の要素を\(l_{i,j}\)とすると以下のような式になっています。</p>



<p>$$ \begin{align*} <br>l_{i,j} \left( \frac{\lambda_i}{\lambda_j}\right)^k<br>\tag{7.15.5}<br>\end{align*} $$</p>



<p>ここで\( |\frac{\lambda_i}{\lambda_j}| &lt; 1\) であるため、\( k \to \infty\) のとき0に収束します。このため、\( \Lambda^k L\Lambda^{-k} \) は\( k \to \infty\) のとき以下のようになります。<br>$$ \begin{align*} <br>\lim_{k \to \infty} \Lambda^k L\Lambda^{-k} = I_n<br>\tag{7.15.6}<br>\end{align*} $$</p>



<p>このため、\( k \to \infty \) のとき式(7.15)は以下のようになります。</p>



<p>$$ \begin{align*} <br>\lim_{k \to \infty} R (\Lambda^k L\Lambda^{-k})R^{-1} =&amp; R I_n R^{-1} \\<br>=&amp; R R^{-1} \\<br>=&amp; I_n \\<br>\tag{7.15.7}<br>\end{align*} $$</p>



<p>この結果から\( k \to \infty \) のとき式(7.15)の左辺が単位行列になるため、QR分解よる行列\( G_k, P_k \) それぞれ以下のように単位行列と収束します。</p>



<p>$$ \begin{align*} <br>\lim_{k \to \infty} G_k =&amp; I_n \\<br>\lim_{k \to \infty} P_k =&amp; I_n \\<br>\tag{7.15.8}<br>\end{align*} $$</p>



<p>この結果を利用する前に、式(7.15.4)の両辺を式変形します。</p>



<p>$$ \begin{align*} <br>X_k =&amp; QG_kD_k \\<br>X_kD_k^H =&amp; QG_kD_kD_k^H \\<br>X_kD_k^H =&amp; QG_k \\<br>\tag{7.15.9}<br>\end{align*} $$</p>



<p>ここで、\(D_k\) はユニタリ対角行列であるため、\(D_k\)の逆行列は\(D_k^H\)です。この式(7.15.8)は\( k \to \infty \) のとき以下のようになります。</p>



<p>$$ \begin{align*}<br>\lim_{k \to \infty} X_kD_k^H =&amp; \lim_{k \to \infty} QG_k \\<br>=&amp; Q <br>\tag{7.16}<br>\end{align*} $$</p>



<p>また、後ほど使う式を順番に示していきます。まず、\(A_k \) を以下のように置きます。</p>



<p>$$ \begin{align*}<br>A_k = X_k^H A X_k \tag{7.17.1}<br>\end{align*} $$</p>



<p>ここで、\(A_k\) の各要素を\( a_{i,j}^{(k)} \) とします。つまり、最終的に\(k \to \infty\)のとき\( a_{i,i}^{(k)} \)が固有値に収束していればよいことになります。<br>次に式(7.14.2)を利用して式(7.14.1)を変形して以下の関係を示しておきます。</p>



<p>$$ \begin{align*} <br>A = Z \Lambda Z^{-1} \\<br>A = QR \Lambda (QR)^{-1} \\<br>A = QR \Lambda R^{-1} Q^H\\<br>Q^H A Q= R \Lambda R^{-1}<br>\tag{7.17.2}<br>\end{align*} $$</p>



<p>ここで\( Q \) はユニタリ行列であるため、\( Q \)の逆行列は\( Q^H \)です。</p>



<p>また、\(D_k\)がユニタリ対角行列なため、以下の式が成り立ちます。</p>



<p>$$ \begin{align*}<br>A_k =&amp; D_k A_k D_k^H<br>\tag{7.17.3}<br>\end{align*} $$</p>



<p>この式(7.17.2)、(7.17.3)と先ほどの式(7.16)を利用すると\(k \to \infty\)のとき\(A_k\)は以下のようになります。</p>



<p>$$ \begin{align*}<br>\lim_{k \to \infty} A_k =&amp; \lim_{k \to \infty} D_k A_k D_k^H \\<br>=&amp; \lim_{k \to \infty} D_k X_k^H A X_k D_k^H \\<br>=&amp; \lim_{k \to \infty} (X_k D_k^H)^H A (X_k D_k^H) \\<br>=&amp; Q^H A Q \\<br>=&amp; R \Lambda R^{-1} <br>\tag{7.16}<br>\end{align*} $$</p>



<p>ここで、\( R \Lambda R^{-1} \) の対角成分について注目します。\( R \) は上三角行列です。この\(R\)の対角要素を\( r_{i,i}\) とします。また、上三角行列の逆行列は上三角行列であり、対角行列の逆行列の対角成分は、元の対角行列の対角成分の逆数になるので\( 1/r_{i,i} \)です。一方、\( \Lambda \) は対角行列です。このため\( R \Lambda R^{-1} \) の対角成分は以下のようになります。</p>



<p>$$ \begin{align*}<br>r_{i,i} \lambda_i \frac{1}{r_{i,i}} = \lambda_i<br>\tag{7.16.1}<br>\end{align*} $$</p>



<p>このため、\( k \to \infty \)のとき\( A_k\)の対角成分\(a_{i,i}^{(k)}\)は以下のようになります。</p>



<p>$$ \begin{align*}<br>\lim_{k \to \infty} a_{i,i}^{(k)} =&amp; r_{i,i} \lambda_i \frac{1}{r_{i,i}} \\<br>=&amp; \lambda_i<br>\tag{7.16.1}<br>\end{align*} $$ </p>



<p>これで\( A_k\) の対角成分が固有値に収束することが示すことができました。</p>



<h2 class="wp-block-heading">終わりに</h2>



<p>今回の記事では同時反復法のアルゴリズムの説明を行いました。正直、本を読んでも全然わからず、しかもネットで検索しても私がわかるレベルまで詳しく書かれた証明が出てこなかったため、かなり苦労しました。同様にわからず悩んでいる方の参考に少しでもなれば幸いです。<br>次はQR法の軽い証明と実装を紹介する記事をかければと思っています。</p><p>The post <a href="https://www.mattari-benkyo-note.com/2022/03/28/theoretical-numerical-linear-algebra-simultaneous-iteration/">[勉強ノート] 「線形計算の数理」7.3 同時反復法</a> first appeared on <a href="https://www.mattari-benkyo-note.com">まったり勉強ノート</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.mattari-benkyo-note.com/2022/03/28/theoretical-numerical-linear-algebra-simultaneous-iteration/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">982</post-id>	</item>
		<item>
		<title>[勉強ノート] 「線形計算の数理」 7.2.1 べき乗法 基本形</title>
		<link>https://www.mattari-benkyo-note.com/2022/03/24/theoretical-numerical-linear-algebra-power-method/</link>
					<comments>https://www.mattari-benkyo-note.com/2022/03/24/theoretical-numerical-linear-algebra-power-method/#respond</comments>
		
		<dc:creator><![CDATA[Shuji Suzuki (shu)]]></dc:creator>
		<pubDate>Wed, 23 Mar 2022 23:37:09 +0000</pubDate>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[numpy]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[固有値問題]]></category>
		<category><![CDATA[線形計算の数理]]></category>
		<guid isPermaLink="false">https://www.mattari-benkyo-note.com/?p=911</guid>

					<description><![CDATA[<p>今日の記事では「線形計算の数理」の7.2.1で紹介されているべき乗法について解説とPythonによる実装を紹介します。基本的には自分があとで見返したときに納得できるように説明を書いたので、かなり基本的なところから書いてあ [&#8230;]</p>
<p>The post <a href="https://www.mattari-benkyo-note.com/2022/03/24/theoretical-numerical-linear-algebra-power-method/">[勉強ノート] 「線形計算の数理」 7.2.1 べき乗法 基本形</a> first appeared on <a href="https://www.mattari-benkyo-note.com">まったり勉強ノート</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>今日の記事では「線形計算の数理」の7.2.1で紹介されているべき乗法について解説とPythonによる実装を紹介します。基本的には自分があとで見返したときに納得できるように説明を書いたので、かなり基本的なところから書いてあると思います。</p>



<p>実数に対応したPythonによる実装はこちらに置いてあります。</p>



<p><a href="https://github.com/shu65/theoretical-numerical-linear-algebra/blob/main/%E7%B7%9A%E5%BD%A2%E8%A8%88%E7%AE%97%E3%81%AE%E6%95%B0%E7%90%86_7_2_1_%E3%81%B9%E3%81%8D%E4%B9%97%E6%B3%95_%E5%9F%BA%E6%9C%AC%E5%BD%A2.ipynb" target="_blank" rel="noreferrer noopener">https://github.com/shu65/theoretical-numerical-linear-algebra/blob/main/%E7%B7%9A%E5%BD%A2%E8%A8%88%E7%AE%97%E3%81%AE%E6%95%B0%E7%90%86_7_2_1_%E3%81%B9%E3%81%8D%E4%B9%97%E6%B3%95_%E5%9F%BA%E6%9C%AC%E5%BD%A2.ipynb</a></p>



<h2 class="wp-block-heading">固有値問題とは</h2>



<p>まずはべき乗法の前に固有値問題について触れます。</p>



<p>複素\( n \)次正方行列 \( A \) に対して以下のような関係を満たす 複素数の\( \lambda \) と 複素ベクトル\( z \) の組を全部、またはいくつか求める問題を固有値問題と言います。 </p>



<p>$$ \begin{align*} <br>A \boldsymbol{z} = \lambda \boldsymbol{z} \tag{7.1} <br>\end{align*} $$</p>



<p>このとき、 \( \lambda \)を固有値、\( z \)を固有ベクトルと言います。</p>



<p>この固有値問題を解くアルゴリズムの一つが今回紹介するべき乗法です。</p>



<h2 class="wp-block-heading">べき乗法とは</h2>



<p>べき乗法は固有値問題を解くアルゴリズムで、固有値のうち、絶対値最大となる固有値とその固有ベクトル を求めるアルゴリズムになります。</p>



<h3 class="wp-block-heading">アルゴリズムの概要</h3>



<p>具体的なPythonコードは後ほどしめしますが、基本的には以下のようなアルゴリズムになります。</p>



<ol class="wp-block-list"><li>\( A \) と任意の単位ベクトル \( \boldsymbol{x}_0 \)を入力に取る</li><li>以下を\( \boldsymbol{x}_{k} \) が収束するまで繰り返す<ol><li>\(  \boldsymbol{y}_{k} := A \boldsymbol{x}_{k-1}\)</li><li>\( \boldsymbol{x}_{k} :=  \boldsymbol{y}_{k} / ||  \boldsymbol{y}_{k} || \) </li></ol></li><li>収束した\( \boldsymbol{x}_{k}\) を\( \boldsymbol{x} \) とし、\( \boldsymbol{x} \) と \( \boldsymbol{y} \) (\(=A \boldsymbol{x}\)) の要素比の絶対値 \( | y_i / x_i | \) が最大となる \( y_i / x_i  \) (ただし、 \( x_i \ne 0 \) ) を求める。</li><li>3で求めた\( y_i / x_i  \)を絶対値最大となる固有値、その固有ベクトルを\( \boldsymbol{x} \) として出力する</li></ol>



<h3 class="wp-block-heading">絶対値最大の固有値の固有ベクトルに収束する理由</h3>



<p>先ほど紹介したアルゴリズムでは\( \boldsymbol{x}_{k} \)が絶対値最大となる固有値の固有ベクトルに収束することを利用していました。そもそもなぜ \( \boldsymbol{x}_{k} \)が固有ベクトルに収束していくのか？を示します。</p>



<p>まず、複素\( n \)次正方行列\(A\)の固有値 \( \lambda_i \) を以下のように絶対値が大きい順に番号付けします。</p>



<p>$$ \begin{align*} <br>|\lambda_1| \geq  |\lambda_2|  \geq &#8230; \geq |\lambda_n|\tag{7.6} <br>\end{align*} $$</p>



<p>また、固有ベクトルを単位ベクトルとし、それぞれの固有値に対応する固有ベクトルを固有値の絶対値が大きい順に \( \boldsymbol{z}_{1}, \boldsymbol{z}_{2}, &#8230;, \boldsymbol{z}_{n} \) とします。ここで\(A\) が対角化可能(つまり\(n\)個の1次独立な固有ベクトルを持つ)という仮定がおけるとします。つまり、\(n\)個の固有ベクトルを用いると\(n\)次元の任意のベクトルを固有値ベクトルを使って表すことができます。</p>



<p>これを利用して任意の単位ベクトル \( \boldsymbol{x}_0 \)を以下のように固有ベクトルを使って表します。</p>



<p>$$ \begin{align*} <br>\boldsymbol{x}_0 = \sum_{i=1}^n c_i \boldsymbol{z}_i \tag{7.7.1} <br>\end{align*} $$</p>



<p>ここで\( c_i \) は複素数です。この(7.7.1)で\(A^k\)を左からかけ、(7.1)を利用すると以下のように変形できます。</p>



<p>$$ \begin{align*} <br>A^k \boldsymbol{x}_0 =&amp; \sum_{i=1}^n c_i A^k \boldsymbol{z}_i \\<br>=&amp; \sum_{i=1}^n c_i \lambda_i^k \boldsymbol{z}_i \\<br>=&amp; \lambda_1^k \left[ c_1 \boldsymbol{z}_1 + \sum_{i=2}^n c_i \left( \frac{\lambda_i}{\lambda_1} \right)^k \boldsymbol{z}_i \right] <br>\tag{7.7} <br>\end{align*} $$</p>



<p>このとき\( \lambda_1 \) は絶対値最大の固有値であるため、 \( |\frac{\lambda_i}{\lambda_1}| &lt; 1 \) が成り立ちます。このため、sumの項に関しては\( k \to \infty \) のとき0に収束することがわかります。</p>



<p>この式を両辺を \( || A^k \boldsymbol{x}_0 || \) で割り、\( k \to \infty \) のときにどうなるかを見てみます。固有ベクトルが単位ベクトルということを利用すると以下のように固有ベクトル \( \boldsymbol{z}_1 \)だけにすることができます。</p>



<p>$$ \begin{align*} <br>\lim_{k \to \infty} \frac{A^k \boldsymbol{x}_0}{|| A^k \boldsymbol{x}_0 ||} =&amp; \lim_{k \to \infty} \frac{\lambda_1^k \left[ c_1 \boldsymbol{z}_1 + \sum_{i=2}^n c_i \left( \frac{\lambda_i}{\lambda_1} \right)^k \boldsymbol{z}_i \right]}{|| \lambda_1^k \left[ c_1 \boldsymbol{z}_1 + \sum_{i=2}^n c_i \left( \frac{\lambda_i}{\lambda_1} \right)^k \boldsymbol{z}_i \right] ||} \\<br>=&amp; \lim_{k \to \infty} \frac{\lambda_1^k \left[ c_1 \boldsymbol{z}_1 + \sum_{i=2}^n c_i \left( \frac{\lambda_i}{\lambda_1} \right)^k \boldsymbol{z}_i \right]}{\lambda_1^k || \left[ c_1 \boldsymbol{z}_1 + \sum_{i=2}^n c_i \left( \frac{\lambda_i}{\lambda_1} \right)^k \boldsymbol{z}_i \right] ||} \\<br>=&amp; \lim_{k \to \infty} \frac{\left[ c_1 \boldsymbol{z}_1 + \sum_{i=2}^n c_i \left( \frac{\lambda_i}{\lambda_1} \right)^k \boldsymbol{z}_i \right]}{|| \left[ c_1 \boldsymbol{z}_1 + \sum_{i=2}^n c_i \left( \frac{\lambda_i}{\lambda_1} \right)^k \boldsymbol{z}_i \right] ||} \\<br>=&amp; \frac{c_1 \boldsymbol{z}_1}{||c_1 \boldsymbol{z}_1||} \\<br>=&amp; \frac{c_1 \boldsymbol{z}_1}{c_1 ||\boldsymbol{z}_1||} \\<br>=&amp; \boldsymbol{z}_1<br>\tag{7.7.2} <br>\end{align*} $$</p>



<p>この式の左辺の \( \frac{A^k \boldsymbol{x}_0}{|| A^k \boldsymbol{x}_0 ||} \) は\( \boldsymbol{x}_k \) の定義から \( \frac{A^k \boldsymbol{x}_0}{|| A^k \boldsymbol{x}_0 ||} = \boldsymbol{x}_k \)です。このため、\( \boldsymbol{x}_k \) が収束すると \( \boldsymbol{z}_1 \) の近似ベクトルになります。</p>



<h3 class="wp-block-heading">固有ベクトルから固有値を求める</h3>



<p>次に固有値の求め方を説明します。先ほどの説明で \( \boldsymbol{x}_k \) が収束すると固有値ベクトル \( \boldsymbol{z}_1 \) に収束することがわかりました。このため、収束した\( \boldsymbol{x}_k \)を \( \boldsymbol{x} \) とし、\( \boldsymbol{y} = A\boldsymbol{x} \) と置きます。この時、\( \boldsymbol{x} \) は固有ベクトルの近似なので以下の関係が成り立ちます。</p>



<p>$$ \begin{align*} <br>\boldsymbol{y} = A \boldsymbol{x} \approx \lambda_1 \boldsymbol{x} \tag{7.7.3} <br>\end{align*} $$</p>



<p>このため、\( \boldsymbol{x}\) と\( \boldsymbol{y}\)の要素をそれぞれ \( x_i\)、\( y_i\)とするとき以下の式が成り立ちます。</p>



<p>$$ \begin{align*} <br>y_i \approx \lambda_1 x_i \tag{7.7.4} <br>\end{align*} $$</p>



<p>式 (7.7.4)から\( x_i \ne 0 \) のときは以下の関係が成り立ちます。</p>



<p>$$ \begin{align*} <br>\lambda_1　\approx  \frac{y_i}{x_i} \tag{7.7.5} <br>\end{align*} $$</p>



<p>本では詳しく理由は書かれていないですが、\( |\frac{y_i}{x_i}| \) が最大となるような \( i \) を選ぶとよいとあります。</p>



<p>また\( A \) がエルミート行列の時は以下の式(レイリー商)のほうが良い近似らしいです。</p>



<p>$$ \begin{align*} <br>\lambda_1　\approx  \frac{\boldsymbol{x}^H A \boldsymbol{x}}{\boldsymbol{x}^H \boldsymbol{x}} \tag{7.9} <br>\end{align*} $$</p>



<p>他の方のblog記事を読むとレイリー商を利用して固有値を出しているケースが多い印象でした。</p>



<h2 class="wp-block-heading">Pythonによる実装</h2>



<p>アルゴリズムの概要で示したものをPythonで具体的に書きます。今回は複素数ではなく実数のみ対応しています。また、簡単な行列演算はnumpyを使用しています。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-python" data-file="power_method" data-lang="Python"><code>def power_method(a, eps=1e-7, max_iterations=100):
  x0 = np.ones((a.shape[1],))/np.sqrt(a.shape[1])
  x_k = x0
  for i in range(max_iterations):
    y_k = a @ x_k
    x_kp1 = y_k / np.linalg.norm(y_k)
    relative_residual_norm = np.linalg.norm(x_kp1 - x_k)
    if relative_residual_norm &lt; eps:
      break
    x_k = x_kp1 
  x = x_k
  y = a @ x
  eigenvalue = None
  for x_i, y_i in zip(x, y):
    if np.abs(x_i) &gt;= eps:
      tmp = y_i / x_i
      if (eigenvalue is None) or (np.abs(eigenvalue) &lt; np.abs(tmp)):
        eigenvalue = tmp
  eigenvector = x
  return eigenvalue, eigenvector</code></pre></div>



<p>このコードを実行すると以下のようになります。<br></p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-python" data-file="main" data-lang="Python"><code># 入力のAの行列
a_matrix = np.array(
    [[1, 0],
     [0, 2]]
)
eigenvalue, eigenvector = power_method(a_matrix)
print(&quot;eigenvalues:&quot;, eigenvalue)
print(&quot;eigenvectors:&quot;)
print(eigenvector)</code></pre></div>



<pre class="wp-block-preformatted"># 出力
eigenvalues: 2.0
eigenvectors:
[1.1920929e-07 1.0000000e+00]</pre>



<p>numpyの固有値と固有ベクトルを求める <code>np.linalg.eig()</code>でも近い値が得られているので想定通りの動作をしていると考えています。</p>



<h2 class="wp-block-heading">終わりに</h2>



<p>最近固有値問題について勉強していて、同僚に良い本として「線形計算の数理」を教えてもらったので読んでいました。この際、アルゴリズムの背景にある数学の証明が面白いと感じたのと、他の方のべき乗法の記事を読んでもわからないところがあったので、自分があとで見返したときに納得できるように説明を書きました。</p>



<p>実は「線形計算の数理」で紹介されている固有値問題のアルゴリズムは大部分を勉強がてら実装してあるので、随時今回のような記事にしていければと思っています。</p><p>The post <a href="https://www.mattari-benkyo-note.com/2022/03/24/theoretical-numerical-linear-algebra-power-method/">[勉強ノート] 「線形計算の数理」 7.2.1 べき乗法 基本形</a> first appeared on <a href="https://www.mattari-benkyo-note.com">まったり勉強ノート</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.mattari-benkyo-note.com/2022/03/24/theoretical-numerical-linear-algebra-power-method/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">911</post-id>	</item>
	</channel>
</rss>
