機械学習に詳しくなりたいブログ

機械学習や数学について勉強した内容を中心に書きます。100%趣味です。記事は数学的に厳密でなかったり誤りを含んでいるかもしれません。ご指摘頂ければ幸いです。

19年9月の振り返り

去年の投信評価損-300万からだいぶ挽回してきて、もうすぐプラスに転じそうだというところで今月もあと一歩が及ばず。(一昨年まででけっこう含み益があったのです)  昨年は10月に相場が大きく下がりましたが、今年はどうなるか。

19年9月の実績
Web収入 投信 前月比評価損益
700,380円 457,767円 1,158,147円
19年の累積
Web収入 投信評価損益 個別株
5,842,104円 1,472,519円 705,618円 8,020,241円

ラプラス近似

関数f(\mathbf{x})を正規分布の形状で近似する方法です。

f(\mathbf{x})の対数をとった\ln f(\mathbf{x})において、\nabla \ln f(\mathbf{x})=\mathbf{0}となる点\mathbf{x}^{\prime}まわりでのテイラー展開による2次近似を考えます。多変数関数の点(x_{1}^{\prime} , \cdots ,x_{n}^{\prime})まわりのテイラー展開は、


\displaystyle f(x_1,\cdots, x_n) \simeq \sum_{k=0}^{\infty}\frac{1}{k!} \left\{ (x_1-x_{1}^{\prime}) \frac{\partial}{\partial x_1} +\cdots+(x_n-x_{n}^{\prime}) \frac{\partial}{\partial x_n} \right\}^{k}f(x_{1}^{\prime},\cdots, x_{n}^{\prime})\tag{1}

ですので、\ln f({\mathbf{x}})の点\mathbf{x}^{\prime}まわりでのテイラー展開による2次近似は、


\displaystyle \ln f(\mathbf{x}) \simeq \ln f(\mathbf{x}^{\prime}) +\displaystyle \frac{1}{2} (\mathbf{x}-\mathbf{x}^{\prime})^{T}\bar{\mathbf{H}} (\mathbf{x}-\mathbf{x}^{\prime}) \tag{2}

です。(参考:ヘッセ行列で極値の判定 *1)ここで


\displaystyle \bar{\mathbf{H}} = \nabla \nabla \ln f(\mathbf{x}) |_{\mathbf{x}=\mathbf{x}^{\prime}} \tag{3}

です。


\displaystyle \mathbf{A} = -\bar{\mathbf{H}} \tag{4}

とすれば、


\displaystyle \ln f(\mathbf{x}) \simeq \ln f(\mathbf{x}^{\prime}) - \displaystyle \frac{1}{2} (\mathbf{x}-\mathbf{x}^{\prime})^{T} \mathbf{A} (\mathbf{x}-\mathbf{x}^{\prime}) \tag{5}

です。対数を外せば、


\displaystyle f(\mathbf{x}) \simeq f(\mathbf{x}^{\prime}) \exp \left\{ -\frac{1}{2} (\mathbf{x}-\mathbf{x}^{\prime})^{T} \mathbf{A} (\mathbf{x}-\mathbf{x}^{\prime}) \right\} \tag{6}

です。式(6)はまさに多変量正規分布の形をしています。

試しにf(x)=\cos xをラプラス近似してみました。計算に自信がなかったので簡単な1変数関数にしてしまいました。これをラプラス近似すると、


\displaystyle \cos x \simeq  \exp \left( -\frac{x^{2}}{2} \right) \tag{7}

となりました。グラフにすると下図のようになり、確かに近似になっていそうです。 f:id:opabinia2:20190922230009p:plain

*1:文字の表現が少し違ってるので、対比して見ると余計ややこしくなりそうですが

ガウスカーネル

概要

カーネル法で書いたとおり、カーネル関数は特徴ベクトルの内積


k(\mathbf{x},\mathbf{x}^{\prime}) = \phi(\mathbf{x})^{T} \phi(\mathbf{x}^{\prime})  \tag{1}

として定義されます。

よく使われるカーネル関数として以下のガウスカーネルがあります。


\displaystyle k(\mathbf{x},\mathbf{x}^{\prime}) = \exp \left( \frac{-\| \mathbf{x} - \mathbf{x}^{\prime} \|^{2}}{2\sigma^{2}} \right)  \tag{2}

今回はガウスカーネルがカーネル関数の定義を満たしており、かつ無限次元の特徴ベクトルで表されることを確認します。

カーネル関数であることの確認

ガウスカーネルの\expの中の分子を展開します。ベクトルのノルムの式(5)や転置行列の定理の式(4)、(5)より、


