<目次>
(1) 確率的勾配降下法(SGD)をロジスティック回帰に適用しPythonで実装した例をご紹介
(1-1) (課題)「勾配降下法」が抱える課題
(1-2) (対策)確率的勾配降下法(SGD)とは?
(1-3) (実装)Pythonで実装する際のポイント
(1-4) (実装例)サンプルプログラム
(1) 確率的勾配降下法(SGD)をロジスティック回帰に適用しPythonで実装した例をご紹介
(1-1) (課題)「勾配降下法」が抱える課題
\( b^{(k+1)} = b^{k}+\eta \sum^{N}_{n=1} (t_n-y_n) \)
(1-2) (対策)確率的勾配降下法(SGD)とは?
\( b^{(k+1)} =b^{k} +\eta (t_n-y_n) \)
(1-3) (実装)Pythonで実装する際のポイント
############################################ # STEP5:学習 ############################################ for epoc in range(25): # バッチのデータ数だけ繰り返し for n1 in range(N): ############################################ # STEP3:最適化手法の定義(例:勾配降下法) ############################################ # Σ(t[n]-y[n])の計算 # (tn-yn)、(tn-yn)xnの変数 t_y = 0 t_y_x = tf.Variable(tf.zeros([M],tf.float64), dtype = tf.float64, shape=[M]) for n2 in range(N): # yの計算(モデルの出力) y = tf.nn.sigmoid(np.dot(X[n2],weight)+bias) # Σ(t[n]-y[n])の更新 t_y = t_y + (t[n2]-y[0]) # Σ(t[n]-y[n])xnの更新 t_y_x.assign_add(tf.math.scalar_mul((t[n2]-y[0]),X[n2])) # 重みwの勾配(∂E(w,b)/∂w)の計算 dweight.assign(tf.math.scalar_mul((1.0/N),t_y_x)) # バイアスbの勾配(∂E(w,b)/∂b)の計算 dbias.assign([(1.0/N)*t_y])
from sklearn.utils import shuffle ############################################ # STEP5:学習 ############################################ for epoc in range(25): # バッチのデータ数だけ繰り返し for n in range(N): # データをシャッフル X_,t_ = shuffle(X.numpy(),t.numpy()) xn = X_[n] ############################################ # STEP3:最適化手法の定義(例:勾配降下法) ############################################ # yの計算(モデルの出力) y = tf.nn.sigmoid(np.dot(xn,weight)+bias) # 重みwの勾配(∂E(w,b)/∂w)の計算 dweight = tf.math.scalar_mul((t_[n]-y[0]),xn) # バイアスbの勾配(∂E(w,b)/∂b)の計算 dbias.assign([t_[n]-y[0]])
(1-4) (実装例)サンプルプログラム
############################################ # ロジスティクス回帰 - 確率的勾配降下法(Scotastic Gradient Descent) ############################################ import numpy as np import tensorflow as tf import os os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' from sklearn.utils import shuffle # 入力xの次元 M = 2 # 入力データセットの数 N = 4 def or_gate(X_arg,t_arg): ############################################ # STEP1:モデルの定義 ############################################ # 入力の電気信号xの初期化 X = tf.constant(X_arg, dtype = tf.float64, shape=[N,M]) # 重みwの定義 ⇒[1行×M列] weight = tf.Variable(tf.zeros([M],tf.float64), dtype = tf.float64, shape=[M]) # バイアスbの定義 ⇒[1行] bias = tf.Variable([0], dtype = tf.float64, shape=[1]) # シグモイド関数:y = σ(wx + b)の定義 ⇒[1行] y = tf.Variable([0], dtype = tf.float64, shape=[1]) # 正解値tの定義([[0,1,1,1]) ⇒[n行×1列] t = tf.Variable(t_arg, dtype = tf.float64, shape=[N]) # 重みwの勾配(∂E(w,b)/∂w)の定義 dweight = tf.Variable(tf.zeros([M],tf.float64), dtype = tf.float64, shape=[M]) # バイアスbの勾配(∂E(w,b)/∂b)の定義 dbias = tf.Variable([0], dtype = tf.float64, shape=[1]) # 学習率ηの定義 eta = 0.1 # Epocの定義 epoc = 0 ############################################ # STEP4:セッションの初期化 ############################################ # ⇒今回は不要 # (TensorFlow v2以降はSessionを使用しないため) ############################################ # STEP5:学習 ############################################ for epoc in range(25): # バッチのデータ数だけ繰り返し for n in range(N): # データをシャッフル X_,t_ = shuffle(X.numpy(),t.numpy()) xn = X_[n] ############################################ # STEP2:誤差関数の定義 ############################################ # ⇒今回は不要 # (確率的勾配降下法の式を使うため、途中経過の誤差関数Eは計算不要) ############################################ # STEP3:最適化手法の定義(例:勾配降下法) ############################################ # yの計算(モデルの出力) y = tf.nn.sigmoid(np.dot(xn,weight)+bias) # 重みwの勾配(∂E(w,b)/∂w)の計算 dweight = tf.math.scalar_mul((t_[n]-y[0]),xn) # バイアスbの勾配(∂E(w,b)/∂b)の計算 dbias.assign([t_[n]-y[0]]) # 重みwの再計算 weight.assign_add(dweight) # バイアスbの再計算 bias.assign_add(dbias) # コンソール出力 decimals = 4 print("Epoc= ",epoc, "No. = ", n, "x1,x2 =", X[n].numpy(), "t =", '{:01}'.format(tf.convert_to_tensor(t_[n]).numpy()), "w1,w2 =", np.round(weight.numpy(),decimals), "theta =", np.round(bias.numpy(),decimals), "y =", '{:06.4f}'.format(tf.convert_to_tensor(y[0]).numpy()), "dw1,dw2 =",np.round(dweight.numpy(),decimals), "db =", np.round(dbias.numpy(),decimals)) def main(): # 初期値を設定し学習実行 X = [[0,0],[0,1],[1,0],[1,1]] t = [0,1,1,1] or_gate(X,t) if __name__ == "__main__": main()