LoginSignup
2

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-08-27

概要

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

ネットワークを構成

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

Let's Code

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

学習データの用意

# 0:不合格、1:合格
# 合格状態のデータ
inputs = np.array([
    [0,1,1],
    [1,0,0],
    [0,1,0],
    [1,0,1]])

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

各パラメータの初期化

weightとbias共に2セットが必要です。一つは入力層と隠れ層をつなぐため、もう一つは隠れ層と出力層をつなぐため。エポック数とlearning rateは前回と同じです。

# 入力層と隠れ層をつなぐ weightの初期化
weights_ih = np.array([
    [0.5],
    [0.5],
    [0.5]])

# 入力層と隠れ層をつなぐbiasの初期化
bias_h = np.array([[0.2]])

# 隠れ層と出力層をつなぐweightの初期化
weights_ho = np.array([[0.5]])

# 隠れ層と出力層をつなぐbiasの初期化
bias_o = np.array([[0.2]])

# learning rateの初期化
lr = 0.1

# epochの初期化
epoch = 5000

活性化関数の定義

def activate(x):
    return 1/(1+np.exp(-x))

学習実行


# start training
for _ in range(epochs):
    # feed forward
    # 隠れ層での予測
    prediction_h = activate(np.dot(inputs, weights_ih) + bias_h)

    # 出力層での予測
    prediction_o = activate(np.dot(prediction_h, weights_ho) + bias_o)

    # backpropagation 
    # phase 1:出力層と隠れ層をつなぐweightとbiasの値の調整

    # △wの計算
    error = prediction_o - outputs
    sigmoid_der_prediction_o = prediction_o * (1 - prediction_o)
    der_cost_w_o = np.dot(prediction_h.T,  sigmoid_der_prediction_o * error)

    # △bの計算
    der_cost_b_o = sigmoid_der_prediction_o * error

    # Gradient Descentを使ってweightの調整
    weights_ho -= learning_rate * der_cost_w_o

    # Gradient Descentを使ってbiasの調整
    bias_o -=  learning_rate * np.sum(der_cost_b_o,axis=0,keepdims=True)

    # phase 2
    # 隠れ層と入力層をつなぐweightとbiasの値の調整

    # △wの計算
    sigmoid_der_prediction_h = prediction_h * (1 - prediction_h)
    tmp = sigmoid_der_prediction_h * sigmoid_der_prediction_o * weights_ho * error
    der_cost_w_h = np.dot(inputs.T, tmp)

    # △bの計算
    der_cost_b_h = np.sum(tmp,axis=0,keepdims=True)

    # Gradient Descentを使ってweightの調整
    weights_ih -= learning_rate * der_cost_w_h

    # Gradient Descentを使ってbiasの調整
    bias_h -=  learning_rate * der_cost_b_h

# 学習終了
print("Loss  : {:.8f}".format(error))
print("weight: ", weights_ih.T[0])
print("bias  : ", np.asscalar(bias_h))

評価

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

# 結果を表示するための関数
def get_prediction(data):
    pred_h = activate(np.dot(data, weights_ih) + bias_h)
    pred_o = activate(np.dot(pred_h , weights_ho) + bias_o)
    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のコメントはすべて英語です。
with_single_hidden_layer.ipynb

最後に

今回はニューラルネットワークの基礎を理解する目的で隠れ層を1つのみ実装しました。次回はこれらの知識を応用してかつほかのフレームワークを使ってより複雑なネットワークを作りましょう。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2