TensorFlow で二次関数の係数を求める
機械学習の進歩で例示によるプログラミングが可能になったという話を読んで、頭ではなんとなく理解しつつも仕組みがさっぱり分からなかったので、なんとなく仕組みが理解できる程度まで調べてみた。
今回はシンプルに二次関数 y=ax^2+bx+c
の入力 x
と出力 y
のペアを複数用意して、各係数を TensorFlow で求めてみる。TensorFlow の実行環境は Google Colaboratory で Notebook を作成するだけで簡単に手に入るので便利だ。なお、以降のコードは TensorFlow 2.0 の使用を前提としている。
まずは「例示」のための二次関数の入力と出力のペアを乱数から生成し学習データとする。これで生成時の係数の値は a=5, b=3, c=2
としておき、TensorFlow でこの値を弾き出せればうまくいったことになる。
import tensorflow as tf
import numpy as np
x_train = np.random.rand(100)
y_train = 5 * x_train * x_train + 3 * x_train + 2
次に2次関数の係数を TensorFlow の変数として定義する。これらの変数は TensorFlow のデータフローグラフの構築に使用する。
a = tf.Variable(tf.zeros(shape=(1)), name="a")
b = tf.Variable(tf.zeros(shape=(1)), name="b")
c = tf.Variable(tf.zeros(shape=(1)), name="c")
y = a * x_train * x_train + b * x_train + c
損失関数と最適化アルゴリズムを決定する。今回は損失関数に平均二乗誤差、最適化アルゴリズムに最急降下法を指定している。このあたりはまだ理解が追いついていない部分なので、より突っ込んだ勉強が必要そうだ。
loss = tf.math.reduce_mean(tf.square(y - y_train))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)
最後に TensorFlow のセッションを開始して、変数を初期化後に学習を実行する。今回は2,000ステップ実行して、学習結果として最後に係数 a, b, c
の値をそれぞれ出力している。
with tf.Session() as sess:
# 変数の初期化
sess.run(tf.initializers.global_variables())
# 学習の実行
for step in range(2000):
sess.run(train)
if step % 100 == 0:
print("Step {:<4}:".format(step), sess.run(a), sess.run(b), sess.run(c))
# 係数 a,b,c の値を出力
print("Result:", sess.run(a), sess.run(b), sess.run(c))
係数の出力結果は以下の通り。ここでは正確な値ではなくて確率的な値を返すようなので注意が必要だが、十分に正解といえる係数の値がちゃんと出力された。
Result: [4.9920454] [3.0083234] [1.9985186]
ここまで実際に手を動かしてみると「例示によるプログラミング」と言われる理由がよく分かる。これまでのプログラミングは入力と出力を一致させるロジックを実装するが、今回のような手法では実装するロジック部分はコンピューターに「計算」させることで導かれるので、入力と出力のペアを複数用意してコンピューターに渡すだけで済む。なので「例示」なのかなと。
一通り仕組みを理解する過程で、微分や行列といった仕組みが機械学習では重要とされる理由がよく分かったのもよかった。コンピューターはロジックを計算する際に最適な値を「探索」しており、そのために微分が使われる。複数の入力からなるロジックの探索は多次元の微分計算になるので、行列を使って効率化している…といったところまではおおよそ理解ができた。
理解にあたっては、以下のドキュメントを参考にした。特に「ロボットカーで学ぶ深層学習の基礎」の資料は、自分のような素人にも分かりやすい内容になっていて素晴らしかった。