Deep Learning - Simple Stochastic Gradient Descent Implementation

Deep Learning - Simple Stochastic Gradient Descent Implementation

LAVI
Simple Stochastic Gradient Descent Implementation

深度學習基礎實作
自行撰寫隨機梯度下降的線性回歸程式

先備知識

  • 權重 (或 )、偏差值 ,稱為參數(Parameters)
    • 演算法目的為找出適合訓練資料的模型參數,一般初始值應隨機給定較小值,不宜直接給定。
  • 學習率 ,稱為超參數(Hyperparameters),其目的為協助演算法找到適合模型的参數(即權重與偏差值)。
    • 學習率影響参數調整更新幅度的大小,其值一般為:,可直接給定,實驗中可嘗試不同值,體驗演算法收斂的速度。
  • 停止條件:
    • 給定最大世代(Epoch)數強迫停止,以免演算法不收斂時,造成無窮迴圈,無法停止。
    • 在多次世代(Epoch)迭代中,訓練沒有任何改進時終止,例如誤差度量在連續若干世代,停滯不再下降時。
    • 當觀察到過度擬合(Overfitting時),則停止訓練。
    • 當訓練資料集的某一誤差度量足夠小時停止,比如設定容忍誤差(Tolerance Error),,若因此條件而停止,可視為找到適合的模型。其他條件停止時,需要重新執行程式,取得新的權重與偏差值初始值,或調整學習率η,或給定較大世代數。
      • 常見誤差度量如下:
      • Mean Squared Error (MSE)
      • Root Mean Squared Error (RMSE)
      • Mean Absolute Error (MAE)

