Djangoroidの奮闘記

python,django,angularJS1~三十路過ぎたプログラマーの奮闘記

Python DeepLearningに再挑戦 19 学習に関するテクニック 重みの初期値

概要

Python DeepLearningに再挑戦 19 学習に関するテクニック 重みの初期値

参考書籍

重みの初期値 重みの初期値を0にする

  • Weight decay(荷重減衰)->重みパラメータの値が小さくなるように学習を行うことが目的。

  • 初期値0は、基本的にNG。正確には重みを均一な値に設定してはいけない。順伝播時に全て同じ値が伝達されてしまうため、全て同じように更新されてしまうため。

隠れ層のアクティベーション分布

import numpy as np
import matplotlib.pyplot as plt

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

x = np.random.randn(1000, 100)# 1000個のデータ

node_num = 100 # 各隠れ層のノード(ニューロン)の数
hidden_layer_size = 5 # 隠れ層が5層
activations = {} # ここにアクティベーションの結果を格納する

for i in range(hidden_layer_size):
    if i != 0:
        x = activations[i-1] # 1-1, 2-1 ,,,, 5-1 まで続く, xは、1000個のデータ
        
    w = np.random.randn(node_num, node_num)*1 #ガウス分布でランダムにする。
    
    z = np.dot(x, w) # zの出力
    a = sigmoid(z) # sigmoid関数で、出力aを算出
    activations[i] = a # 隠れ層ごとの出力aを算出して代入する。

#以下でヒストグラムを表示させる。
for i, a in activations.items():
    plt.subplot(1, len(activations), i+1)
    plt.title(str(i+1) + "-layer")
    plt.hist(a.flatten(), 30, range=(0,1))
plt.show()
  • sigmoid関数では、0か1に近づくにつれて、変化が緩やかになるため、逆伝播での勾配の値が小さくなって消えてしまう(勾配消失 gradient vanishing)と呼ばれる。

  • 重みの初期設定を変えて再度実行してみる。

 w = np.random.randn(node_num, node_num)*0.01

Xavierの初期値

  • Xavierの初期値:前層からn個のノードの接続がある場合、1/√nの標準偏差を持つ分布を初期値として使う。

f:id:riikku:20161225212147p:plain

  • Xavierの初期値を利用した場合、前層のノードの数が多ければ多いほど、対象ノードの初期値として設定する重みのスケールは小さくなる。
    node_num = 100
    w = np.random.randn(node_num, node_num) / np.sqrt(node_num)    # ガウス分布* 1/√n
  • 初期値は、Xavierの初期値を使うといいのか。

  • sigmoid関数の代わりに、tanh関数(双曲線関数)を用いると改善されるらしい。tanh関数が原点(0,0)で対象なS字カーブで、sigmoidは(x,y)=(0, 0.5)において対象なS字カーブ。活性化関数にはできるだけ原点対象であることが望ましい。