検索
連載

Pythonで線形代数!〜行列・応用編(行列式・固有値)数学×Pythonプログラミング入門(3/5 ページ)

AI/機械学習で使われるデータを表現するためにはベクトルや行列などの線形代数を理解することが必要不可欠。今回は行列式と固有値/固有ベクトルの求め方、さらに、それらの応用について、プログラミングの方法を初歩から見ていく。

Share
Tweet
LINE
Hatena

目標3: 固有値と固有ベクトルを求める

 次の目標は、一次変換(後述)を特徴付ける固有値と固有ベクトルを求めることです。方法は、numpy.linalgモジュールのeig関数かscipy.linalgモジュールのeig関数に配列を指定するだけです。eigは固有値を表すeigenvalue(アイゲンバリュー)や固有ベクトルを表すeigenvector(アイゲンベクター)の略です。

 例えば、一次変換を表す以下の行列Aの固有値λ(ラムダ)と固有ベクトルを求めてみましょう。

 固有値として52、固有ベクトルとして(0.89442719,0.4472136)(−0.70710678,0.70710678)が得られれば正解です。手計算で答えを求める方法については省略しますが、気になる方は別連載『AI・機械学習の数学入門 ― 中学・高校数学のキホンから学べる』の「番外編5 線形代数の固有値・固有ベクトルをマスター」を参照してください。固有値や固有ベクトルの考え方は後でちゃんとお話しします。

3. 固有値と固有ベクトルを求めるコードを書く

 では、コードを書いてみましょう(リスト7)。え、固有値や固有ベクトルについての説明はナシでいきなりですか、と思われるかもしれませんが、はい、いきなりです。関数に配列を指定するだけなので簡単です。とにかくやってみてから、意味を考えていきましょう。

import numpy as np
from scipy import linalg

A = np.array([[4, 2],
              [1, 3]])

print("NumPyでの結果:")
print(np.linalg.eig(A))
print("SciPyでの結果:")
print(linalg.eig(A))
# 出力例:
# NumPyでの結果:
# (array([5., 2.]), array([[ 0.89442719, -0.70710678],
#        [ 0.4472136 ,  0.70710678]]))
# SciPyでの結果:
# (array([5.+0.j, 2.+0.j]), array([[ 0.89442719, -0.70710678],
#        [ 0.4472136 ,  0.70710678]]))

リスト7 固有値と固有ベクトルを求める
最初の52が固有値。NumPyでは虚数部がない場合は表示されないが、SciPyでは虚数部がなくても複素数の形で表示される。次の配列の列ベクトルがそれぞれの固有値に対する固有ベクトル。つまり固有値5に対する固有ベクトルが(0.89442719,0.4472136)、固有値2に対する固有ベクトルが(−0.70710678,0.70710678)となる。

 結果は出ましたが、意味不明な値が現れたので「これが何の役に立つんかいな」と思いますよね。そこで、固有値と固有ベクトルの意味を簡単に説明しておきます。動画でも解説しているのでぜひご覧ください。

動画2 固有値と固有ベクトルの意味


 一次変換を表す行列をAとしたときに、以下の式を満たす零ベクトルでないベクトルxA固有ベクトルと呼び、λ固有値と言います。

 固有値や固有ベクトルを理解するには、(3)式の前に、一次変換について知っておく必要がありそうですね。一次変換とは、簡単に言うと座標軸を変えることです。私たちが普段使っているxy座標上のあらゆるベクトルは、x方向の単位ベクトル(1,0)y方向の単位ベクトル(0,1)を使って表せます。例えば、x=(3,4)であれば、

と表せます。これらの単位ベクトルを並べた行列Aを使えば以下のようにも書けます。

 このとき、(1,0)(4,1)に、(0,1)(2,3)に移すように座標を変換するなら、Aを以下のように変えます。すると、x=(3,4)(20,15)に移動することが分かります。

 さて、ここで(3)式に戻りましょう。(3)式を再掲します。

 左辺がここで見てきた一次変換を表します。右辺は一次変換を行った結果ですが、xの定数倍(λ倍)になっています。つまり、(3)式の意味は一次変換を行って移動した先が、元のベクトルの定数倍になっているということです。この式を満たすλが固有値、xが固有ベクトルでしたね。

 残念ながらx=(3,4)は一次変換を行っても定数倍になっていません。(20,15)(3,4)の定数倍ではないので(3)式を満たしません。ところが、定数倍になり、(3)式を満たすベクトルもあります。例えば、x=(2,1)の場合は、

となり、元のベクトルの5倍になっています。従って、この例では固有値λの値は5です。一方の固有ベクトルとは、固有値に対するxのことです。この例ではλ=5に対する固有ベクトルは(2,1)ですね。

 定数倍ということは、原点から引いた同じ直線上にあるということです。元の(2,1)も移動先の(10,5)も、

という直線上にあります。一次変換を行っても、原点から引いた同じ直線上に移動するようなベクトルが固有ベクトルであるということです。

 なお、この例ではもう1つ固有値があり、その値は2となっています。2という固有値に対する固有ベクトルは(1,−1)です。

 ここまで来て(いえ、それ以前に)気付かれた方もおられると思いますが、ここで示した固有ベクトルと、リスト7で求めた固有ベクトルはまったく異なる値です。固有値の方は一致していますね。

 別に答えが間違っているわけではありません。固有ベクトルは同じ直線上にあればどれでもいいからです。上の例では分かりやすいように要素が整数の固有ベクトルを示しましたが、numpy.linalgモジュールのeig関数やscipy.linalgモジュールのeig関数では長さ1の固有ベクトルが返されます。例えば、(2,1)という固有ベクトルは長さが

なので、(2,1)をそれぞれ√5で割って、

とすれば、同じ直線上で長さが1になります。関数が返した値はこれらの値です。

 繰り返しになりますが、手計算で固有値や固有ベクトルを求める方法については、こちらを参照してください。一度、その方法を見ておくと、固有値や固有ベクトルに対する理解も深まります。

Copyright© Digital Advantage Corp. All Rights Reserved.

[an error occurred while processing this directive]
ページトップに戻る