實驗一

  • 給定 Lab 1_train data1.txt 為訓練資料:
    • 共含 100
    • 第一個欄位為 ,為自變數(Independent Variable)
    • 第二個欄位為 ,為應變數 (Dependent Variable)
  • 作業要求:
    • 使用讀檔方式讀取訓練資料 (Lab 1_traindata1.txt)
    • 利用隨機梯度下降法,找回歸線 ŷ,即找權重 和偏差值
    • 一旦找到回歸線,就可以使用模型進行預測:
      • 時, 的預測值是多少?
      • 時, 的預測值是多少?
  • 輸出要求:
    • 輸出線性方程式 ŷ 的參數值
    • ,預測其對應估計值 ŷŷ
    • 畫圖(畫出直線 ŷ,及 2 筆測試資料點 ŷŷ

Solution Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import numpy as np
import matplotlib.pyplot as plt

# 讀取資料
data = np.loadtxt(fname="Lab1_traindata1.txt",
dtype=np.float64,
delimiter=None, # 因為默認就是用空白隔開
encoding="utf-8-sig") # (100 , 2)

# 資料切割
X = data[: , 0] # (100 , 1)
Y = data[: , 1] # (100 , 1)

# 初始化 w 和 b
# 這邊用的是 normal 常態分布
# 同學們可以試試看不同的初始化方法
w = np.random.normal(loc=0 , scale=1)
b = np.random.normal(loc=0 , scale=1)

# 設定超參數
max_epoch = 1000 # 最大世代數
learning_rate = 1e-6 # 學習率
tau = 1e-1 # 提前終止條件

for epoch in range(max_epoch):
for i in range(len(X)):

# 提取資料
x = np.array([X[i]]) # 因為 w 是 np.array,x 也要是相同型態
y = Y[i]

# 預測 ŷ = b + wx
y_predict = x * w + b # 因為 x 是一維所以才能這樣乘,否則要用 np.matmul

# 損失函數 = 0.5 * (y_predict - y) ** 2
# 計算梯度
w_gradient = (y_predict - y) * x.T # 雖然 x 是 (1 , 1) 但正確邏輯觀念是 x.T
b_gradient = y_predict - y

# 依照梯度反方向更新 w 和 b (梯度下降)
w -= learning_rate * w_gradient
b -= learning_rate * b_gradient

# 計算 mse: 1/n Σ(y - ŷ)²
Y_predict = X * w + b # (100 , 1) * (1 , 1)
mse = np.mean((Y_predict - Y) ** 2)

# 判斷是否提前終止
if mse < tau:
break

# 預測題目要求的兩筆資料
xa = 28.2
xb = 135.0

# ŷ = b + wx
ŷa = xa * w + b
ŷb = xb * w + b

# 題目輸出要求
print("-------------------------------------------")
print("深度學習 Lab1-1 輸出:")
print(f"w = {w.item():.5f}")
print(f"b = {b.item():.5f}")

print(f"當 x = {xa} , ŷ = {ŷa.item():.5f}")
print(f"當 x = {xb} , ŷ = {ŷb.item():.5f}")
print("------------------------------------------")

# plot 畫圖
plt.plot(xa, ŷa, 'o', color="salmon") # 畫點 xa 和 xb,圖形為 o
plt.plot(xb, ŷb, 'o', color="plum")

# 畫線性方程式,假設 100 個 x,套入 w 和 b 計算 ŷ
x_values = np.linspace(0, 150, 100) # 從 0 到 150 中間取 100 個點
y_values = x_values * w + b # 算出每個 x 的 ŷ
plt.plot(x_values, y_values, color="turquoise") # 畫出線性方程式

# 標題
plt.title("Deep Learning Lab1-1")

# x y 座標名稱
plt.xlabel("x value")
plt.ylabel("y value")

# 右下角標示顏色線的名稱
plt.legend([f"(xa, ŷa) = ({xa}, {ŷa.item():.1f})", f"(xb, ŷb) = ({xb}, {ŷb.item():.1f})", "ŷ = b + wx"], loc = "lower right")
# plt.show() 用來自己檢視圖片用

# 輸出成 output 檔案
plt.savefig('output.png')

實驗二

  • 給定 Lab 1_traindata2.csv 為籃球員訓練資料:
    • 共含 52
    • 1 - 4 欄位是 ,第 5 欄位是
    • 以下描述各欄位:
      • 高度(英尺)
      • 重量(磅)
      • 成功射籃的百分比(嘗試 100 次)
      • 成功罰球的百分比(嘗試 100 次)
      • 每場比賽的平均得分
  • 作業要求:
    • 使用讀檔方式讀取訓練資料 (Lab 1_traindata2.csv)
    • 利用梯度下降法,找到回歸超平面(Hyperplane) ŷ,即找權重 和偏差值
    • 一旦找到回歸超平面,就可以使用模型進行預測:
      • 時,預測值
      • 時,預測值
  • 輸出要求:
    • 輸出線性方程式 ŷ 的參數值
    • ,預測其對應估計值 ŷŷ

Solution Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import numpy as np
import matplotlib.pyplot as plt

# 讀取資料
data = np.loadtxt(fname="Lab1_traindata2.csv",
dtype=np.float64,
delimiter=",",
encoding="utf-8-sig") # (52 , 5)

# 資料切割
X = data[: , :-1] # (52 , 4)
Y = data[: , -1:] # (52 , 1)

# 初始化 w 和 b
# 這邊用的是 uniform 均勻分布
# 同學們可以試試看不同的初始化方法
w = np.random.uniform(low=-1. , high=1. , size=(4 , 1)) # (4 , 1)
b = np.random.uniform(low=-1. , high=1.)

# 設定超參數
max_epoch = 1000 # 最大世代數
learning_rate = 1e-6 # 學習率
tau = 1e-1 # 提前終止條件

for epoch in range(max_epoch):
for i in range(len(X)):

# 提取資料
x = X[i].reshape(1 , 4) # (1 , 4)
y = Y[i]

# 預測 ŷ = b + wx
y_predict = np.matmul(x , w) + b # (1 , 4) * (4 , 1)

# 損失函數 = 0.5 * (y_predict - y) ** 2
# 計算梯度
w_gradient = (y_predict - y) * x.T
b_gradient = y_predict - y

# 依照梯度反方向更新 w 和 b (梯度下降)
w -= learning_rate * w_gradient
b -= learning_rate * b_gradient

# 計算 mse: 1/n Σ(y - ŷ)²
Y_predict = np.matmul(X , w) + b # (52 , 4) * (4 , 1)
mse = np.mean((Y_predict - Y) ** 2)

# 判斷是否提前終止
if mse < tau:
break


# 預測題目要求的兩筆資料
xa = np.array([[6.8 , 210 , 0.402 , 0.739]])
xb = np.array([[6.1 , 180 , 0.415 , 0.713]])

# ŷ = b + wx
ŷa = np.matmul(xa , w) + b # (1 , 4) * (4 , 1)
ŷb = np.matmul(xb , w) + b # (1 , 4) * (4 , 1)


# 題目輸出要求
print("-------------------------------------------")
print("深度學習 Lab1-2 輸出:")
print(f"w = {w}")
print(f"b = {b}")

print(f"當 x = {xa.reshape(-1)} , ŷ = {ŷa.item():.5f}")
print(f"當 x = {xb.reshape(-1)} , ŷ = {ŷb.item():.5f}")
print("------------------------------------------")

Reference

  • 黃貞瑛老師的深度學習課程
  • 吳建中同學的共同討論
On this page
Deep Learning - Simple Stochastic Gradient Descent Implementation