最低限仲良くなりたい頻出な数式や統計量の行列表現
これ何
これまでなんとなく曖昧で避けてきてもなんとかなってきたけど、機械学習を勉強するに当たって当たり前のように出てくる数式や統計量の行列表現を当たり前の知識にする!
僭越ながら、機械学習を勉強すると、様々な理論が固有値問題や単純な確率統計が土台となることを痛感します。
逆にいうと、ベースを固めてしまえば、新しく学ぶ機械学習の理論もスムーズにインプットできると感じます。
まずは、数式の内容自体は簡単だけど見た目が記号になると慣れ親しんでないが故に一気に難しく感じる、ベクトルや行列表現の食わず嫌いを克服したい。
食べ物でいうとなんとなく崇高で見た目もまずそうだけど美味な「うに」を徐々に克服しようといったところ*1。
どんな人向け
例えば、3つの特徴量からなるデータがあった時、1つのサンプルデータを特徴量で重みづけして予測値yを表現するとするなら、
と明示的に表現されればすんなり理解できるけど
より一般化して
と書かれるのは最初は「😇」となっちゃいがちな人*2。
はい、私もです。
一般的なデータのまとめ方
これまで機械学習を学んできて、基本的には
- 1行が1サンプル
- 1列が1特徴量
が原則*3。そして、
- 特徴量=次元の数
である。
i番目のトレーニングサンプルのj個目の特徴量のデータはと表現される。
太字のアルファベットは通常[列ベクトル]を表すと言っていい。
つまりj個目の特徴量を表す列ベクトル(j次元, j変量とも言う)は
行列計算で意識してほしいこと
機械学習においてnumpyを使った行列計算は頻出。
import numpy as np a = np.dot(b, c)
これは、行列積を表す。
このような行列計算を行う際、必ず意識してほしいこと。
行列の行と列の数をチェックする
行列積の計算では、必ず、各要素の外側の行と列が残る。どういうことかというと
例えば
という(2×3)と(3×1)の行列積を考えてみると、答えはとなり、(2×1)となることがわかる。行列積では、内側の数(今回の場合3)は必ず等しい。
そして、残るのは、1つ目の行列の「行」と、最後の行列の「列」だけである。
色々な行列同士の掛け算を見たとき、まず行と列の掛け算をチェックしてみてください。
それを意識するだけで正しい行列演算にたどり着くことも多く、理解の幅が広がります。
それでは、具体的な式をいくつか見ていきます。
線型結合
冒頭でも触れた例。
m個の重みベクトルとデータの入力ベクトルを用いて表される予測値は、式で書くと
pythonで書くと
np.dot(w.T, x)
wとxが両方縦ベクトルの場合, そのままだと(m, 1)と(m,1)の行列演算はできないので片方を転置します。
もし自分で行列の形を設定するとき、wを横ベクトルと考えた場合はという式になり、
np.dot(w, x)
でOK.
また、これはベクトルからベクトルへの射影、すなわち内積を表しているともいえる。
分散(variance)と共分散(covariance)
j個目の特徴量の偏差平方和は、j特徴量における平均を用いてと表される。
j個目の特徴量の(不偏)分散は、偏差平方和を(データ数-1)で割った値である。
共分散は、ある1つのサンプルにおける、2つの特徴量jとkの分散にあたり、との偏差積和をn-1で割ったもの。式で書くと
これを行列で書く(一般化する)と
# X.shape = (n_samples, m) であるとする # 正規化して, 共分散行列を求める u = np.mean(X, axis=0) n_samples = X.shape[0] S = np.dot((X - u).T, (X - u)) / (X_train.shape[0]) # あるいはこれで一発 np.cov(X)
この行列の形は何x何でしょうか?
答えは、(mxm)で、特徴量x特徴量の対角行列です(下図)。
対角成分が分散、右上(左下)が共分散となります。
全生徒の、身長, 体重, 靴のサイズ....といった変数の関係性が見たいと考えるとわかりやすいでしょうか。
相関係数
例えばXとYの共分散は、「(Xの偏差) ×(Yの偏差)」の平均であり、2変数間のばらつきを表す指標と言える。
ただ、これだとスケールに依存するという問題がある。例えばXが数学でYが国語の点数である場合、満点が10点か100点かによって値がかなり変わってくる。
共分散をスケール化したものが、相関係数であり、式で表すと
pythonで書くと
np.corrcoef(X)
固有値問題
これも基礎知識としておくべき事項。
普通、とあるベクトルに行列をかけると、回転して向きが変わる。例えば
となるが、これはというベクトルが、というベクトルに回転&拡大したと見なせる。
しかし、稀に、行列をかけても回転せず大きさだけが変わるベクトルが存在する。このベクトルが固有ベクトル(eigen vector)であり、変化した大きさを表すのが、固有値(eigen value)である。式で書くと
逆に言うと、が解をもつ条件は、正則でなくなる条件式、
具体的な解き方は教科書などを参照してほしい。
ただ、機械学習において固有値問題を解くときは、numpyのパッケージを用いて
np.linalg.eig(A)
で一発で求まるので、解き方に固執する必要はない。
さて、固有ベクトルを横に並べた行ベクトルと、それに対応するように固有値を対角上に並べた対角行列を用いて、行列表現を書くとこうなる
Aの右から逆行列をかけてとなる。
この時、固有ベクトル同士は独立であり、正規直交基底をなす。つまりVは直交行列である。よってであることを用いて
何が嬉しいの
2つある。
1つ目。嬉しいというか、必要です。
機械学習の理論でバンバン出てきます。
主成分分析(Principal Component AnalysisPCA)や、特異値分解(Singular Value Decomposition: SVD: )、線形判別分析(Linear Discriminant Analysis: LDA)といった「次元圧縮」は、この固有値分解がベースといってもいい。
固有値分解の形は必ず理解しよう。
2つ目。少し蛇足かもしれないが、もともと対角化は、を求めるために編み出されたもの*4らしい。
なぜかというと
が成り立つから。(で全て打ち消される)
対角化もろもろについてはこのブログが詳しいのでぜひ。
kriver-1.hatenablog.com
その他呼吸するがごとく当たり前にしたい数式や記号など
ノルム:ベクトルの重みの二乗和の平方根(つまり大きさ)
これを行列で表すと
- (発展)
Frobeniusノルムといい、全成分の二乗和の平方根である。Fの添字がつくことが多い。
pythonでは
np.norm(x)
(ここまで見たように、数値演算では関数が実装されていることが多いnumpyを活用しまくります。)
n×m次元 = n個のデータとm個の特徴量からなる実数空間に属するX。
- 合成関数の微分の求め方
シグモイド関数
この導関数の結果をaを用いて表すとどうなるでしょうか?
スラスラ算出できるようにしましょう*5。
ちなみに、シグモイド関数はnumpyには実装されていないので自分で書く必要があります。
def sigmoid(x): a = 1 / 1 + np.exp(-x) return a
合成関数の微分(またの名を連鎖律)は、単回帰分析における重みの算出(最小二乗法)、からニューラルネットワークまで、あらゆるところで出てきます。超超頻出です。
これ以外にも色々ある気がしますが力尽きてきたので、また今後、追記する可能性ありです。
混乱しがちな行列表現の定義と英語表現
逆行列をもつ行列のこと。
を満たすn次正方行列Bが存在するとき、BをAの逆行列といい、Aは正則であるという。
すごく覚えにくいが、英語でいろんな言い回しがされているので、わかるようにした方が良さそう。
私なりの覚え方↓
regular = 等辺等角 → 数学でいう正多角形の「正」の部分を表す
inversible = 逆にできる → 逆行列が存在する。
non-singular = 非特異値 → なんか0が多くなさそうだから逆行列持ちそう(適当)
- 転置行列: transpose
となるような正方行列A
- 直交行列: orthogonal matrix
となるような正方行列A
- (補足) エルミート行列: hermitian matrix
定義は
ある行列Aの複素共役(複素部分の符号を反対にすればいい)をとり、さらに転置させたが元の行列Aに等しいということ。
つまり、「対称行列」をさらに複素数の行列に対して一般化したもの。
- (補足) ユニタリー行列: unitary matrix
定義は
これは、「直交行列」をさらに複素数の行列に対して一般化したもの。
以下定義省略で英単語リスト
最後に
深夜に思いつく限りのことを書き出しました*6。
私自身、機械学習という底無し沼にしばしば絶望感を覚えつつも、あ〜〜色々分かって繋がって楽し〜〜と思いながら勉強しています。楽しむのが一番です。
至らないところが多々ありますが、初心者視点の本記事が次に勉強する人たちの少しでも役に立てますように。
間違っている箇所があったら指摘していただけると幸いです。