はじめに
日本ディープラーニング協会というものが最近?発足しました. そこでどうやら、エンジニア向けの資格試験(E資格)を実施するそうです. そいつをちょいと受けてみようかと思い立ったので、認定プログラムを受講してきました.
E資格を取ろうと思った動機・経緯、認定プログラムの内容等々は、、、ここでは割愛します. いずれ別記事にまとめるつもりです.
資格試験の実施も近づいてきているので、E資格のシラバスに載っている内容について勉強ノートを作成していますなう. 皆様のお役に立てるかどうかはわかりませんが、とりあえず晒すことにします.
自分用のノートなのであまり親切でもなければ、知識が網羅されているような代物でもありません. とはいえイメージが湧くように、なるべく具体例を交えながら説明していこうと思います. 皆様のお勉強のとっかかりになれば幸いです.
項目
シラバスではざっくり
- 応用数学
- 機械学習
- 深層学習
の3項目に別れています. 本記事では応用数学についてまとめます:
特異値分解
任意の $m \times n$ 行列$A$を、 $A = U\Sigma V$ のような積に分解することを特異値分解といいます.
$U$は$m \times m$の直交行列、 $V$ は $n \times n$ の直交行列、 $\Sigma$ は $m \times n$ の非対角成分が$0$の行列. $\Sigma$の非ゼロ成分のことを特異値と呼びます.
(参考: 特異値分解の定義,性質,具体例)
これが果たして何に役に立つのかというと、どうやら画像の圧縮や情報検索に応用されるようです. ここで、行列$A$が以下のように分解されるとしましょう:
A = \left(
\begin{array}{cc}
a & b \\
c & d
\end{array}
\right)
\left(
\begin{array}{ccc}
x & 0 & 0\\
0 & y & 0
\end{array}
\right)
\left(
\begin{array}{cc}
e & f\\
g & h\\
i & j
\end{array}
\right)
= x\left(
\begin{array}{c}
a \\
c
\end{array}
\right)
\left(
\begin{array}{cc}
e & f
\end{array}
\right)
+ y\left(
\begin{array}{c}
b \\
d
\end{array}
\right)
\left(
\begin{array}{cc}
g & h
\end{array}
\right)
= xu_1v_1^{\mathrm{T}} + yu_2v_2^{\mathrm{T}}
行列 $A$ は特異値を係数とする $u_kv_k^{\mathrm{T}}$ という行列の線型結合で書けることになります.
仮に画像が $408 \times 200 = 81600{\rm pix}$ だったとして、これを $200 \times 408$ 行列 $A$ と見なします. $A$ の特異値が $k$ 個だとすると、要素の個数は $k(200 + 408)$となります. $k$ が少なければ情報量は大幅に削減できることになります.
式を見てわかるとおり線型結合となる行列 $u_kv_k^{\mathrm{T}}$ の重みは特異値になるので、大きい特異値の項のみを拾ってくるとさらに要素を圧縮できます. 具体的に画像の次元を削減してみましょう:
import numpy as np
import matplotlib.pyplot as plt
import copy
with open('Toro.pgm', 'r') as f:
# Read from pgm file
A = f.readlines()
column, row = np.array(A[2].split(' ')).astype('int')
A = np.array(A[4:]).astype('int').reshape(row, column)
U, s, V = np.linalg.svd(A, full_matrices=True) # Execute SVD
A_svd = np.zeros((row, column))
A_svd_arr = []
append_interval = np.array([10, 25, 50])
for i, sigma in enumerate(s):
# Add terms in descending order
A_svd += s[i] * U[:, i:i+1] * V[i:i+1, :]
if np.any(append_interval == i):
A_svd_arr.append(copy.deepcopy(A_svd))
print('Singular values: {}'.format(s[:5]))
# >> Singular values: [ 70325.90261891, 2522.70275689, 2038.5399065, 1889.48437463, 1787.74643761]
# Plot
plt.figure(figsize=(7.5, 5))
for i in range(3):
plt.subplot(2, 2, i+1, xticks=[], yticks=[])
plt.title('i = {0}, elements = {1}'.format(append_interval[i],
append_interval[i] * (row + column)))
plt.axis('off')
plt.imshow(A_svd_arr[i], cmap='gray', vmin=50, vmax=255)
plt.subplot(2, 2, 4, xticks=[], yticks=[])
plt.title('i = {0}, elements = {1} (original)'.format(len(s), row * column))
plt.axis('off')
plt.imshow(A, cmap='gray', vmin=50, vmax=255)
次元を削りすぎると流石に荒っぽい画像になってしまいますが、半分以下に圧縮してもそんなに違和感ないですね. こういった処理のことを主成分分析と呼びます.
特異値分解は線形代数演算ライブラリのベンチマークとして用いられることも多く、線形代数では基本的な処理なのでしょうが、、、今回勉強して初めて応用例が理解できました. 画像の圧縮って案外簡単にできるんですね.
(参考: 特異値分解とその応用)
一般的な確率分布
機械学習で用いる確率分布についてです. コレ以外にもいろいろ使うとは思いますが.
ベルヌーイ分布
定義は以下の通り:
$f(k;\ p) = p^k(1-p)^{1-k}\ \ {\rm for}\ k\ \in {0, 1}$
事象$k$が起きる確率を$p$、起きない確率を$1-p$とするような確率分布. 事象が表裏一体になっています.
たとえば、サイコロの目が3で割り切れる事象を1、3で割り切れない事象を0とすると、
$f\left(k;\ p=\frac{1}{3}\right) = \frac{1}{3}^k\left(\frac{2}{3}\right)^{1-k}$
2項分布に似ていますね.
マルチヌーイ分布
定義は以下の通り:
$p(n_1,...,\ n_k) = \cfrac{n!}{n_1!,...,\ n_k!}\ p_1^{n_1} ...\ p_k^{n_k}$
2項定理の拡張版で、高校でやった多項定理です.
たとえば、サイコロを4回続けて投げるとき、1の目が2回、4の目が1回、5の目が1回出る確率は
$p(2, 1, 1) = \cfrac{4!}{2!1!1!}\ \left(\frac{1}{6}\right)^{2}\left(\frac{1}{6}\right)^{1}\left(\frac{1}{6}\right)^{1}$
ガウス分布
定義は以下の通り:
$f(x) = \cfrac{1}{\sqrt{2\pi\sigma^2}}\ e^{-\frac{(x-\mu)^2}{2\sigma^2}}$
$\mu$は分布の平均値、$\sigma$は標準偏差.
言わずもがな、最も大事な分布関数. 世界はガウシアンでできている.
中心極限定理のおかげで、自然現象を含んだありとあらゆる場面で顔を見せます. 加えて関数としての性質もよく、複雑怪奇な計算に陥りやすい量子論のオアシスでもあります. VAEとかでも登場しますね.
import math as m
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-5, 5, 100)
mu, sigma = 0, 1
plt.plot(x, 1/m.sqrt(2 * m.pi * sigma**2) * np.exp(-(x - mu)**2 / (2 * sigma**2)))
ベイズ則
定義は以下の通り:
$$
P(B|A) = \cfrac{P(A|B)P(B)}{P(A)}
$$
$P(B|A)$は条件付き確率で、事象Aが起こったときのBの確率.
また、分子は$P(A|B)P(B) = P(A\cap B)$を書き換えることができる.
これだとイメージが沸かないので具体的な例をば1つ.
「サイコロを2回投げたとする. その2つの目の積が偶数(A)だったとき、3の倍数(B)である確率を求めよ」
この問題が意味するところは$P(B|A)$ですが、これについてベイズ則が成り立っているかどうかを確認してみます.
- ベイズ則左辺
白黒問わず、丸が付いているところは積が偶数のところです. 27個あります.
黒丸のところはその27個のうち、積が3の倍数のところです. 15個あります.
ということで、$P(B|A) = \frac{15}{27}$となります.
- ベイズ則右辺
次にベイズ則右辺です.
目の積が偶数である確率は$P(A) = 1 - \frac{3}{6}\cdot\frac{3}{6} = \frac{27}{36}$
目の積が3の倍数である確率は$P(A) = 1 - \frac{2}{6}\cdot\frac{2}{6} = \frac{20}{36}$
白黒問わず、丸が付いているところは積が3の倍数のところです. 20個あります.
黒丸のところはその20個のうち、積が偶数のところです. 15個あります.
ということで、$P(A|B) = \frac{15}{20}$
これでベイズ則右辺を求める準備ができました. 計算してみましょう:
$(右辺) = \cfrac{P(A|B)P(B)}{P(A)} = \cfrac{15}{20}\cdot\cfrac{20}{36}\cdot\cfrac{36}{27} = \cfrac{15}{27}$
- まとめ
左辺と右辺が一致したので、この例に関してはベイズ則は成り立っていることがわかりました. もちろんこれは証明ではありませんが、なんとなく式の意味しているところは解っていただけたと思います.
ベイズ則は、$P(B|A)$は直接求めにくいけど$P(A|B)$は簡単に求められるような場合に威力を発揮します.
ちなみにここまで読めばもうおわかりだと思いますが、
「サイコロを2回投げたとする. その2つの目の積が偶数(A)だったとき、3の倍数(B)である確率を求めよ」
「サイコロを2回投げたとする. その2つの目の積が偶数(A)かつ、3の倍数(B)である確率を求めよ」
は全く異なる概念です. 上は$P(B|A)$、下は$P(A\cap B)$です. ここでは詳しく説明はしませんが、頭に?マークが浮かんだ方はじっくり考えてみて下さい. 高校数学の良い復習になると思います.
情報理論
ざっくりしすぎなので割愛、、、情報エントロピーとかそのへん勉強しておけばよいのだろうか.
ML/DLの勉強途上で必要になったら都度勉強しましょう.
おわりに
わりとあっさりした内容ではありますが、以上です. まあそもそもこれが本題ではないですしね、、、
機械学習編に続きます.