ニューラルネットワークの基礎知識 - 3


概要

今回はTensorflowを使って、1つの隠れ層を入れてネットワークを構築します。前回のベースにプログラムを書いているので、もし読んでいない場合は、まず
ニューラルネットワークの基礎知識 - 1
ニューラルネットワークの基礎知識 - 2
を読むことをお勧めします。

ネットワークを構成

今回作成するネットワークは、前回と同じく入力層で3つのニューロン(ノード)を持ち、隠れ層で1つのニューロン、そして出力層でも1つのニューロンを持ちます。


隠れ層のノードは簡単に増減できます。「ニューラルネットワークの基礎知識 - 2」で2つ以上のノードを入れる場合は、複雑なコードを書かなければならないが、Tensorflowを使う事で簡単にノードの増減ができます。また、LOSSを少なくするためにも数学の微分方程式を使っていましたが、そのあたりもTensorflowが私たちの代わりにやってくれますので、短いコードで読みやすいコードを書く事が出来ます。

Let's Code

# numpyのインポート
import numpy as np
# tensorflowのインポート
import tensorflow as tf

学習データの用意

# 0:不合格、1:合格
# 合格状態のデータ
# 数学、英語、物理
inputs = np.array([
    [0,1,1],
    [1,0,0],
    [0,1,0],
    [1,0,1]]).astype(np.float32)

# 0:仕事見つからなかった、1:見つかった
# 仕事見つかった実績
outputs = np.array([
    [1],
    [1],
    [0],
    [1]]).astype(np.float32)

各パラメータの初期化

前回と同じくエポック数とlearning rateを設定します。

# learning rateの初期化
lr = 0.1

# epochの初期化
epoch = 5000

Tensorflowを使って各層の処理を予め登録します。Tensorflowの基礎的な事については、ここはふれませんが、Tensorflowでは、先に処理を定義しておいて、そのあと実行するというイメージを持ってください。以下のようにまず処理を記述します。

# 入力層のノードの数
input_feature = inputs.shape[1]

# 出力層のノードの数
# 自由に変えてOK
num_node = 1

# 入力層と隠れ層をつなぐ weightの初期化
weights_ih = tf.Variable( tf.random_uniform([input_feature,num_node] , minval=0.1 , maxval=0.9 , dtype=tf.float32))

# 入力層と隠れ層をつなぐbiasの初期化
bias_h = tf.Variable( tf.random_uniform( [num_node]   , minval=0.1 , maxval=0.9 , dtype=tf.float32  ))

# 隠れ層での予測
prediction_h  = tf.sigmoid( tf.matmul( inputs, weights_ih ) + bias_h )

# 隠れ層と出力層をつなぐweightの初期化
weights_ho = tf.Variable( tf.random_uniform( [num_node,1] , minval=0.1 , maxval=0.9 , dtype=tf.float32  ))

# 隠れ層と出力層をつなぐbiasの初期化
bias_o = tf.Variable( tf.random_uniform( [1]   , minval=0.1 , maxval=0.9 , dtype=tf.float32  ))

# 出力層での予測
prediction_o  = tf.sigmoid( tf.matmul( prediction_h, weights_ho ) + bias_o )

# lossの計算
loss = tf.reduce_sum( tf.square(outputs - prediction_o ) )

# gradient descentを使ってLossの最小化
train = tf.train.GradientDescentOptimizer(lr).minimize(loss)

以上で各プロセスの記述が終わりです。あとは実行するのみ。

学習実行

with tf.Session() as sess:
  sess.run( tf.global_variables_initializer() )
  for step in range(epoch) :
    sess.run(train)

  weights_ih_f, bias_h_f, weights_ho_f, bias_o_f, error = sess.run([weights_ih, bias_h, weights_ho, bias_o, loss])

# 学習終了
print("Loss  : {:.8f}".format(error))
print("weight ih: ", weights_ih_f)
print("bias h : ", bias_h_f)
print("weights ho: ", weights_ho_f.T[0])
print("bias o : ", np.asscalar(bias_o_f))

評価

どのように学習したか評価します。

# 結果を表示するための関数
def get_prediction(data):
    def activate(x):
        return 1/(1+np.exp(-x))
    pred_h = activate(np.dot(data, weights_ih_f) + bias_h_f)
    pred_o = activate(np.dot(pred_h, weights_ho_f) + bias_o_f)
    msg = "Hired" if round(np.asscalar(pred_o)) else "Not Hired"
    print(data, msg, np.asscalar(pred_o))

# 全科目合格の場合は、仕事見つかるか
get_prediction([1,1,1])

# 物理のみ不合格の場合は、仕事見つかるか
get_prediction([1,1,0])

# 全科目不合格の場合は、仕事見つかるか
get_prediction([0,0,0])

今回も、サンプルデータが少ない事とネットワークが単純すぎるから間違った答えがおおいかもしれませんが、基礎の理解という事でご許しください。

Google Colab

直接Colabから実行することもできますので一度試してみてください。ちなみに、Colabのコメントはすべて英語です。
using_tensorflow.ipynb

最後に

3つの記事を通してニューラルネットワークの基礎について説明しました。皆様の何かの参考になれば幸いです。もしミスや誤文字などがありましたらご指摘頂けたら修正します。