Linear Regression
\( \large h_{\theta}(x) = \theta_0 + \theta_{1}x_{1}+ \theta_{2}x_{2}+ \theta_{3}x_{3}...+ \theta_{k}x_{k} \)
เรียก \( \large \theta \) ว่าเป็น parameter หรือ weight ที่ใช้ map ระหว่าง X และ Y
ในรูปแบบการเขียนแบบทั่วไป จะทำการเพิ่ม \( \large x_0 = 1\) เรียกว่า "intercept term" เข้ามา
\( \large h_{\theta}(x) = \theta_{0}x_{0} + \theta_{1}x_{1}+ \theta_{2}x_{2}+ \theta_{3}x_{3}+...+ \theta_{k}x_{k} \)
\( \large h_{\theta}(x) = \sum_{i=1}^{n}\theta_{i}x_{i} = \theta^T \cdot X \)
โดยที่สมการล่าสุดจะมอง \( \theta ,X \) เป็น Vector และ n คือจำนวนของ input variable ที่ไม่นับ \( x_0\)
หลังจากกำหนด hypothesis function แล้ว ต่อไปคือขั้นการ train สมการด้วย data set ที่ได้จากการสังเกตุ เป้าหมายของการ train คือเพื่อให้ได้ชุดของ \( \large \theta \) ที่นำมาใช้หาของ \(\large h(x) \) ที่ใกล้เคียงกับค่า Response variable (y) ที่ได้จากการสังเกตุมากที่สุด เพื่อให้สามารถตรวจสอบได้ว่าค่าของ \( \large h(x) \) ใกล้เคียงกับ y แค่ไหน เราจึงการกำหนด cost function ขึ้นมา
Cost function
คือฟังก์ชั่นที่แสดงให้เราเห็นว่าค่าประมาณการมีความใกล้เคียงกับค่าสังเกตุเพียงใด หรือกล่าวอีกนัยว่าสมการ Regression ที่หาได้นั้นมีประสิทธิมากน้อยเพียงใด นิยามโดย
\( \large J(\theta) = \frac{1}{2}\sum_{i=1}^{N}(h_{\theta}(x^{(i)}) - y^{(i)})^2\) หรือ
\( \large J(\theta) = \frac{1}{2}\sum_{i=1}^{N}(\theta^Tx^{(i)} - y^{(i)})^2\)
ตัวแบบที่ดีควรมีค่าของ Cost function น้อยที่สุด นั้นคือเราต้องหาชุด \( \large \theta\) ที่ทำให้ const function มีค่าน้อยที่สุด และ algorithm ที่นิยมใช้กันคือการใช้ Gradient descent
Gradient descent เปรียบได้กับการเดินลงเขาเพื่อไปหาจุดที่ต่ำที่สุด ด้วยการก้าวเล็กๆทีละก้าว |
\(\large \triangledown_{\theta}J(\theta) =
\begin{bmatrix}
\frac{\partial{J(\theta)}}{\partial\theta1} \\
\frac{\partial{J(\theta)}}{\partial\theta2} \\
\frac{\partial{J(\theta)}}{\partial\theta3} \\
.\\
.\\
.\\
\frac{\partial{J(\theta)}}{\partial\theta_{n}} \\
\end{bmatrix}
\)
เริ่มที่กำหนดค่าของ \( \large \theta \) ขึ้นมาแบบสุ่มก่อน แทนค่าเข้าไปใน hypothesis function เพื่อดูค่า cost function ทำเช่นนี้ไปเรื่อย ๆ จนพบว่า ไม่สามารถทำให้ค่า cost function ต่ำไปกว่านี้ได้อีก
ดังนั้น Gradient จึงเป็นการใช้หลักการของ Derivative function ระหว่าง \( \large J(\theta)\) กับ \( \large \theta \) และการวนรอบเพื่อหาค่าที่เหมาะสม
\(\large \theta_{j} \equiv \theta_{j} - \alpha \frac{\partial J(\theta)}{\partial \theta} \dashrightarrow(1) \)
โดยกำหนดให้ \( \large \alpha \) คือ Learning rate เปรียบได้กับขนาดของก้าว ค่านี้ควรมีค่าไม่มากเกินไปหรือน้อยเกินไป (มากเกินไปอาจทำให้ก้าวข้ามจุดที่ต่ำที่สุดได้ เล็กเกินไปจะใช้เวลาประมวลผลนาน)
\(\large \frac{\partial{J(\theta)}}{\partial{\theta_j}} = \frac{\partial {\frac{1}{2}(h_{\theta}(x) - y)^2 }}{\partial \theta_{j}} \)
\(\large \frac{\partial{J(\theta)}}{\partial{\theta_j}} = \frac{1}{2}\times 2 (h_{\theta}(x)-y)\frac{\partial {(h_{\theta}(x) - y) }}{\partial \theta_{j}} \)
\(\large \frac{\partial{J(\theta)}}{\partial{\theta_j}} = (h_{\theta}(x)-y)\frac{\partial {(\sum_{i=0}^{n}\theta_i x_i - y) }}{\partial \theta_{j}} \)
\(\large \frac{\partial{J(\theta)}}{\partial{\theta_j}} = (h_{\theta}(x)-y)x_j \dashrightarrow(2)\)
\(\large \frac{\partial{J(\theta)}}{\partial{\theta_j}} = \frac{1}{2}\times 2 (h_{\theta}(x)-y)\frac{\partial {(h_{\theta}(x) - y) }}{\partial \theta_{j}} \)
\(\large \frac{\partial{J(\theta)}}{\partial{\theta_j}} = (h_{\theta}(x)-y)\frac{\partial {(\sum_{i=0}^{n}\theta_i x_i - y) }}{\partial \theta_{j}} \)
\(\large \frac{\partial{J(\theta)}}{\partial{\theta_j}} = (h_{\theta}(x)-y)x_j \dashrightarrow(2)\)
สมการที่ (2) เป็นตัวแทนของ Gradient descent ของ Cost function สำหรับ Linear regression เมื่อนำไปแทนค่าใน (1) จะได้
\(\large \theta_j \equiv \theta_j+\alpha(y^{(i)} - h_{\theta}(x^{(i)}))x^{(i)}_{j} \dashrightarrow(3) \)
เรียกสมการ (3) "update rule" ที่ใช้หลักการ Least Mean Square (LMS) หรืออาจใช้ชื่อว่า "Widrow-Hoff learning rule"
อาจเรียก \(\large y^{(i)} - h_{\theta}(x^{(i)}) \) ว่าเป็น "Error" ก็ได้ เพราะมันคือความต่างระหว่างค่าที่ได้จากการสังเกตุกับค่าที่ได้จากการคำนวณจาก Regression
import numpy as np
class LinearReg():
def __init__(self):
self._iter = 1000
self._lr = 0.1
self._beta = None
@property
def iteration(self):
return self._iter
@property
def learning_rate(self):
return self._lr
@property
def beta(self):
return self._beta
@iteration.setter
def iteration(self,i):
self._iter = i
@learning_rate.setter
def learning_rate(self,lr):
self._lr = lr
@beta.setter
def beta(self,b):
self._beta = b
def fit(self,X,Y):
X = np.insert(X,0,1,axis=1) # inject X0 into input vector with value 1
_beta = np.zeros(X.shape[1]) # create beta vector
for i in range(self.iteration):
for x,y in zip(X,Y):
output = x.dot(_beta)
_error = y - output
_beta = _beta + self.learning_rate * _error * x
self.beta = _beta
def predict(self,X):
if self.beta is not None :
X = np.insert(X,0,1,axis=1)
res= X.dot(self.beta)
return res.reshape((X.shape[0],1))
else :
return None
def r2(self,X,Y):
'''
r2 is defined by 1-u/v
where
u = sum of (observ - predict)^2
v = sum of (observ - mean of observ)^2
'''
u = np.sum(np.power(Y - self.predict(X) ,2))
v = np.sum(np.power(Y - Y.mean(),2))
return 1 - u/v
if __name__ == "__main__":
X = np.array([[1],[2],[3],[4],[5]])
Y = np.array([[1],[2],[3],[4],[5]])
lr = LinearReg()
lr.iteration = 1000
lr.fit(X,Y)
print(lr.beta)
print(lr.predict(np.array([[7],[8],[100]])))
print(lr.r2(X,Y))
[1] https://en.wikipedia.org/wiki/Linear_least_squares#Derivation_of_the_normal_equations
[2] http://mathworld.wolfram.com/NormalEquation.html
[3] https://en.wikipedia.org/wiki/Ordinary_least_squares
[4] https://somchaisom.blogspot.com/2018/07/basic-linear-algebra-1.html
ความคิดเห็น
แสดงความคิดเห็น