\begin{eqnarray*}
\| \mathbf{x} - \mathbf{x}^{\prime} \|^{2} &=& (\mathbf{x} - \mathbf{x}^{\prime})^{T} (\mathbf{x} - \mathbf{x}^{\prime}) \tag{3}\\
&=&  (\mathbf{x}^{T} - (\mathbf{x}^{\prime})^{T}) (\mathbf{x} - \mathbf{x}^{\prime}) \tag{4} \\
&=& \mathbf{x}^{T}\mathbf{x}  -\mathbf{x}^{T}\mathbf{x}^{\prime} - (\mathbf{x}^{\prime})^{T} \mathbf{x}  + (\mathbf{x}^{\prime})^{T} \mathbf{x}^{\prime} \tag{5} \\
&=& \mathbf{x}^{T}\mathbf{x}  -2\mathbf{x}^{T}\mathbf{x}^{\prime}   + (\mathbf{x}^{\prime})^{T} \mathbf{x}^{\prime} \tag{6} 
\end{eqnarray*}

と展開できます。これを式(2)に代入すれば、


\begin{eqnarray*}
\displaystyle \exp \left( \frac{-\| \mathbf{x} - \mathbf{x}^{\prime} \|^{2}}{2\sigma^{2}} \right) &=& \exp\left( -\frac{ \mathbf{x}^{T}\mathbf{x}  -2\mathbf{x}^{T}\mathbf{x}^{\prime}   + (\mathbf{x}^{\prime})^{T} \mathbf{x}^{\prime}}{2\sigma^{2}} \right)  \tag{7}\\
&=& \exp \left( \frac{-\mathbf{x}^{T}\mathbf{x}}{2\sigma^{2}} \right) \exp \left( \frac{\mathbf{x}^{T}\mathbf{x}^{\prime}}{\sigma^{2}} \right) \exp \left( \frac{-(\mathbf{x}^{\prime})^{T} \mathbf{x}^{\prime}}{2\sigma^{2}} \right) \tag{8}
\end{eqnarray*}

となります。

k_1(\mathbf{x},\mathbf{x}^{\prime}) がカーネル関数ならば、\exp(k_1(\mathbf{x},\mathbf{x}^{\prime}))f(\mathbf{x}) k_1(\mathbf{x},\mathbf{x}^{\prime}) f(\mathbf{x}^{\prime})もまたカーネル関数であるという性質*1を使えば、\mathbf{x}^{T}\mathbf{x}^{\prime}は内積そのものでカーネル関数ですから、式(8)はカーネル関数であることがわかります。以上より、ガウスカーネルはカーネル関数であることが確認できました。

無限次元の特徴ベクトルで表されることの確認とカーネルトリック

e^{x}をマクローリン展開すると、


\begin{eqnarray*}
\displaystyle f(x) = e^{x} &=& \sum_{n=0}^{\infty} \frac{f^{(n)}(0) }{n!}x^{n} \tag{9}\\
&=& \sum_{n=0}^{\infty}  \frac{x^{n}}{n!} \tag{10}
\end{eqnarray*}

ですから、


\displaystyle \exp \left( \frac{\mathbf{x}^{T}\mathbf{x}^{\prime}}{\sigma^{2}} \right) = \sum_{n=0}^{\infty} \frac{1}{n!} \left( \frac{\mathbf{x}^{T}\mathbf{x}^{\prime}}{\sigma^{2}} \right)^{n} \tag{11}

となり、ガウスカーネルは無限次元の特徴ベクトルを持つことがわかります。でも無限次元の特徴ベクトルの内積を直接計算することなく、式(2)のガウスカーネルの計算をするだけで無限の特徴ベクトルを扱ったのと同義になります。うまいことできてますね。これはカーネルトリックと呼ばれるテクニックのようです。

*1:特に説明を書いていませんが、ここでは既知のものとして扱います。その他、様々な性質があるようです

19年8月の振り返り

8月はずいぶん相場が乱高下してました。まだ当分不安定な状況が続くんですかね。

中断してしまっていた機械学習の勉強をそろそろ再開します。思い出すのが大変なんですよね。思い出すために自分の書いた記事を読み直すんですが、書いたときはわかりやすいと思っていた内容が、読み直すとけっこうひどい。内容が難しくなるにつれて理解の自信も落ちるので、断定的な表現を避けた文章を書いてしまっているか、無意識に曖昧にしてしまっているのかもしれない。いや、まだ読み直していないので想像ですけど。

19年8月の実績
Web収入 投信 前月比評価損益
724,572円 -660,716円 63,856円
19年の累積
Web収入 投信評価損益 個別株
5,141,724円 1,014,752円 705,618円 6,862,094円

19年7月の振り返り

7月はWeb収入も投信も調子が良かった。最近はやりたいことが多くて機械学習に時間が割けていない。おそらく機械学習の記事を期待してくださっているであろう36名の読者の方へ、2回連続でお金の記事を流してしまうことに罪悪感を感じる。

