#13 ふれてみよう高校数学 離散数学・数論

固有値と固有ベクトル——行列が「伸ばすだけ」の方向

固有値・固有ベクトルとは

「行列は空間を変形させる道具」——普通は矢印(ベクトル)の向きも変えてしまいます。しかし「向きは変えずに長さだけ変える」特別な方向があります。それが固有ベクトルの方向で、伸びる倍率が固有値です。

たとえばゴムシートを横方向に引っ張ったとき、横方向のベクトルは向きを変えずに伸び、縦方向のベクトルは向きを変えずに縮む——こういう「変形しても向きが変わらない特別な方向」が固有ベクトルです。

行列 AA に対して、次の条件を満たすゼロでないベクトル v\mathbf{v} とスカラー λ\lambda を考えます:

Av=λvA\mathbf{v} = \lambda \mathbf{v}

  • v\mathbf{v}固有ベクトル(eigenvector)——「向きが変わらない特別な方向」
  • λ\lambda固有値(eigenvalue)——「どれだけ伸縮するかの倍率」

意味:AA でベクトル v\mathbf{v} を変換すると、向きが変わらずに λ\lambda 倍に伸縮するだけ。

普通のベクトルは AA で変換すると向きが変わりますが、固有ベクトルは向きが変わらない特別な方向です。


固有値の求め方

「特別な方程式を解けば固有値が求まる」——手順は次のとおりです:

Av=λvA\mathbf{v} = \lambda\mathbf{v} より (AλI)v=0(A - \lambda I)\mathbf{v} = \mathbf{0}

非自明な解(v0\mathbf{v} \neq \mathbf{0})が存在するには、行列式がゼロになる必要があります——「逆行列が存在しないとき、ゼロでない解が生まれる」:

det(AλI)=0\det(A - \lambda I) = 0

これを特性方程式(characteristic equation)といいます。


2×2 行列の例

「実際に手を動かして固有値と固有ベクトルを求めてみましょう」:

A=(3113)A = \begin{pmatrix} 3 & 1 \\ 1 & 3 \end{pmatrix}

① 特性方程式を立てる

det(AλI)=det(3λ113λ)=(3λ)21=0\det(A - \lambda I) = \det\begin{pmatrix} 3-\lambda & 1 \\ 1 & 3-\lambda \end{pmatrix} = (3-\lambda)^2 - 1 = 0

λ26λ+8=0    (λ2)(λ4)=0\lambda^2 - 6\lambda + 8 = 0 \implies (\lambda - 2)(\lambda - 4) = 0

固有値:λ1=2,λ2=4\lambda_1 = 2, \quad \lambda_2 = 4——「この行列は2倍に伸ばす方向と4倍に伸ばす方向がある」

② 固有ベクトルを求める

λ1=2\lambda_1 = 2 のとき:(A2I)v=0(A - 2I)\mathbf{v} = \mathbf{0}

(1111)v=0    v1+v2=0    v1=(11)\begin{pmatrix}1&1\\1&1\end{pmatrix}\mathbf{v} = \mathbf{0} \implies v_1 + v_2 = 0 \implies \mathbf{v}_1 = \begin{pmatrix}1\\-1\end{pmatrix}

λ2=4\lambda_2 = 4 のとき:(A4I)v=0(A - 4I)\mathbf{v} = \mathbf{0}

(1111)v=0    v1+v2=0    v2=(11)\begin{pmatrix}-1&1\\1&-1\end{pmatrix}\mathbf{v} = \mathbf{0} \implies -v_1 + v_2 = 0 \implies \mathbf{v}_2 = \begin{pmatrix}1\\1\end{pmatrix}


変換のアニメーション

円周上のすべてのベクトルを AA で変換します。固有ベクトルの方向のベクトルは向きが変わらず(スケールのみ変化)、他のベクトルは向きが変わることを観察してください。

行列変換アニメーション:円周上の矢印が変換前から変換後へとゆっくり動く。黄色い矢印(固有ベクトルの方向)だけは向きが変わらず長さだけ変わる——これが『向きが変わらない特別な方向』の意味。青い矢印は変換によって向きも変わってしまう。
var t, i, ox, oy, scale, numVec;
t = 0;
numVec = 16;

// Matrix A = [[3,1],[1,3]]
var A00 = 3, A01 = 1, A10 = 1, A11 = 3;

function mulMat(x, y) {
return [A00*x + A01*y, A10*x + A11*y];
}

