2017/01/31
0:00

TensorFlowによる回帰分析③


TensorFlowによる回帰分析の結果

みなさんこんにちは。
人工知能ラボの助手です。

今回は引き続き、TensorFlowによる回帰実装
を行っていきましょう。

前回は、ステップ③までのお話をしてきましたので、
④から順にやっていきたいと思います。

④誤差関数の定義
理論学習でお話しした2乗誤差を使いましょう。
まずは、以下のコードを見てください。

コード4
#誤差関数の定義(2乗誤差)
loss = tf.reduce_sum(tf.square(y - y_))
これで、変数lossに全データに対する2乗誤差
の合計値が代入されます。
今回は誤差関数として2乗誤差を使用しましたが、
画像認識等で行うクラス分類では、主にクロスエントロピー
という尺度を使用します。
それについては、またの機会にお話ししたいと思っています。

ちなみにこの④の操作は、回帰分析の
理論学習で学んだ
ステップ2:パラメータを含む数式モデルを仮定
に相当します。

⑤誤差関数の最小化手法や学習回数、
 学習率といった学習条件を決定

まず最小化手法について、これは有名なもの
がいくつかあるのですが、今回はこの前説明した
勾配降下法を使用しましょう。
実はこのほかの方法も、基本的にはこの勾配降下法に
何かしらの手を加えたものになっていることが多いです。

学習率は0.001としてみましょう。
それでは、以下のコードを見てください。

コード5
"""学習ステップを以下の設定で定義
最小化手法:勾配降下法、
学習率:0.001
誤差関数lossを最小化
"""

train_step = tf.train.GradientDescentOptimizer(0.001).minimize(loss)
このコードで、学習ステップを定義しています。
誤差関数の最小化手法の定義には、TensorFlowの
trainクラスを使用します。
勾配降下法を利用する場合は、GradientDescentOptimizer
を指定し、引数に学習率を指定します。
(最小化手法を変えたい場合は、GradientDescentOptimizer
の部分を使用する手法に書き換えます)

そして、最後にminimizeで最小化の指定をし、
引数に誤差関数を渡します。
あとすみません、学習回数についてはここではなく、
次のステップ⑥のコードで出てきます。

それでは、最後のステップに進みましょう。

⑥セッションを作成し、変数を初期化後に
 入力データを用いて学習を開始

まずは、前々回の記事でお話しした、セッションの作成と
初期化を行います。

コード6
#初期化の定義
init = tf.initialize_all_variables()

#セッションの作成
sess = tf.Session()

#変数(Variable)の初期化
sess.run(init)
これに関しては、この前お話しした通りなので、説明は
省略します。
それでは、学習を行うためのプログラムを見ていきましょう。

コード7
#学習の実行
for step in range(100):
    sess.run(train_step, feed_dict={x:x_data, y_:y_data})
    
    #10回ごとにデータ1件あたりの誤差を表示
    if (step+1) % 10 == 0:
        print str(step+1)+':'+str(round(math.sqrt((sess.run(loss,feed_dict={x:x_data, y_:y_data}))/5),3))

#学習終了後のパラメータの値を表示
print sess.run(a)
print sess.run(b)
学習の実行にはfor文を使用します。
そして、そのループ回数(今回は100)がそのまま
学習回数となります。

さらに、先ほど定義したtrain_stepを実行します。
また、この右にあるfeed_dictという引数において、
placeholderに入力するデータセットを指定します。
今回であれば、xにはx_data、yにはy_dataが入るので、
このコードの2行目のように記述します。

ここまでが、理論学習で学んだ
ステップ3:最も適したパラメータを決定
に相当します。

学習自体はこの2行目までのコードで終了となります。
ただ、せっかくなので今回の学習結果を簡単に
見てみましょう。

コードの5-7行目を見てください。
学習10回ごとに誤差値を表示しています。
3回ほど前の記事でお話ししたように、誤差関数を
データの件数で割り、そのルートをとることで、1件当たり
の平均誤差値を表示するようにしています。

そして、9行目以降では学習終了後のパラメータa、bの値を
表示しています。
それでは、最後にプログラムを実行してみましょう。

全コード
#coding:utf-8

import tensorflow as tf
import numpy as np
import math

data = np.array([[2,1],[3,14],[-2,1],[10,31],[-5,-6]])

x_data, y_data = np.hsplit(data,[1])

x = tf.placeholder('float', shape=[None,1])
y_ = tf.placeholder('float', shape=[None,1])

a = tf.Variable(tf.truncated_normal([1], stddev=0.1))
b = tf.Variable(tf.constant(1.0, shape=[1]))

y = a*x + b

loss = tf.reduce_sum(tf.square(y - y_))

train_step = tf.train.GradientDescentOptimizer(0.001).minimize(loss)

init = tf.initialize_all_variables()

sess = tf.Session()

sess.run(init)

for step in range(100):
    sess.run(train_step, feed_dict={x:x_data, y_:y_data})

    if (step+1) % 10 == 0:
        print str(step+1)+':'+str(round(math.sqrt((sess.run(loss,feed_dict={x:x_data, y_:y_data}))/5),3))

print sess.run(a)
print sess.run(b)

実行結果
10:4.947
20:4.797
30:4.688
40:4.595
50:4.516
60:4.449
70:4.392
80:4.345
90:4.305
100:4.271
[ 2.52233052]
[ 3.02024484]

式はy=2.522x+3.020、最終的な1件当たりの平均誤差は4.271でした。
実はこの結果を図示したのが、この記事の最初に載ってた画像です。

これを見ると、ある程度適切な直線が
引けているというのが分かりますね。


あと、言い忘れていましたがコードの冒頭でインポートされている
mathというライブラリは、2乗誤差のルートをとるときに使用しています。

ここまででTensorflowを使った回帰分析の実装は終了です。
今回は最も簡単な1変数の回帰直線の式の決定だったので、
非常に簡単なコードとなりました。
ただ、実際に機械学習で利用するニューラルネットワークなど
のモデルは、これと比べるとある程度複雑なものになります。

大変だとは思いますが、そういったものも
いずれは勉強していきましょう。
それでは今回はここまでにしておきましょう。


お疲れ様でした!