TensorFlow : Edward : Tutorials : ベイジアン線形回帰モデル (教師あり学習 (回帰)) (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
更新日時 : 11/19, 11/11/2018
作成日時 : 10/15/2018
* 本ページは、Edward サイトの Tutorials : Supervised Learning (Regression) を翻訳した上で適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
教師あり学習 (回帰)
教師あり学習では、タスクは訓練サンプル $\{(x_n, y_n)\}$ から成る、ラベル付けられたデータから隠れ構造を推論することです。回帰は典型的には出力 $y$ は連続値を取ることを意味します。
Edward で例により示します。Jupyter notebook による対話的なバージョンは こちら で利用可能です。
データ
$40$ データポイントの訓練とテストセットをシミュレートします。それらは入力 $\mathbf{x}_n\in\mathbb{R}^{10}$ と出力 $y_n\in\mathbb{R}$ のペアから成ります。それらは正規分布に従うノイズを伴う線形従属性を持ちます。
def build_toy_dataset(N, w, noise_std=0.1): D = len(w) x = np.random.randn(N, D) y = np.dot(x, w) + np.random.normal(0, noise_std, size=N) return x, y N = 40 # number of data points D = 10 # number of features w_true = np.random.randn(D) X_train, y_train = build_toy_dataset(N, w_true) X_test, y_test = build_toy_dataset(N, w_true)
モデル
モデルをベイジアン線形回帰として仮定します (Murphy, 2012)。それは入力 $\mathbf{x}\in\mathbb{R}^D$ と出力 $y\in\mathbb{R}$ の間の線形関係を仮定します。
$N$ データポイント $(\mathbf{X},\mathbf{y})=\{(\mathbf{x}_n, y_n)\}$ に対して、モデルは次の分布を仮定します :
\[\begin{aligned}
p(\mathbf{w})
&=
\text{Normal}(\mathbf{w} \mid \mathbf{0}, \sigma_w^2\mathbf{I}),
\\[1.5ex]
p(b)
&=
\text{Normal}(b \mid 0, \sigma_b^2),
\\
p(\mathbf{y} \mid \mathbf{w}, b, \mathbf{X})
&=
\prod_{n=1}^N
\text{Normal}(y_n \mid \mathbf{x}_n^\top\mathbf{w} + b, \sigma_y^2).\end{aligned}
\]
潜在変数は線形モデルの重み $\mathbf{w}$ とバイアスとしても知られる、切片 $b$ です。$\sigma_w^2,\sigma_b^2$ は既知の事前 (分布) 分散で $\sigma_y^2$ は既知の尤度分散であると仮定します。尤度の平均は入力 $\mathbf{x}_n$ の線形変換で与えられます。
$\sigma_w,\sigma_b,\sigma_y=1$ を固定して、Edward でモデルを構築しましょう。
from edward.models import Normal X = tf.placeholder(tf.float32, [N, D]) w = Normal(loc=tf.zeros(D), scale=tf.ones(D)) b = Normal(loc=tf.zeros(1), scale=tf.ones(1)) y = Normal(loc=ed.dot(X, w) + b, scale=tf.ones(N))
ここで、プレースホルダ X を定義します。推論の間、データに従ってこのプレースホルダに値を渡します。
推論
今は変分推論を使用して事後分布を推論することに取り掛かります。変分モデルを重みに渡る、完全に分解された正規分布 (= fully factorized normal) として定義します。
qw = Normal(loc=tf.get_variable("qw/loc", [D]), scale=tf.nn.softplus(tf.get_variable("qw/scale", [D]))) qb = Normal(loc=tf.get_variable("qb/loc", [1]), scale=tf.nn.softplus(tf.get_variable("qb/scale", [1])))
アルゴリズムで $250$ 反復と $5$ 潜在変数サンプルを使用して、Kullback-Leibler ダイバージェンスで変分推論を実行します。
inference = ed.KLqp({w: qw, b: qb}, data={X: X_train, y: y_train}) inference.run(n_samples=5, n_iter=250)
この場合 KLqp は再パラメータ化勾配を使用する $\text{KL}(q\|p)$ ダイバージェンス measure の最小化にデフォルト設定されます。
推論のより詳細については、$\text{KL}(q\|p)$ チュートリアル を見てください。
批評 (= Criticism)
回帰のための標準的な評価は取り置きの「テスト」データ上で予測精度を比較することです。最初に事後予測分布を形成することでこれを行ないます。
y_post = ed.copy(y, {w: qw, b: qb}) # This is equivalent to # y_post = Normal(loc=ed.dot(X, qw) + qb, scale=tf.ones(N))
これでモデルからの予測 (事後予測) を使用して様々な数量を評価できます。
print("Mean squared error on test data:") print(ed.evaluate('mean_squared_error', data={X: X_test, y_post: y_test}))
## Mean squared error on test data: ## 0.0300492 ## Mean absolute error on test data: ## 0.123616
訓練されたモデルは (出力の大きさと比較すると) 低い誤差で予測を行ないます。
(最初の特徴次元上で) 事前 (分布) で生成されたデータを事後 (分布) で生成されたデータと比較することにより fit() も可視化できます。
def visualise(X_data, y_data, w, b, n_samples=10): w_samples = w.sample(n_samples)[:, 0].eval() b_samples = b.sample(n_samples).eval() plt.scatter(X_data[:, 0], y_data) inputs = np.linspace(-8, 8, num=400) for ns in range(n_samples): output = inputs * w_samples[ns] + b_samples[ns] plt.plot(inputs, output)
# Visualize samples from the prior. visualise(X_train, y_train, w, b)
# Visualize samples from the posterior. visualise(X_train, y_train, qw, qb)
モデルは $\mathbf{x}\in\mathbb{R}^D$ の最初の次元と出力 $y\in\mathbb{R}$ の間の線形関係を学習しました。
References
- Murphy, K. P. (2012). Machine learning: A probabilistic perspective. MIT Press.
以上