本文へスキップ
ひもとくAI

行列と固有値・特異値分解:向きを変えずに伸ばすだけの向き

レッスン 4/7

行列は、ベクトルを変形する

次のレッスンの 主成分分析 では、「データが一番大きく広がっている向き」を求めます。その道具が、このレッスンで学ぶ 固有値・固有ベクトル と 特異値分解 です。まず、行列の見方を1つ増やします。

第6章の @ の復習

第6章では、@(行列の積)を「たくさんの内積をまとめて計算する記号」として使いました。例えば、2行2列の行列 AA と、2つの数の組(ベクトル)vv の積 AvAv は、「AA の各行と vv の内積」を並べたものです。

A=(2112),v=(10)⇒Av=(2×1+1×01×1+2×0)=(21)A = \begin{pmatrix} 2 & 1 \\ 1 & 2 \end{pmatrix}, \quad v = \begin{pmatrix} 1 \\ 0 \end{pmatrix} \quad \Rightarrow \quad Av = \begin{pmatrix} 2 \times 1 + 1 \times 0 \\ 1 \times 1 + 2 \times 0 \end{pmatrix} = \begin{pmatrix} 2 \\ 1 \end{pmatrix}

新しい見方:行列は、矢印を別の矢印に変える

ベクトル (1,0)(1, 0) を、原点から点 (1,0)(1, 0) への矢印だと考えます。AA を掛けると、矢印 (2,1)(2, 1) に変わりました。長さが変わり、向きも変わっています。いろいろなベクトルに AA を掛けてみます。

もとのベクトル vv(1,0)(1, 0)(0,1)(0, 1)(1,1)(1, 1)(1,−1)(1, -1)
AvAv(2,1)(2, 1)(1,2)(1, 2)(3,3)(3, 3)(1,−1)(1, -1)
向きは?変わる変わる変わらない(3倍に伸びる)変わらない(1倍のまま)
1つ目の数2つ目の数01230123
  • (1, 0)
  • A を掛けた (2, 1)
  • (1, 1)
  • A を掛けた (3, 3)
原点から引いた4本の矢印(線分)。横向きの (1, 0) は、A を掛けると (2, 1) になり、向きが斜め上に変わる。斜め45度の (1, 1) は、A を掛けると (3, 3) になり、同じ向きのまま3倍の長さに伸びる。(1, 1) の線は、同じ向きの (3, 3) の線の上に重なっている。4本の矢印の先の点を○で示す

ほとんどのベクトルは、AA を掛けると向きが変わります。ところが、(1,1)(1, 1) と (1,−1)(1, -1) の向きのベクトルだけは、向きが変わらず、長さが何倍かになるだけ でした。この特別な向きが、次のスライドの固有ベクトルです。

行列を掛けることは、平面全体を「引き伸ばしたり、回したり、押しつぶしたり」する変形だと見ることができます。ニューラルネットワークの各層の @ W も、入力をこのように変形しています。

固有値と固有ベクトル:向きを変えずに、伸ばすだけの向き

定義

行列 AA を掛けても 向きが変わらず、λ\lambda 倍になるだけ のベクトル vv(0ではない)を、AA の 固有ベクトル、その倍率 λ\lambda(ラムダ)を 固有値 と呼びます。式で書くと、次のとおりです。

Av=λvAv = \lambda v

前のスライドの A=(2112)A = \begin{pmatrix} 2 & 1 \\ 1 & 2 \end{pmatrix} では、

  • (1,1)(1, 1) の向き: AA を掛けると3倍になる → 固有値 3
  • (1,−1)(1, -1) の向き: AA を掛けても1倍のまま → 固有値 1

です。固有ベクトルは「向き」が大事なので、(1,1)(1, 1) でも (2,2)(2, 2) でも同じ固有ベクトルとみなします。ふつうは、長さを1にそろえた (0.707,0.707)(0.707, 0.707) のような形で表します(0.707≈120.707 \approx \frac{1}{\sqrt{2}})。

どう見つけるか

固有値・固有ベクトルを手で求める方法(2行2列なら2次方程式を解く)は大学の数学で学ぶので、ここでは NumPy に任せます。

import numpy as np

A = np.array([[2.0, 1.0],
              [1.0, 2.0]])
