固有ベクトルは向きが変わらない方向
固有ベクトルとは、行列を掛けても向きが変わらず、長さだけが変わるベクトルです。長さが何倍になるかを、固有値といいます。
機械学習では、データがいちばん大きく散らばる方向を見つけるために、固有ベクトルを使います。たくさんの数を、少ない数に減らす手がかりになります。
このレッスンのゴール
メモ
固有ベクトルと固有値を説明し、機械学習で使われる理由を言うことができる。
キーワード
| ことば | いみ |
|---|---|
| 固有ベクトル | 行列を掛けても、向きが変わらないベクトル |
| 固有値 | 固有ベクトルが何倍になるかを表す数 |
| べき乗法 | 行列を掛けては長さを 1 に戻す、くり返しの方法 |
| 次元削減 | 成分の数を、情報をなるべく残して減らすこと |
| 主成分 | データがいちばん大きく散らばる方向 |
学生が入力するセルは、このプレビューでは空白です。
伸び縮みするだけの方向がある
行列を掛けると、ふつうは、ベクトルの向きも長さも変わります。ところが、向きが変わらず、伸び縮みするだけの方向があります。
その方向のベクトルが固有ベクトルです。伸びる倍率が固有値で、1 より小さければ縮み、負なら反対向きになります。
例: 行列 [[2, 1], [1, 2]] の働き
| ベクトル | 行列を掛けた結果 | 向きと長さ |
|---|---|---|
| [1, 1] | [3, 3] | 向きは同じで、3倍(固有値 3) |
| [1, -1] | [1, -1] | 向きは同じで、1倍(固有値 1) |
| [1, 0] | [2, 1] | 向きが変わる(固有ベクトルではない) |
学生が入力するセルは、このプレビューでは空白です。
3つのベクトルを動かす
# 行列 [[2, 1], [1, 2]] を、3つのベクトルに掛けます。
vectors = [[1, 1], [1, -1], [1, 0]]
for v in vectors:
x = 2 * v[0] + 1 * v[1]
y = 1 * v[0] + 2 * v[1]
print(v, "->", [x, y])
# [1, 2] を加えて、向きが変わるかどうか予想してから実行してください。
NumPy で固有値を求める
docker exec jupyter python3 -c "import numpy as np; a = np.array([[2, 1], [1, 2]]); print(a @ np.array([1, 1]), np.linalg.eigvalsh(a))"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
掛け続けると最大の方向に近づく
適当なベクトルから始めて、行列を何度も掛けます。向きは、最大の固有値の固有ベクトルへ近づいていきます。
これがべき乗法です。値が大きくなりすぎないように、毎回、長さを 1 に戻します。倍率の見積もりが、固有値です。
例: [1, 0] から掛け続ける
| 回 | ベクトル | 1つ目の成分の倍率 |
|---|---|---|
| 0 | [1, 0] | - |
| 1 | [2, 1] | 2 ÷ 1 = 2 |
| 2 | [5, 4] | 5 ÷ 2 = 2.5 |
| 3 | [14, 13] | 14 ÷ 5 = 2.8 |
| 4 | [41, 40] | 41 ÷ 14 = 約 2.93 |
学生が入力するセルは、このプレビューでは空白です。
よくある間違い
注意
多くの人は、固有ベクトルを、行列を掛けても動かないベクトルだと考えます。動かないのは向きだけで、長さは固有値の倍になります。固有値が 1 のときだけ、元と同じです。
行列を掛け続ける
# 同じ行列を、何度も掛けます。値は大きくなりますが、向きは落ち着いていきます。
v = [1, 0]
for step in range(4):
v = [2 * v[0] + v[1], v[0] + 2 * v[1]]
print(step + 1, "回目:", v, "比:", round(v[1] / v[0], 3))
# range(4) を range(6) に変えて、比がどこに近づくか見てください。
主成分は散らばりの大きい方向
気温と貸出台数を、どちらも平均 0、ばらつき 1 にそろえて、相関行列を作ります。その固有値は、約 1.77 と約 0.23 です。
合計 2 のうち約 88% が1つの方向にあるので、2つの数を、その1つで表しても、情報はあまり失われません。これが次元削減です。
気温と貸出台数の固有値を調べる
docker exec jupyter python3 -c "import numpy as np; d = np.genfromtxt('hires.csv', delimiter=',', skip_header=1, usecols=(4, 6)); print(np.round(np.linalg.eigvalsh(np.corrcoef(d.T)), 2))"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
さらに挑戦: 3つの成分で
気温、雨量、貸出台数の3つを、同じようにそろえて、相関行列の固有値を3つ求めてみましょう。
合計は 3 になります。いちばん大きい固有値が、全体の何割を占めるかを、一文で書きましょう。