1. 程式人生 > >機器學習筆記——線性迴歸(Linear Regression)

機器學習筆記——線性迴歸(Linear Regression)

線性迴歸演算法


1 簡單線性迴歸(Simple Liner Regression)

  • 解決迴歸問題
  • 思想簡答,容易實現
  • 許多強大的非線性模型的基礎
  • 結果具有很好的可解釋性
  • 蘊含機器學習中的很多重要思想

1.1 什麼是線性迴歸演算法?

房價預測模型
一個簡單的例子就是房屋的面積與房子的價格,通過對樣本點的學習從而找到一條最大程度擬合所有樣本點的直線 y = a

x + b y=ax+b 從而每次獲得一個新的樣本帶入模型即可給出預測的 y y 值,像這樣的特徵值只有一個的我們稱之為簡單線性迴歸,特徵值有多個的我們稱之為多元線性迴歸。

1.2 如何尋找“最大程度”擬合的這條直線呢?

假設我們已經找到了最佳擬合的直線方程: y = a x + b y=ax+b

b 則對於每一個樣本點 x ( i ) x^{(i)} 根據我們的線性方程,則可計算出預測值為 y ^ ( i ) = a x ( i ) + b {\hat{y}}^{(i)}=ax^{(i)}+b 而我們希望真實值 y ( i ) y^{(i)} 與預測值 y ^ ( i ) {\hat{y}}^{(i)} 的差距儘量小,而如何來衡量這兩者的差距呢?最簡單的方式就是兩者作差 y ( i ) y ^ ( i ) y^{(i)}-{\hat{y}}^{(i)} ,然而這種方式計算出的差值有正有負,求和之後值可能為零,所以這種衡量方式並不可行。另一種方式即兩者作差的絕對值,即 y ( i ) y ^ ( i ) |y^{(i)}-{\hat{y}}^{(i)}| ,然而絕對值在某些地方並不可導,對後續的求導求最值有影響,所以也不考慮這種方式。最後一種,考慮所有的樣本 i = 1 n ( y ( i ) y ^ ( i ) ) 2 \sum_{i=1}^n {(y^{(i)}-{\hat{y}}^{(i)})^2} 這種衡量方式顯然符合要求。所以現在的目標就是使得目標函式 i = 1 n ( y ( i ) a x ( i ) b ) 2 \sum_{i=1}^n {(y^{(i)}-{ax^{(i)}-b})^2} 儘可能小,通過最優化這個損失函式以此獲得機器學習模型。這是一個典型的最小二乘法的問題,我們通過求解後得出的引數 a a b b
a = i = 1 m ( x ( i ) x ˉ ) ( y ( i ) y ˉ ) i = 1 m ( x ( i ) x ˉ ) 2 a = \frac{\sum_{i=1}^m{(x^{(i)}-\bar{x})(y^{(i)}-\bar{y})}} {\sum_{i=1}^m{(x^{(i)}-\bar{x})^2}}
b = y ˉ a x ˉ b = \bar{y} - a\bar{x}
由此我們即可確定最大程度擬合的這條直線。

1.3 簡單線性迴歸的實現

手動生成五個點 ( 1 , 1 ) , ( 2 , 3 ) , ( 3 , 2 ) , ( 4 , 3 ) , ( 5 , 5 ) (1,1),(2,3),(3,2),(4,3),(5,5) 求一條最佳直線來擬合這五個點

#SimpleLinearRegression.py
import numpy as np

class SimpleLinearRegression1:

    def __init__(self):
        """初始化Simple Linear Regression模型"""
        self.a_ = None
        self.b_ = None   
    def fit(self, x_train, y_train):
      """根據訓練資料集x_train, y_train訓練 SimpleLinearRegression模型"""
        assert x_train.ndim == 1,\
          "Simple Linear Regressor can only solve single feature training data."
        assert len(x_train) == len(y_train),\
          "the size of x_train must be equal to the size of y_train"
        x_mean = np.mean(x_train)
        y_mean = np.mean(y_train)

        num = 0.0
        d = 0.0    
        for x,y in zip(x_train, y_train):
            num += (x - x_mean) * (y - y_mean)
            d += (x - x_mean) ** 2    self.a_ = num/d
        self.b_ = y_mean - self.a_ * x_mean

        return self
    def predict(self, x_predict):
        """給定待預測資料集x_predict,返回x_predict的結果向量"""
        assert x_predict.ndim == 1,\
        "Simple Linear Regressor can only solve single feature training data."
        assert self.a_ is not None and self.b_ is not None,\
        "must fit before predict!"
        return np.array([self._predict(x) for x in x_predict])
    def _predict(self, x_single):
        """給定單個待預測資料x_single,返回x_single的預測結果"""
        return self.a_ * x_single + self.b_
    def __repr__(self):
        return "SimpleLinearRegression1()"
*****************************************************************************
#test.py
import numpy as np
from SimpleLinearRegression import SimpleLinearRegression1
import matplotlib.pyplot as plt

x = np.array([1.,2.,3.,4.,5.])
y = np.array([1.,3.,2.,3.,5.])

x_predict = 6 reg1= SimpleLinearRegression1()
reg1.fit(x, y)

y_predict = reg1.predict(np.array([x_predict]))
print(y_predict)

y_hat = reg1.a_ * x + reg1.b_

plt.scatter(x, y)
plt.plot(x, y_hat, color = 'r')
plt.axis([0,6,0,6])
plt.show()

執行結果:
[5.2]

1.4 向量化

在1.3中我們在計 a = i = 1 m ( x ( i ) x ˉ ) ( y ( i ) y ˉ ) i = 1 m ( x ( i ) x ˉ ) 2 a = \frac{\sum_{i=1}^m{(x^{(i)}-\bar{x})(y^{(i)}-\bar{y})}} {\sum_{i=1}^m{(x^{(i)}-\bar{x})^2}}