線性迴歸算法(一)

參考資料

  • 慕課網《Python3 入門機器學習》

文章目錄

接下來將分爲3篇文章完成線性迴歸算法的相關內容,這是3個文章的整體大綱。python

1. 簡單線性迴歸

拿波士頓的房價爲例,如今有這麼一張圖,x軸是房子的面積,y軸是房子的價格,咱們假設房子面積和房屋價格之間呈現線性關係,那麼咱們就能夠經過線性迴歸算法對房價進行預測。算法

注意: 這裏的圖跟以前的KNN算法之間的圖是不同的。機器學習

咱們中學學過都知道,一條直線能夠表示成:y = ax +b 的形式。函數

線性迴歸算法就是假設有一條直線能夠儘量地擬合咱們的數據,從而經過這麼一條直線來進行預測。性能

如今假設咱們找到了最佳擬合的直線方程:學習

y = ax+ b測試

則對於每個樣本點x^{i}優化

根據咱們的直線方程,預測值爲: spa

真值爲:y^{(i)}.net

那麼此時,若是此時這條方程是最佳擬合方程,那麼:

必然是最小的。

可是咱們通常不採用絕對值的方式,而是採用平方的方式,因此咱們上面的公式能夠寫成:

拿咱們如今 目標,就是使得:

儘量地小。

又由於

因此,如今,線性迴歸法的目標就是,找到a和b使得

儘量地小。

到這裏咱們能夠總結一下學習算法的基本思路,就是最優化原理,本質都是經過找到某些參數,讓這個損失(其實就是偏差)儘量的小,儘量的擬合全部數據點。

對於這類思想,有一門專門的學科,叫「最優化原理」,還有另一種方法,叫「凸原理」。但願深耕的朋友能夠了解一下。

在求解a和b的以前,咱們要了解一下最小二乘法。

1.1 最小二乘法

如今咱們要求一個函數的最小值,其實就是這個這個函數的極值。學太高數的朋友都知道, 求函數極值最簡單的方法就是對函數中的各個變量進行求導,導數爲0的地方就是極值的地方

敲黑板,敲黑板,這是推導的核心。

so,如今咱們把

簡寫成 \jmath (a,b)

,對它求極值也就是:

好了,先對b求導:

第一步:求導

第二步:整理出b

第三步 : 求出b

求出b後,咱們接下來對a求導:

如今要整理一下這個式子,讓a能夠單獨提取出來:

以後提取出a:

整理後就獲得a的表達式:

a求解出來了,可是不夠簡單,如今咱們要對它再進行變形。

有了這個結論後,咱們就能夠對式子進行變形:

最終咱們獲得了稍微好看一點的a了:

最終a和b的方程以下:

1.2 簡單線性迴歸的實現

接下來,要用代碼實現一下簡單線性迴歸算法。

這裏定義成SimpleLinearRegression1是有緣由的,由於後面會進行優化這個算法~這個只是第一版。

class SimpleLinearRegression1:

    def __init(self):
        self.a_ = None
        self.b_ = None

    def fit(self,x_train,y_train):
        assert x_train.ndim == 1, "Simple Linear Regressor can only solve single 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_i, y_i in zip(x_train, y_train):
            num += (x_i - x_mean) * (y_i - y_mean)
            d += (x_i - x_mean) ** 2

        self.a_ = num / d
        self.b_ = y_mean - self.a_ * x_mean

        return self

    def predict(self,x_predict):
        assert x_predict.ndim == 1,\
        "Simple Linear Regressor can only solve single feature 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):
        return self.a_ * x_single + self.b_
複製代碼

只要你把上面看懂了,這個代碼沒什麼難度。 如今咱們測試一下:

  1. 先假造一下測試數據集:

  1. 調用咱們寫好的算法進行建模和預測

1.3 向量化

因爲採用for循環效率是比較低的,因此咱們要把for循環轉成採用向量的計算。

能夠當作是下面的向量相乘:

而咱們知道,若是把w和v兩個向量定義成下圖中的樣子:

那麼此時,公式能夠轉化成:

這樣咱們就可使用numpy中的向量操做了。

如今咱們也明白了,以前爲何必定要把a簡化成這種形式,由於這種形式方便轉化成向量。

1.4 向量化算法實現

接下來咱們改造一下以前採用for循環寫的線性迴歸算法:

只要把for循環變成乘就能夠了。

1.5 性能測試

接下來,咱們進行兩個線性迴歸算法的性能測試。

對於一個10萬的計算量,採用for循環的每一次計算耗時1.1s,而向量才20ms。差距很大。


下一篇,將完成迴歸算法衡量指標相關內容,加油~

前路漫漫

相關文章
相關標籤/搜索