機械学習 はじめよう

第14回 ベイズ線形回帰を実装してみよう

この記事を読むのに必要な時間:およそ 5 分

前回までに紹介したベイズ線形回帰を実装してみます。

ベイジアンという言葉に難しい印象を持たれている方もいるかもしれませんが,実装が劇的に難しくなったりはしませんから,ご安心ください。

ベイジアンに難しいところがあるとすれば,増えたパラメータをどう決めるかという点と,確率分布として求まる解をどう扱うかという点でしょうか。今回はそのあたりも含めて,見ていくことにしましょう。

環境はこれまでと同じPython&numpy&matplotlibを使用します。インストールなどがまだの方は連載第6回を参照ください。

普通の線形回帰のコードを復習

それでは,ベイズ線形回帰を解くコードを実際に書いていくのですが,第11回で書いた普通の線形回帰のコードに必要な部分を書き足す形で進めましょう。ただし,特徴関数φにはガウス基底を使うことにします。

ガウス基底は,次のような正規分布と同じ釣り鐘型をした関数です。ただし分布ではないので正規化は必要ありません。

画像

ガウス基底の良いところは,データ点の近くはその情報を強く使って,離れるにしたがって影響を弱めるという自然なモデルを構成できるところです。

一方の多項式基底は見慣れた多項式という形式で解を得られるというメリットの反面,データが離れた点での推定に影響を強く及ぼすという特徴があります。解の表記に対する制約が強すぎるという言い方もできるでしょう。その点,ガウス基底は解の表記に対する事前の仮定を弱くできます。

ガウス基底を使う場合,上の式の中のciとsをどのように取るか決めなければなりません。

sはデータが影響を及ぼす距離をコントロールするパラメータです。大きくするほど遠くまで影響が届くようになります。そのため小さめの値が望ましいですが,あまり小さくすると,データの密度が低い箇所でどのデータ点も使えず,正しく推論ができないということが起きたりします。今回はs=0.1としておきましょう。

ciはガウス基底の中心です。このガウス基底の線形和で求めたい関数を表すわけですから,回帰を行いたい区間をカバーするように取る必要があります。基本は先ほどのsに設定した値の間隔で取っていけば大丈夫でしょう。というわけで今回は[0,1]区間からs=0.1間隔で取った11個のガウス基底関数を使いましょう。

以下に第11回のコードについて,関数phiをガウス基底に変更したものと,その場合に推定された関数のグラフを掲げます。phiは11個のガウス基底関数に加えて,定数項を表すための1を加えて12次元のベクトルを返します。

import numpy as np
import matplotlib.pyplot as plt

X = np.array([0.02, 0.12, 0.19, 0.27, 0.42, 0.51, 0.64, 0.84, 0.88, 0.99])
t = np.array([0.05, 0.87, 0.94, 0.92, 0.54, -0.11, -0.78, -0.79, -0.89, -0.04])

# 定数項+ガウス基底(12次元) 
def phi(x): 
    s = 0.1 # ガウス基底の「幅」
    return np.append(1, np.exp(-(x - np.arange(0, 1 + s, s)) ** 2 / (2 * s * s)))

PHI = np.array([phi(x) for x in X])
w = np.linalg.solve(np.dot(PHI.T, PHI), np.dot(PHI.T, t))

xlist = np.arange(0, 1, 0.01)
ylist = [np.dot(w, phi(x)) for x in xlist]

plt.plot(xlist, ylist)
plt.plot(X, t, 'o')
plt.show()

画像

12次元のガウス基底は4次元の多項式基底よりずっと自由度と表現力が高いため,推定された関数はかなり「おかしい」状態になってしまっているようです。いわゆる過学習という状態ですね。

これがベイジアンになることでどう変わるかも見て欲しいポイントです。

ちなみに今回,特徴関数をガウス基底に変更したわけですが,コードの変更点がその特徴関数phiの定義を書き換えるだけで済んでいます。このように特徴関数の作り方によらず,パラメータwを特徴行列PHIに対する行列計算だけで決めることができてしまうのが線形回帰の良いところでした。

その点はベイズ線形回帰も同様ですから,PHIを求めるまでのコードはそのまま使っていきましょう。

著者プロフィール

中谷秀洋(なかたにしゅうよう)

サイボウズ・ラボ(株)にてWebアプリ連携や自然言語処理を中心に研究開発を行いながら,英単語タイピングゲーム iVocaをサービス提供している。

URLhttp://d.hatena.ne.jp/n_shuyo/
Twitterhttp://twitter.com/shuyo