19年7月の実績
Web収入 投信 前月比評価損益
758,917円 367,059円 1,125,976円
19年の累積
Web収入 投信評価損益 個別株
4,417,152円 1,675,468円 705,618円 6,798,238円

19年6月の振り返り

前月はずいぶん相場が下がったけど、6月はちょっと持ち直した。今日7月1日は日経平均も大幅に上昇して7月は幸先の良いスタート。といっても、昨年の-300万が大きすぎて、まだ含み損なんですけど。プラ転まであと一息。 Web収入は大型連休のあった先月よりなぜか上昇。単純計算だと今年のWeb収入は700万いくかどうかってところでしょうか。

19年6月の実績
Web収入 投信 前月比評価損益
622,752円 340,576円 963,328円
19年の累積
Web収入 投信評価損益 個別株
3,658,235円 1,308,409円 705,618円 5,672,262円

ガウス過程による回帰(3)実験結果

概要

今回は、以下の記事を経て導出した結果


\displaystyle m(\mathbf{x}_{N+1}) = \sum_{n=1}^{N} a_{n} k(\mathbf{x}_n,\mathbf{x}_{N+1}) \tag{1}

を使って、ガウス過程による回帰を実験してみました。

www.iwanttobeacat.com

www.iwanttobeacat.com

www.iwanttobeacat.com

ガウス過程による回帰の実験結果

早速結果です。カーネル関数はガウスカーネルを使いました。また、予測分布p(t_{N+1}| \mathbf{t})も求めてみました。 カーネルを用いた回帰でも、カーネル回帰分析(2)実験結果とはずいぶん傾向が違いますね。今回の訓練データの場合では、ガウスカーネルでなくても、多項式モデルから\mathbf{K}を計算してもちゃんと予測分布が求められました。事前分布のパラメータ\alphaの定数倍を微調整する必要がありましたが。ちなみに、線形回帰をベイズ推定で解く(2)予測分布をプロットで求めた予測分布は、線形モデルのパラメータ\mathbf{w}の事前分布を設定し、訓練データから事後分布を求め、\mathbf{w}について積分することで予測分布を求めていました。ガウス過程による回帰も、出発点はパラメータ\mathbf{w}の事前分布を設定することでしたが、考え方がいろいろあって面白いですね。

ガウスカーネルの分散を小さくしてみたら面白い結果になりました。 ガウスカーネルの分散が小さいということは、隣の訓練データの影響が小さくなるのでいびつな回帰曲線になってしまうんですね。

サンプリング

ガウス過程で実験してみたようにサンプリングしてみました。



左がガウス過程の記事でサンプリングした結果。yの期待値は0でしたから、0付近をうろうろした結果となっています。一方で平均値が式(1)で求められた右のサンプリングはどれも訓練データである正弦波を再現するようなサンプリングとなりました。

今回のコードです。

# ガウス過程による回帰
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm


def k(x0, x1):
    sigma = 0.3
    return np.exp(-(x0 - x1) ** 2 / (2 * sigma ** 2))
    # ret = 0
    # for i in range(5):
    #  ret += x0**i * x1**i
    # return ret/0.01


# グラム行列
def gram_matrix(x):
    gram = np.empty([N, N])
    for i in range(N):
        for j in range(N):
            gram[i, j] = k(x[i], x[j])
    return gram


# p(t_N+1|t)
def pt(x1, y1):
    k_t = np.vectorize(k)(x.T, np.repeat(x1, N))
    mu = k_t @ a
    v = k(x1, x1) + 1.0/BETA - k_t @ Cn_inv @ k_t
    return np.exp(-(y1 - mu) ** 2 / (2 * v)) / np.sqrt(2*np.pi*v)


# ランダムシードを固定
np.random.seed(0)
# 訓練データ数
N = 10

# 訓練データ
x = np.linspace(0, 1, N)
t = np.sin(2*np.pi*x.T) + np.random.normal(0, 0.2, N)

# 係数aを求める
BETA = 5.0
Cn_inv = np.linalg.inv(gram_matrix(x) + 1.0/BETA*np.eye(N))
a = Cn_inv @ t


# 新たな入力x2に対する予測値yを求める
x2 = np.linspace(0, 1, 100)
y = np.empty(100)
for i in range(x2.size):
    y[i] = np.vectorize(k)(x.T, np.repeat(x2[i], N)) @ a


# 結果の表示
plt.xlim(0.0, 1.0)
plt.ylim(-1.5, 1.5)
plt.scatter(x, t)
plt.plot(x2, y)
plt.show()

# 予測分布 p(t_N+1|t)
X, Y = np.meshgrid(np.linspace(-0, 1, 100), np.linspace(-1.5, 1.5, 100))
Z = np.vectorize(pt)(X, Y)
plt.contourf(X, Y, Z, cmap=cm.coolwarm)
plt.scatter(x, t)
plt.xlim(0, 1)
plt.ylim(-1.5, 1.5)
plt.show()