線性迴歸算法

本文參考公共號《數據科學家聯盟》餅乾文章。html

 

1、簡單線性迴歸:簡單線性迴歸及最小二乘法的數據推導python

        所謂簡單,是指只有一個樣本特徵,即只有一個自變量;所謂線性,是指方程是線性的;所謂迴歸,是指用方程來模擬變量之間是如何關聯的。 簡單線性迴歸,其思想簡單,實現容易(與其背後強大的數學性質相關。同時也是許多強大的非線性模型(多項式迴歸、邏輯迴歸、SVM)的基礎。而且其結果具備很好的可解釋性。算法

一、推導思路:機器學習

找到一組參數,使得真實值與預測值之間的差距儘量地小,是一種典型的機器學習算法的推導思路函數

咱們所謂的建模過程,其實就是找到一個模型,最大程度的擬合咱們的數據。 在簡單線迴歸問題中,模型就是咱們的直線方程:y = ax + b 。 要想最大的擬合數據,本質上就是找到沒有擬合的部分,也就是損失的部分儘可能小,就是損失函數(loss function)(也有算法是衡量擬合的程度,稱函數爲效用函數(utility function))_auto_0學習

所以,推導思路爲: 1.經過分析問題,肯定問題的損失函數或者效用函數; 2.而後經過最優化損失函數或者效用函數,得到機器學習的模型 近乎全部參數學習算法都是這樣的套路,區別是模型不一樣,創建的目標函數不一樣,優化的方式也不一樣。 回到簡單線性迴歸問題,目標:測試

已知訓練數據樣本X、y ,找到a和b的值,使_auto_1儘量小大數據

這是一個典型的最小二乘法問題(最小化偏差的平方) 經過最小二乘法能夠求出a、b的表達式:_auto_2優化

二、最小二乘法

2.1 損失函數

在機器學習中,全部的算法模型其實都依賴於最小化或最大化某一個函數,咱們稱之爲「目標函數」。 最小化的這組函數被稱爲「損失函數」。什麼是損失函數呢?spa

損失函數描述了單個樣本預測值和真實值之間偏差的程度。用來度量模型一次預測的好壞。

 

損失函數是衡量預測模型預測指望結果表現的指標。損失函數越小,模型的魯棒性越好。。 經常使用損失函數有:

  • 0-1損失函數:用來表述分類問題,當預測分類錯誤時,損失函數值爲1,正確爲0_auto_0

  • 平方損失函數:用來描述迴歸問題,用來表示連續性變量,爲預測值與真實值差值的平方。(偏差值越大、懲罰力度越強,也就是對差值敏感)_auto_1

  • 絕對損失函數:用在迴歸模型,用距離的絕對值來衡量_auto_2

  • 對數損失函數:是預測值Y和條件機率之間的衡量。事實上,該損失函數用到了極大似然估計的思想。P(Y|X)通俗的解釋就是:在當前模型的基礎上,對於樣本X,其預測值爲Y,也就是預測正確的機率。因爲機率之間的同時知足須要使用乘法,爲了將其轉化爲加法,咱們將其取對數。最後因爲是損失函數,因此預測正確的機率越高,其損失值應該是越小,所以再加個負號取個反。_auto_3

以上損失函數是針對於單個樣本的,可是一個訓練數據集中存在N個樣本,N個樣本給出N個損失,如何進行選擇呢? 這就引出了風險函數。

2.2 指望風險

指望風險是損失函數的指望,用來表達理論上模型f(X)關於聯合分佈P(X,Y)的平均意義下的損失。又叫指望損失/風險函數。_auto_0

2.3 經驗風險

模型f(X)關於訓練數據集的平均損失,稱爲經驗風險或經驗損失。 其公式含義爲:模型關於訓練集的平均損失(每一個樣本的損失加起來,而後平均一下)_auto_1

經驗風險最小的模型爲最優模型。在訓練集上最小經驗風險最小,也就意味着預測值和真實值儘量接近,模型的效果越好。公式含義爲取訓練樣本集中對數損失函數平均值的最小。_auto_2

2.4 經驗風險最小化和結構風險最小化

指望風險是模型關於聯合分佈的指望損失,經驗風險是模型關於訓練樣本數據集的平均損失。根據大數定律,當樣本容量N趨於無窮時,經驗風險趨於指望風險。 所以很天然地想到用經驗風險去估計指望風險。可是因爲訓練樣本個數有限,可能會出現過分擬合的問題,即決策函數對於訓練集幾乎所有擬合,可是對於測試集擬合效果過差。所以須要對其進行矯正:

  • 結構風險最小化:當樣本容量不大的時候,經驗風險最小化容易產生「過擬合」的問題,爲了「減緩」過擬合問題,提出告終構風險最小理論。結構風險最小化爲經驗風險與複雜度同時較小。_auto_3

經過公式能夠看出,結構風險:在經驗風險上加上一個正則化項(regularizer),或者叫作罰項(penalty) 。正則化項是J(f)是函數的複雜度再乘一個權重係數(用以權衡經驗風險和複雜度)

2.5最小二乘法

 

_auto_0

那麼爲了求出這個二次函數的最小值,對其進行求導,導數爲0的時候取得最小值:_auto_1

進而:_auto_2

正好是算數平均數(算數平均數是最小二乘法的特例)。 這就是最小二乘法,所謂「二乘」就是平方的意思。 (高斯證實過:若是偏差的分佈是正態分佈,那麼最小二乘法獲得的就是最有可能的值。)

 

2、簡單線性迴歸實現及向量化應用

python手動實現

import numpy as np

class SimpleLinearRegression:
    def __init__(self):
        """模型初始化函數"""
        self.a_ = None
        self.b_ = None

    def fit(self, x_train, y_train):
        """根據訓練數據集x_train,y_train訓練模型"""
        assert x_train.ndim ==1
        '''簡單線性迴歸模型僅可以處理一維特徵向量'''
        assert len(x_train) == len(y_train)
        '''特徵向量的長度和標籤的長度相同'''
        x_mean = np.mean(x_train)
        y_mean = np.mean(y_train)
        num = (x_train - x_mean).dot(y_train - y_mean)  # 分子
        d = (x_train - x_mean).dot(x_train - x_mean)    # 分母
        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
        '''簡單線性迴歸模型僅可以處理一維特徵向量'''
        assert self.a_ is not None and self.b_ is not None
        '''先訓練以後才能預測'''
        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 "SimpleLinearRegression()"

向量化運算:

向量w和向量v,每一個向量的對應項,相乘再相加。其實這就是兩個向量「點乘」

這樣咱們就可使用numpy中的dot運算,很是快速地進行向量化運算。

總的來講:向量化是很是經常使用的加速計算的方式,特別適合深度學習等須要訓練大數據的領域。

對於 y = wx + b, 若 w, x都是向量,那麼,能夠用兩種方式來計算,第一是for循環:

y = 0
for i in range(n):
    y += w[i]*x[i]
    y += b

向量化

y = np.dot(w,x) + b

對於獨立的樣本,用for循環串行計算的效率遠遠低於向量化後,用矩陣方式並行計算的效率。所以: 只要有其餘可能,就不要使用顯示for循環。

3、多元線性迴歸:多選線性迴歸和正規方程解及實現

1.經過分析問題,肯定問題的損失函數或者效用函數;

2.而後經過最優化損失函數或者效用函數,得到機器學習的模型。而後咱們推導並實現了最小二乘法,而後實現了簡單線性迴歸。最後還以簡單線性迴歸爲例,學習了線性迴歸的評價指標:均方偏差MSE、均方根偏差RMSE、平均絕對MAE以及R方。

可是,在真實世界中,一個樣本一般有不少(甚至成千上萬)特徵值的,這就是多元線性迴歸。本篇內容咱們學習多元線性迴歸並實現。

 

對於下面的樣本數據集_auto_0

對應的是一個向量,每一行是一個樣本,每列對應一個特徵。對應的結果能夠用以下以下公式:_auto_1

簡單線性迴歸,只計算前兩項,可是在多元線性迴歸中就要學習到n+1個參數,就能求出多元線性迴歸預測值:_auto_2

也就是:第一個特徵與參數1相乘、第二個特徵與參數2相乘,累加以後再加上截距。就能獲得預測值。 求解思路也與簡單線性迴歸很是一致,目標一樣是:

已知訓練數據樣本X、y ,找到_auto_3

,使_auto_4

儘量小.

 

其中_auto_0

是列向量列向量,並且咱們注意到,能夠虛構第0個特徵X0,另其恆等於1,推導時結構更整齊,也更加方便:_auto_1

這樣咱們就能夠改寫成向量點乘的形式:_auto_2

此時,咱們能夠得出:_auto_3

所以咱們能夠把目標寫成向量化的形式:

已知訓練數據樣本X、y ,_auto_4

推導出能夠獲得多元線性迴歸的正規方程解_auto_5

固然了,具體的推導過程不須要了解的,不影響咱們的使用,咱們只要知道結果思想就行,結果也不用背下來,在網上搜一下就能找到。

可是這種樸素的計算方法,缺點是時間複雜度較高:O(n^3),在特徵比較多的時候,計算量很大。優勢是不須要對數據進行歸一化處理,原始數據進行計算參數,不存在量綱的問題(多選線性不必作歸一化處理)。

python代碼實現多元線性迴歸:

import numpy as np
from sklearn.metrics import r2_score

class LinearRegression:

    def __init__(self):
        """初始化Linear Regression模型"""
        self.coef_ = None    # 係數(theta0~1 向量)
        self.interception_ = None   # 截距(theta0 數)
        self._theta = None  # 總體計算出的向量theta

    def fit_normal(self, X_train, y_train):
        """根據訓練數據X_train,y_train訓練Linear Regression模型"""
        assert X_train.shape[0] == y_train.shape[0]
        '''the size of X_train must be equal to the size of y_train'''
        # 正規化方程求解
        X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
        self._theta = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y_train)

        self.interception_ = self._theta[0]
        self.coef_ = self._theta[1:]
        return self

    def predict(self, X_predict):
        """給定待預測的數據集X_predict,返回表示X_predict的結果向量"""
        assert self.interception_ is not None and self.coef_ is not None
        '''must fit before predict'''
        assert X_predict.shape[1] == len(self.coef_)
        '''the feature number of X_predict must be equal to X_train'''
        X_b = np.hstack([np.ones((len(X_predict), 1)), X_predict])
        y_predict = X_b.dot(self._theta)
        return y_predict

    def score(self, X_test, y_test):
        """很倔測試機X_test和y_test肯定當前模型的準確率"""
        y_predict = self.predict( X_test)
        return r2_score(y_test, y_predict)
    

    def __repr__(self):
        return "LinearRegression()"
相關文章
相關標籤/搜索