Stochastic Gradient Descent

CrossKnight
5 min readSep 2, 2020

--

http://www.its.caltech.edu/~nazizanr/papers/SMD.html

Stochastic Gradient Descent (SGD) เป็นวิธีการหลักในการ Train Neural Network Model โดยใช้ Gradient หรือ ความชัน เป็นตัวบอกขนาดและทิศทางในการปรับ Parameters ที่จะทำให้ Loss Value เคลื่อนที่ไปยัง จุดต่ำสุดของพื้นผิว (Minima) การทำความเข้าใจแนวคิดของ SGD จึงเป็นสิ่งสำคัญในการที่จะทำให้สามารถปรับจูน Neural Network โดยเฉพาะ Deep Learning Model ให้มีประสิทธิภาพมากยิ่งขึ้น

โดยในบทนี้ได้ทำความเข้าใจพฤติกรรมการเคลื่อนที่ของ Loss Value ในแต่ละรอบของการ Train Model แบบ Linear Regression โดยใช้ Tensorflow และ Keras Framework ซึ่งจะมีวิธีการ 2 แบบ ได้แก่

  1. Gradient Descent
  2. Stochastic Gradient Descent

Gradient Descent Method

Two Dimensional Parabola Graph

y=x²-2x+3

เพื่อให้เห็นภาพมากขึ้น ขอยกตัวอย่างกราฟพาราโบลา y=x²-2x+3 ซึ่งมีจุดต่ำสุดที่จุด x เท่ากับ 1 ดังภาพด้านบน จุดมุ่งหมายของ Gradient Descent Method คือการหาค่าของ x (Weight หรือ Bias) ที่ทำให้ y (Loss Value) มีค่าต่ำสุด โดยการปรับค่า x ให้ค่อยๆ เคลื่อนที่ไปตามทางลาด (Descending) ของพื้นผิวนั้นๆ

สมมติว่าหากผูกผ้าปิดตาแล้วนำไปวางไว้ที่จุด x เท่ากับ -4 การที่จะไปยังจุดต่ำสุดได้ เราต้องอาศัยสัมผัสของเท้าทั้ง 2 ข้างเพื่อประเมินว่าจะเดินไปทางซ้ายหรือทางขวา โดยในการประเมิน เราจะหาอนุพันธ์ของฟังก์ชัน y เทียบกับ x (หา Gradient)

ดังนั้นที่จุด x เท่ากับ -4 ความชันของกราฟพาราโบลาจะมีค่าเท่ากับ -10

Gradient = 2x-2
= (2)(-4)-(2)
= -10

ซึ่งเมื่อความชันเป็นลบ เราจึงรู้ได้ว่าพื้นผิวที่ยืนอยู่นั้น มีการลาดเอียงมาทางขวามือ เราจึงเดินไป 10 ก้าว ยังจุดที่ x เท่ากับ 6

Update x = x-(-10)
= (-4)-(-10)
= 6

อย่างไรก็ตามการเดินถึง 10 ก้าว ทำให้เราเคลื่อนที่ไปยังอีกฝั่งของหลุมที่ความชันเป็นบวก แทนที่จะค่อยๆ เดินลงหลุมไปยังจุดต่ำสุด ดังนั้นในการ Train Model จริง จึงต้องมีการ Update ค่า x ด้วยจำนวนก้าวที่ไม่มากนัก โดยการทำให้ Gradient มีขนาดเล็กลง ด้วยการคูณด้วย Learning Rate ที่มีค่าอยู่ระหว่าง 0–1 ตามสมการด้านล่าง

Learning_Rate = 0.01
Update x = x - Learning_Rate*Gradient
= (-4)-(0.01)(-10)
= -3.9

Linear Regression with Tensorflow

เริ่มต้นด้วยการ Implement Neural Network Model แบบ Linear Regression ด้วย Tensorflow Framework เพื่อศึกษาการเคลื่อนที่ของ Loss Value โดยใช้ Gradient Descent Method จาก Fish market ดังตัวอย่างตามขั้นตอนต่อไปนี้

Import Library

import tensorflow.compat.v1 as tf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as seabornInstance
from sklearn.model_selection import train_test_split
from sklearn import metrics
from tensorflow.python.keras.models import Sequential
from tensorflow.python.keras.layers import Dense
from keras import backend as K
import plotly
import plotly.graph_objs as go
import plotly.io as pio
pio.renderers.default = 'colab'
%matplotlib inline

กำหนด Random Seed และจำนวน Epoch ที่จะ Train

np.random.seed(seed=13)
EPOCH = 500

Load ไฟล์ Fish.csv ซึ่งพบว่ามีทั้งหมด 159 Row โดยจะนำข้อมูลใน Column Height มาทำเป็น Input Data หรือตัวแปรอิสระ (Predictor) และ Width มาทำเป็นผลเฉลย หรือตัวแปรตาม (Response)

Plot Heightและ Width เพื่อดูลักษณะของข้อมูล

ดูการกระจายตัวของ Height

แยก Dataset เป็น Input Data (x) และผลเฉลย (y)

X = dataset['Height'].values.reshape(-1,1)
y = dataset['Width'].values.reshape(-1,1)

สุ่มแบ่งข้อมูลเป็น 2 ชุด สำหรับ Train 80% และ Test 20%

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle= True)