vals, vecs = np.linalg.eigh(A)    # 固有値と固有ベクトル(対称な行列用)
print(vals)     # → [1. 3.](小さい順)
print(vecs)     # → [[-0.707  0.707]
                #    [ 0.707  0.707]](各「列」が固有ベクトル)
  • np.linalg.eigh は、対称な行列(左上から右下への対角線について、折り返すと同じになる行列)用の関数です。固有値は小さい順に並びます
  • 固有ベクトルは、vecs の 列 です(vecs[:, 1] が固有値3の固有ベクトル (0.707,0.707)(0.707, 0.707))。行ではないことに注意します
  • 1列目は (−0.707,0.707)(-0.707, 0.707) で、(1,−1)(1, -1) と逆向きですが、同じ向きの線上にあるので、同じ固有ベクトルです

対称な行列の、うれしい性質

対称な行列では、固有ベクトルどうしが必ず 直角に交わります((1,1)(1, 1) と (1,−1)(1, -1) は直角)。第10章の 共分散の表(np.cov が返す2行2列の表)は、いつも対称な行列です。

次のレッスンでは、共分散の表の固有ベクトルが「データが一番大きく広がっている向き」になり、固有値が「その向きの広がり(分散)の大きさ」になることを使います。

特異値分解・ランク・テンソル、振り返り

特異値分解:どんな形の行列にも使える「伸ばす向き」

固有値・固有ベクトルは、正方形の行列(行と列の数が同じ)にしか使えません。データの表のように、行と列の数が違う行列にも使えるように広げたのが、特異値分解(SVD)です。どんな行列 MM も、次の3つの行列の積に分けられます。

M=UΣV⊤M = U \Sigma V^{\top}

「V⊤V^{\top} で回す → Σ\Sigma で、向きごとに伸ばす → UU で回す」という3段階の変形に分けた、という意味です。Σ\Sigma(シグマ)の対角線に並ぶ「伸ばす倍率」を 特異値 と呼び、大きい順に並べます。

M = np.array([[3.0, 1.0],
              [1.0, 3.0],
              [1.0, 1.0]])            # 3行2列の行列
U, s, Vt = np.linalg.svd(M)
print(s)                              # → [4.243 2.   ](特異値、大きい順)

大きい特異値の部分だけを残し、小さい特異値を0にすると、情報をあまり失わずに行列を小さくまとめられます。画像の圧縮や、次のレッスンの主成分分析(scikit-learn の PCA は、内部で特異値分解を使っています)に使われます。

ランク:本当に独立な向きの数

(1224)\begin{pmatrix} 1 & 2 \\ 2 & 4 \end{pmatrix} は、2行目が1行目のちょうど2倍です。この行列を掛けると、平面のどの点も、1本の直線の上に押しつぶされます。このように、行列が変形した後に残る「独立な向きの数」を ランク と呼びます。この行列のランクは1、前のスライドの AA はランク2です。ランクは、0でない特異値の数と一致します(np.linalg.matrix_rank で求められます)。

テンソルと、アダマール積

  • テンソル: 数を並べる方向(軸)の数を問わない、配列の呼び方です。1つの数(0階)、ベクトル(1階)、行列(2階)、さらに「縦 × 横 × 色 × 枚数」の画像のまとまり(4階)など。PyTorch では、配列のことを Tensor と呼びます
  • アダマール積: 同じ形の2つの配列の、同じ位置どうしの掛け算 です。NumPy の * がこれにあたり、第10章の期待値の計算(値 × 確率)でも使いました。行列の積 @ とは違う計算なので、区別します

よくある誤解

  • 「行列を掛けると、ベクトルは必ず向きが変わる」: 固有ベクトルの向きだけは、向きが変わらず伸び縮みするだけです
  • 「np.linalg.eigh の結果の各行が、固有ベクトル」: 固有ベクトルは 列 です(vecs[:, i])
  • 「* と @ は、どちらも行列の掛け算」: * は同じ位置どうしの掛け算(アダマール積)、@ は内積をまとめた行列の積です

振り返り

  • 行列を掛けることは、ベクトル(矢印)を変形することと見られる
  • 固有ベクトルは、行列を掛けても向きが変わらない向きで、固有値はその倍率。対称な行列の固有ベクトルは互いに直角
  • 特異値分解は、どんな形の行列も「回す・伸ばす・回す」に分ける。特異値の大きい部分だけで、行列を近似できる
  • ランクは独立な向きの数。テンソルは軸の数を問わない配列、アダマール積は同じ位置どうしの掛け算

演習

演習を読み込んでいます…