function loop() {
ctx.clearRect(0, 0, W, H);
t += 0.008;
var lerpT = (Math.sin(t) + 1) / 2; // 0..1

ox = W/2; oy = H/2; scale = 48;

// grid
ctx.strokeStyle = '#1e293b';
ctx.lineWidth = 1;
for (var g = -5; g <= 5; g++) {
  ctx.beginPath(); ctx.moveTo(ox+g*scale, oy-5*scale); ctx.lineTo(ox+g*scale, oy+5*scale); ctx.stroke();
  ctx.beginPath(); ctx.moveTo(ox-5*scale, oy+g*scale); ctx.lineTo(ox+5*scale, oy+g*scale); ctx.stroke();
}
ctx.strokeStyle = '#334155';
ctx.lineWidth = 2;
ctx.beginPath(); ctx.moveTo(ox-5*scale, oy); ctx.lineTo(ox+5*scale, oy); ctx.stroke();
ctx.beginPath(); ctx.moveTo(ox, oy-5*scale); ctx.lineTo(ox, oy+5*scale); ctx.stroke();

// draw vectors
for (i = 0; i < numVec; i++) {
  var angle = (i / numVec) * Math.PI * 2;
  var vx = Math.cos(angle), vy = Math.sin(angle);
  var tv = mulMat(vx, vy);

  // interpolate between original and transformed
  var ix = vx + lerpT * (tv[0] - vx);
  var iy = vy + lerpT * (tv[1] - vy);

  // check if close to eigenvector directions
  var norm = Math.sqrt(ix*ix + iy*iy);
  var cos45 = Math.abs(ix - iy) / norm;
  var cos45b = Math.abs(ix + iy) / norm;
  var isEigen = cos45 < 0.15 || cos45b < 0.15;

  ctx.strokeStyle = isEigen ? '#fbbf24' : '#60a5fa88';
  ctx.lineWidth = isEigen ? 2.5 : 1;
  ctx.beginPath();
  ctx.moveTo(ox, oy);
  ctx.lineTo(ox + ix * scale, oy - iy * scale);
  ctx.stroke();

  if (isEigen) {
    ctx.fillStyle = '#fbbf24';
    ctx.beginPath();
    ctx.arc(ox + ix*scale, oy - iy*scale, 4, 0, Math.PI*2);
    ctx.fill();
  }
}

// eigenvector labels
ctx.fillStyle = '#fbbf24';
ctx.font = '12px monospace';
ctx.textAlign = 'center';
ctx.fillText('v₁=(1,-1) λ=2', ox + 80, oy + 110);
ctx.fillText('v₂=(1,1) λ=4', ox - 70, oy - 100);

ctx.fillStyle = '#e2e8f0';
ctx.font = '13px monospace';
ctx.textAlign = 'left';
ctx.fillText('A = [[3,1],[1,3]]', 14, 22);
var phase = lerpT < 0.1 ? '変換前' : lerpT > 0.9 ? '変換後' : '変換中...';
ctx.fillText(phase, 14, 40);

requestAnimationFrame(loop);
}
loop();

特性多項式と固有空間

n×nn \times n 行列は nn 個の固有値を持つ」——n×nn \times n 行列の特性方程式は λ\lambdann 次方程式(特性多項式)で、一般に nn 個の固有値(重複・複素数含む)を持ちます。

各固有値 λi\lambda_i に対応する固有ベクトル全体(0\mathbf{0} を含む)を固有空間(eigenspace)といいます——「同じ固有値を持つベクトルたちの集合」。


トレースと行列式との関係

「固有値の和と積は行列から直接読み取れる」——2×22 \times 2 行列 A=(abcd)A = \begin{pmatrix}a&b\\c&d\end{pmatrix} の固有値 λ1,λ2\lambda_1, \lambda_2 は:

λ1+λ2=tr(A)=a+d(トレース)\lambda_1 + \lambda_2 = \text{tr}(A) = a + d \quad (\text{トレース}) λ1λ2=det(A)=adbc\lambda_1 \cdot \lambda_2 = \det(A) = ad - bc

これはビエタの公式の適用です——「対角成分を足したものと行列式が、固有値の情報をすでに含んでいる」。

例:A=(3113)A = \begin{pmatrix}3&1\\1&3\end{pmatrix}tr(A)=6=2+4\text{tr}(A) = 6 = 2 + 4 ✓、det(A)=8=2×4\det(A) = 8 = 2 \times 4


固有値・固有ベクトルの応用

「固有値は現代技術の各所で活躍している」——日常生活に直結した応用があります:

分野使い方
主成分分析(PCA)データの分散方向(固有ベクトル)を求める
PageRankWebグラフの遷移行列の最大固有ベクトル
振動解析固有振動数(固有値)と振動モード(固有ベクトル)
量子力学エネルギー固有状態
マルコフ連鎖定常分布は固有値1の固有ベクトル

行列の対角化

「固有ベクトルを並べた行列で変換すると、行列が対角化できる」——計算が非常に楽になります:

AAnn 個の線形独立な固有ベクトル v1,,vn\mathbf{v}_1, \ldots, \mathbf{v}_n を持つとき:

P1AP=D=(λ1λn)P^{-1}AP = D = \begin{pmatrix}\lambda_1 & & \\ & \ddots & \\ & & \lambda_n\end{pmatrix}

P=[v1vn]P = [\mathbf{v}_1 \cdots \mathbf{v}_n](固有ベクトルを並べた行列)

対角化できれば An=PDnP1A^n = P D^n P^{-1} により行列のべき乗が簡単に計算できます——「対角行列のべき乗は各対角成分のべき乗だけで済む」。フィボナッチ数の一般項もこの方法で導けます!


まとめ

  • 固有方程式Av=λvA\mathbf{v} = \lambda\mathbf{v}(向きが変わらずスケールのみ変化)——「変換されても向きが変わらない特別な方向」
  • 固有値の求め方:特性方程式 det(AλI)=0\det(A - \lambda I) = 0——「この方程式を解けば固有値が出る」
  • 固有ベクトルの求め方:各 λ\lambda について (AλI)v=0(A-\lambda I)\mathbf{v} = \mathbf{0} を解く
  • λ1+λ2=tr(A)\lambda_1 + \lambda_2 = \text{tr}(A)λ1λ2=det(A)\lambda_1 \cdot \lambda_2 = \det(A)——「行列から固有値の情報を読み取れる」
  • 対角化:固有ベクトル行列 PP を使って A=PDP1A = PDP^{-1} と表せる——「べき乗の計算が楽になる」
  • 機械学習・物理・統計で中心的な役割を果たす

次回はフィボナッチ数列と黄金比——自然界に現れる美しい数列の秘密を探ります。