นิยาม Model ด้วย Tensorflow โดยจะมีการนำ X_train เข้า Model ทั้งก้อนขนาด 127 Row

W = tf.Variable(tf.random.uniform([1], -1.0, 1.0))
b = tf.Variable(tf.random.uniform([1], -1.0, 1.0))

y = W * X_train + b

นิยาม Loss Function แบบ Mean Squared Error (MSE)

loss = tf.reduce_mean(tf.square(y - y_train))

กำหนด Optimizer และ Learning Rate

optimizer = tf.train.GradientDescentOptimizer(0.0001)
train = optimizer.minimize(loss)

โดย Optimizer จะมีการทำ Back-propagation Algorithm เพื่อปรับค่า Weight (W) และ Bias (b) ให้อัตโนมัติ

เคลียร์ Tensorflow Variable

init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)

Train Model

his=[]
wb = []

for step in range(EPOCH):
sess.run(train)
his.append(sess.run(loss))
print(step, sess.run(W), sess.run(b), sess.run(loss))
wb.append([sess.run(W)[0], sess.run(b)[0], sess.run(loss)])

ดึง Weight (W) และ Bias (b) มาสร้าง Linear Regression Model

M = sess.run(W)
C = sess.run(b)

นิยาม Function Predict

def predict(X, M, C):
y = M*X+C
return y[0]

แปลง Loss Value List เป็น DataFrame

df = pd.DataFrame(his, columns=['loss'])

Plot Loss

Predict Height

แสดงผลการ Predict 10 แถวแรก

Plot กราฟเปรียบเทียบผลการทำนายกับค่าจริง

แสดง Model ที่สร้างจากการ Train ใน Epoch ที่ 1

M = [i[0] for i in wb]
L = [i[2] for i in wb]
C = [i[1] for i in wb]

แสดง Model ที่สร้างจากการ Train ใน Epoch ที่ 5

แสดง Model ที่สร้างจากการ Train ใน Epoch ที่ 10

แสดง Model ที่สร้างจากการ Train ใน Epoch ที่ 500

ดู Loss Value เทียบกับค่า Weight

ดู Loss Value เทียบกับค่า Bias

ดู Loss Value เทียบกับค่า Weight และ Bias

จะเห็นว่าค่า Loss Value จะค่อยๆ เคลื่อนที่ไปยังจุดต่ำสุดของพื้นผิว (Minima) แบบ 3 มิติ ด้วย Learning Rate เท่ากับ 0.0001 ครับ

วัดประสิทธิภาพของ Model ด้วย Mean Absolute Error, Mean Squared Error และ Root Mean Squared Error

Stochastic Gradient Descent Method

Linear Regression with Keras

ต่อไปจะทดลอง Train Neural Network Model แบบ Linear Regression โดยใช้ Keras Framework ซึ่งในการ Train Model ด้วย Keras นั้นจะใช้เวลาค่อนข้างมาก การจะนำ Dataset เข้า Train Model เป็นก้อนใหญ่ๆ จึงไม่เหมาะสม

ดังนั้นเราจะใช้การสุ่มแบ่ง Dataset เป็นก้อนเล็กๆ ขนาด 64 Row (Batch Size เท่ากับ 64) เพื่อนำไป Train Model ซึ่งเราจะเรียก Gradient Descent แบบที่มีการสุ่มแบ่ง Dataset เป็นก้อนขนาดเล็กว่า Stochastic Gradient Descent

นิยาม Root Mean Squared Error

def rmse(y_true, y_pred):
return K.sqrt(K.mean(K.square(y_pred - y_true), axis=-1))

นิยาม Model

model = Sequential()
model.add(Dense(1, input_dim=1, kernel_initializer='random_uniform', activation='linear'))
model.summary()

Compile Model

model.compile(loss='mse', optimizer='adam', metrics=['mae', 'mse', rmse])

Train Model ด้วยการสุ่มแบ่งข้อมูลสำหรับ Train 80% และ Validate อีก 20% โดยกำหนด Batch Size เท่ากับ 64

history = model.fit(X_train, y_train, epochs=EPOCH, batch_size=64,  verbose=1, validation_split=0.2, shuffle=True)

Plot Loss และ Validate Loss

Predict

y_pred = model.predict(X_test)

แปลงเป็น DataFrame

y_pred = y_pred.flatten()

df = pd.DataFrame({'Actual': y_test, 'Predicted': y_pred})
df.head(10)

Plot กราฟเปรียบเทียบผลการทำนายกับค่าจริง

แสดง Model ที่สร้างจากการ Train 500 Epoch

วัดประสิทธิภาพของ Model ด้วย Mean Absolute Error, Mean Squared Error และ Root Mean Squared Error

Reference
https://blog.pjjop.org/introduction-to-stochastic-gradient-descent-with-tensorflow-and-keras

Colab
https://colab.research.google.com/drive/1lH0PLUIgjTPJkb5BkJ0_ZTTBEe50jATn?usp=sharing

บทความนี้เป็นส่วนหนึ่งของรายวิชา AI จัดทำขึ้นเพื่อทดลองทำ Lab ซึ่งหากมีข้อผิดพลาดใดๆ ขออภัยไว้ ณ ที่นี้

--

--