Linear Regression

Linear Regression

แสดงความสัมพันธ์ระหว่างตัแปรด้วย linear function

\( \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)\)


สมการที่ (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




ความคิดเห็น