線性回歸算法集合

線性回歸算法

注:本文所有代碼和數(shù)據(jù)均在個人github下click me

回歸算法一般是針對預(yù)測是連續(xù)的情況下,對于預(yù)測值是離散的,采用的算法是分類算法。線性回歸算法包括很多種變形,這里提到的線性回歸算法是其中的幾種典型算法。在實際應(yīng)用中,我們采用線性算法可以預(yù)測商品的價格,預(yù)測房子的房價等等,雖然線性回歸算法比較簡單,但是在實際中還是有很多的使用的。

在機器學(xué)習(xí)中,我們要緊盯三件事情。第一,算法的損失函數(shù);第二,采用什么求值算法求損失函數(shù)的最小值;第三,算法的評價指標

一般線性回歸算法

一般的線性回歸又叫做最小二乘算法,最小二乘是因為算法的損失函數(shù)是最小二乘的,損失函數(shù)如下:
J(\theta)={\frac 12}\sum\limits_{i=1}^{m}(h_\theta(x^{(i)}) - y^{(i)})^2 \tag {1.1}
其中h_\theta(x^{(i)})是算法針對數(shù)據(jù)的預(yù)測值,而y^{(i)}是數(shù)據(jù)的真實值,m表示訓(xùn)練數(shù)據(jù)的條數(shù),而{\frac 12}是為了此公式求導(dǎo)方便而加入的。而\theta是算法的參數(shù),在這里就是線性回歸的權(quán)重值。通過此公式我們可以得到,線性回歸算法的損失函數(shù)就是針對每個樣本計算預(yù)測值和真實值得差,然后將差求平方,之后將全體樣本的差平方相加即得到損失函數(shù)。
針對損失函數(shù),我們有兩種算法可以求取損失函數(shù)的最小值。

梯度下降算法

梯度下降算法的一般形式:
\theta_j: = \theta_j - \alpha{\frac \partial {\partial\theta_j}}J(\theta) \tag {1.2}
這里寫的是梯度下降算法的標量形式。這個公式描述了梯度下降算法是如何更新算法的參數(shù)的,其中\alpha是參數(shù)的更新步長??梢钥吹竭@里的關(guān)鍵是如何求取損失函數(shù)關(guān)于參數(shù)j的偏導(dǎo)數(shù)。
將損失函數(shù)帶入到梯度下降算法,即公式(1.2)中,并且求導(dǎo),可以得到下式:
\theta_j:= \theta_j + \alpha{\sum_{i=1}^m (y^{(i)} - h_\theta(x^{(i)}))x_j^{(i)}} \tag {1.3}
我們重復(fù)的使用公式(1.3)直到達到收斂條件,即可以求得線性回歸算法中的參數(shù)值。
從公式中,可以看到用真實值和預(yù)測值之間的差值來更新參數(shù)值,這種方式或者思想在很多的機器學(xué)習(xí)算法中可以看到,包括深度學(xué)習(xí)的后向傳播算法。同時,可以看到每一次的迭代都要使用整個數(shù)據(jù)集。這種方式叫做批量梯度下降算法。還有一種方式可以求取\theta值,叫做隨機梯度下降算法,算法如下:

隨機梯度下降

從中我們可以看到,隨機梯度下降算法每次采用一個訓(xùn)練樣本取更新所有的參數(shù)值,注意那里的(for every j)。當訓(xùn)練樣本很多時,相比于批量梯度下降算法,隨機梯度下降算法能夠更快的更新算法的參數(shù)值,并且能夠更快的逼近損失函數(shù)的最小值。

代數(shù)解

我們將損失函數(shù)用向量表示,如下所示:
J(\theta) = {\frac 12}(X\theta - \vec{y})^T(X\theta - \vec{y}) \tag{1.4}
公式中的X表示訓(xùn)練數(shù)據(jù)的矩陣。因為損失函數(shù)是凸二次函數(shù),所以只有一個最小值,所以導(dǎo)數(shù)為0的點就是損失函數(shù)的最小值。
具體的推導(dǎo)過程如下(主要利用了矩陣的跡運算):

損失函數(shù)的導(dǎo)數(shù)

令導(dǎo)數(shù)等于0,從而得到:
\theta = (X^TX)^{(-1)}X^T\vec{y} \tag{1.5}

回歸模型的概率解釋

大家想過沒有,為什么在線性回歸模型里面選擇最小二乘作為損失函數(shù)?接下來從概率的角度來解釋選擇最小二乘作為損失函數(shù)的原因。
首先,假設(shè)目標變量和輸入數(shù)據(jù)存入如下的關(guān)系:
y^{(i)} = \theta^Tx^{(i)} + \epsilon^{(i)} \tag{1.6}
這里的\epsilon^{(i)}是誤差項,包括模型未考慮到影響目標變量的因素和隨機噪聲。
接下來假設(shè),誤差項相互獨立同分布,并且服從高斯分布(即正態(tài)分布)

為什么要假設(shè)誤差項服從高斯分布? 第一是因為采用高斯分布,在數(shù)學(xué)上處理會比較簡單;第二是因為根據(jù)中心極限定理,獨立的隨機變量的和,其總的影響接近高斯分布

誤差項的概率密度函數(shù)為:
p(\epsilon^{(i)}) = {\frac 1{\sqrt{2\pi}}}exp(-{\frac {(\epsilon^{(i)})^2} {2\sigma^2}}) \tag {1.7}
根據(jù)公式(1.6)和公式(1.7),我們可以得出如下結(jié)論:

概率分布

在公式中,\theta不是隨機變量,而是實際存在的值,雖然我們不知道真實值是多少。p(y^{(i)}|x^{(i)};\theta)的含義是給定x^{(i)},參數(shù)設(shè)定為\theta時,y^{(i)}的概率密度。注意公式中用的分號。
數(shù)據(jù)的概率是由p(\vec{y} | X;\theta)給出的,而總的概率可以看成是在固定\theta時,關(guān)于\vec{y}的函數(shù)。換個角度,我們想要將這個函數(shù)明確的看成是關(guān)于\theta的函數(shù),所以我們將其稱作似然函數(shù),從而我們得到關(guān)于\theta的似然函數(shù):

似然(likelihood)和概率(probability)實際上是一個東西,但是似然函數(shù)是對參數(shù)\theta定義的,為了加以區(qū)分,使用了似然這一術(shù)語。我們可以說參數(shù)的似然,數(shù)據(jù)的概率,但不能說數(shù)據(jù)的似然,參數(shù)的概率。

L(\theta) = L(\theta;X,\vec{y}) = p(\vec{y}|X;\theta)
極大似然估計就是選擇\theta,使參數(shù)的似然函數(shù)最大化,也就是選擇參數(shù)使得已有樣本的出現(xiàn)概率最大。
因為L(\theta)是嚴格單調(diào)遞增的,并且對數(shù)函數(shù)也是遞增的,所以取對數(shù),得到的\theta跟不取對象是一樣的。

似然函數(shù)

對數(shù)似然函數(shù)\mathcal {l}(\theta):

對數(shù)似然函數(shù)

最大化似然函數(shù),就是最大化對數(shù)似然函數(shù),即最小化
{\frac 12}{\sum\limits_{i=1}^{m}}(y^{(i)} - \theta^Tx^{(i)})^2
這個式子剛好是線性回歸算法中采用的損失函數(shù)??偨Y(jié)一下,最小二乘回歸模型剛好就是在假設(shè)了誤差獨立同服從正態(tài)分布后,得到的最大似然估計。同時注意到,正態(tài)分布中的方差\sigma^2的取值對模型并沒有影響。

編程實現(xiàn)

代數(shù)解實現(xiàn)線性回歸算法

def standard_regression(x_arr, y_arr):
    """
    這里直接采用代數(shù)解直接求取權(quán)重大小.這里有個條件是xTx的逆必須存在,
    如果不存在,則直接返回
    :param x_arr:
    :param y_arr:
    :return:
    """
    x_mat = np.mat(x_arr)
    y_mat = np.mat(y_arr).T
    xTx = x_mat.T * x_mat
    if np.linalg.det(xTx) == 0.0:
        print("矩陣是奇異的,逆不存在")
        return
    ws = xTx.I * (x_mat.T * y_mat)
    return ws

根據(jù)standard_regression函數(shù)可以直接求取算法的權(quán)重。然后根據(jù)權(quán)重就可以求得數(shù)據(jù)的預(yù)測結(jié)果,這里選擇的數(shù)據(jù)在點我
畫出的圖像如下:

線性回歸測試

直線為擬合直線,散點是真實值。

隨機梯度下降實現(xiàn)線性回歸

由于代碼篇幅比較長,所以可以直接上我的github上面看。代碼

局部加權(quán)線性回歸算法

局部加權(quán)線性回歸

每個點都對應(yīng)一個不同的\theta,利用\theta計算預(yù)測值。
下面我們用剛才介紹的局部加權(quán)線性回歸來擬合一下這個模型,簡單回顧一下過程:
1.用高斯核函數(shù)計算出第i個樣本處,其它所有樣本點的權(quán)重W
2.用權(quán)重w對第i個樣本作加權(quán)線性回歸,得到回歸方程,即擬合的直線方程
3.用剛才得到的經(jīng)驗回歸直線計算出x^i處的估計值y^i
4.重復(fù)一至三步,得到每個樣本點的估計值

同時,從計算公式中,可以看到對于每個點的預(yù)測值,需要利用所有的數(shù)據(jù)樣本進行計算。如果數(shù)據(jù)量比較大,計算量就會是一個大問題。
相比于上面提到線性回歸算法(參數(shù)算法),局部加權(quán)線性回歸算法是非參數(shù)算法。

參數(shù)算法vs非參數(shù)算法

引用地址

參數(shù)算法:
如果我們對所要學(xué)習(xí)的問題有足夠的認識,具備一定的先驗知識,此時我們一般會假定要學(xué)習(xí)的目標函數(shù)f(x)或分布P(y|x)的具體形式。然后,通過訓(xùn)練數(shù)據(jù)集,基于ERM、SRM、MLE、MAP等學(xué)習(xí)策略,可以估計出f(x)或P(y|x)中含有的未知參數(shù)。一旦未知參數(shù)估計完畢,訓(xùn)練數(shù)據(jù)一般來說,就失去其作用了,因為這些估計出來的參數(shù)就是訓(xùn)練數(shù)據(jù)的濃縮。通過這種方式建立起來的模型就是參數(shù)模型。參數(shù)模型的一個很重要的特點是,如果對于模型的假設(shè)正確,那么只需要很少的訓(xùn)練數(shù)據(jù)就可以從假設(shè)空間中學(xué)出一個很好的模型。但是,如果模型的假設(shè)錯誤,那么無論訓(xùn)練的數(shù)據(jù)量有多大,甚至趨于無窮大,學(xué)出的模型都會與實際模型出現(xiàn)不可磨滅的偏差。感知機、邏輯斯特回歸、高斯判別分析、樸素貝葉斯、線性支持向量機都屬于參數(shù)模型。對于神經(jīng)網(wǎng)絡(luò)來說,當固定了隱層的數(shù)目以及每一層神經(jīng)元的個數(shù),它也屬于參數(shù)模型。但由于隱層數(shù)目與每一層神經(jīng)元個數(shù)的不確定性,很多時候,神經(jīng)網(wǎng)絡(luò)都被歸類為半?yún)?shù)模型。
非參數(shù)算法:
當我們對所要學(xué)習(xí)的問題知之甚少,此時我們一般不會對潛在的模型做過多的假設(shè)。在面對預(yù)測任務(wù)的時候,我們通常會用上所有的訓(xùn)練數(shù)據(jù)。例如簡單的核密度估計(KDE)的表達式中,就帶有所有訓(xùn)練數(shù)據(jù)的信息。通過這種方式建立的模型就是非參數(shù)模型。非參數(shù)模型的一個很重要的特點就是:let the data speak for itself. 正因為如此,非參數(shù)模型的存儲開銷、計算開銷都會比參數(shù)模型大的多。但是,由于不存在模型的錯誤假定問題,可以證明,當訓(xùn)練數(shù)據(jù)量趨于無窮大的時候,非參數(shù)模型可以逼近任意復(fù)雜的真實模型。這正是非參數(shù)模型誘人的一點。另外需要說明的一點是,非參數(shù)模型之所以叫做非參數(shù),并不是因為模型中沒有參數(shù)。實際上,非參數(shù)模型中一般會含有一個或多個超參數(shù),外加無窮多個普通的參數(shù)。k近鄰就是典型的非參數(shù)模型。

總結(jié)就是所謂參數(shù)學(xué)習(xí)算法它有固定的明確的參數(shù),參數(shù) 一旦確定,就不會改變了,我們不需要在保留訓(xùn)練集中的訓(xùn)練樣本。而非參數(shù)學(xué)習(xí)算法,每進行一次預(yù)測,就需要重新學(xué)習(xí)一組 , 是變化的,所以需要一直保留訓(xùn)練樣本。

實際使用

這里采用的數(shù)據(jù)跟線性回歸算法采用的相同。選取不同的k值,得到的擬合曲線如下圖:


局部加權(quán)回歸擬合

從圖中可以看到,當k值較小時,對于訓(xùn)練數(shù)據(jù)有很好的擬合效果;當k值較大時(比如取1),對于訓(xùn)練數(shù)據(jù)擬合的效果不是很好。當然這都是針對訓(xùn)練數(shù)據(jù),在實際使用中,我們更關(guān)注的是對于測試數(shù)據(jù)的效果如何。在實際中,我們可以將數(shù)據(jù)進行十倍交叉驗證,選擇最合適的k值。
從高斯公式中,我們從兩個方面看。首先,我們固定k值,那么距離x^{(i)}較遠的樣本,其對應(yīng)的權(quán)重相對較小;距離x^{(i)}較近的樣本,其對應(yīng)的權(quán)重相對較大,當x取x^{(i)}時,對應(yīng)的權(quán)重為1。而如果我們固定x(即只看某一特定樣本點),k取值較大時,此樣本點對應(yīng)的權(quán)重相對較大;k取值較小時,此樣本點對應(yīng)的權(quán)重相對較大。所以k可以控制算法選擇x^{(i)}點附近有多少樣本參與計算。

k值的影響

最上面的圖是樣本點,剩下三幅圖都是針對樣本點x=0.5,根據(jù)不同的k值,畫出的x附近樣本的權(quán)重變化??梢钥吹剑攌取0.5時,當計算x=0.5時的預(yù)測值時,幾乎所有的樣本點都包括了;而當k=0.01時,僅僅取了x=0.5附近的點參與計算。如果k值取無窮大,那么w對于所有的點的權(quán)重都是1,那么局部加權(quán)線性回歸就變成了普通的線性回歸算法。

嶺回歸算法(Ridge Regression)

上面介紹的線性回歸算法里面可以看到需要計算X^TX的逆,那么如果逆不存在呢?首先思考第一個問題,什么情況下,X^TX的逆不存在呢?

  1. X本身存在相關(guān)關(guān)系,即非滿秩矩陣。比如其中兩列是具有線性關(guān)系
  2. 如果特征列多余樣本數(shù)量,那么X^TX也是非滿秩的。

對于逆不存在的情況下,我們需要將原來的線性回歸算法進行處理,使原先無法求逆的X^TX變成非奇異的??梢酝ㄟ^縮減的方式來處理這類問題,比如嶺回歸算法和LASSO算法。同時由于能夠調(diào)整算法中權(quán)重的大小,能夠防止線性回歸算法的過擬合問題。

嶺回歸算法損失函數(shù)

f(w) = {\sum\limits_{i=1}^m{(y_i - x_i^Tw})^2} + \lambda{\sum\limits_{i=1}^n{w_i^2}}

通過改變\lambda的值,可以使得算法的方差和偏差之間達到平衡,增加\lambda,模型的方差減小而偏差增加。
對損失函數(shù)求取一階導(dǎo)數(shù),并另導(dǎo)數(shù)等于0,求得權(quán)重如下式:
\hat{w} = (X^TX + \lambda{I})^{(-1)}X^TY
在嶺回歸算法中\lambda的選擇對于算法有很大的影響。下圖展示了不同的\lambda的取值對于權(quán)重的影響,因為數(shù)據(jù)有八個特征,所以這里有八個權(quán)重。當\lambda較小時,權(quán)重的值跟采用常規(guī)的線性回歸差不多;而當\lambda較大時,權(quán)重的值都會被調(diào)解的較小。

嶺回歸,lambda值與權(quán)重的關(guān)系

為了找到合適的\lambda值,我們在實踐中往往會采用交叉測試來找到合適的\lambda值。

lasso回歸算法(Least Absolute Shrinkage and Selection Operator)

從嶺回歸算法中,我們可以看到,算法防止過擬合主要是在損失函數(shù)中添加懲罰項。在嶺回歸中,懲罰項如下所示:
{\sum\limits_{k=1}^n{w_k^2}} <= \lambda
而在lasso回歸算法中,懲罰項變成下式:
{\sum\limits_{k=1}^n{|w_k|}} <= \lambda
即將權(quán)重的平方和小于\lambda,替換為權(quán)重的絕對值和小于\lambda.進行了這個變化后,能夠?qū)?quán)重縮小到0,而嶺回歸中無法將權(quán)重值縮小到0,只能接近0.

lasso回歸算法損失函數(shù)

f(w) = {\sum\limits_{i=1}^m{(y_i - x_i^Tw})^2} + \lambda{\sum\limits_{i=1}^n{|w_i|}}

我們也可以結(jié)合嶺回歸算法和lasso的損失函數(shù),構(gòu)建新的損失函數(shù)。這就是彈性網(wǎng)絡(luò)(ElasticNet)

逐步向前回歸

LASSO計算復(fù)雜度相對較高,本部分稍微介紹一下逐步向前回歸,他屬于一種貪心算法,給定初始系數(shù)向量,然后不斷迭代遍歷每個系數(shù),增加或減小一個很小的數(shù),看看代價函數(shù)是否變小,如果變小就保留,如果變大就舍棄,然后不斷迭代直到回歸系數(shù)達到穩(wěn)定。代碼如下:

def run_stage():
    x_arr, y_arr = load_data_set('./data/abalone.txt')
    all_w_001 = stage_wise(x_arr, y_arr, 0.001, 5000)
    print(all_w_001)
    all_w_01 = stage_wise(x_arr, y_arr, 0.01, 200)
    print(all_w_01)
  
def stage_wise(x_arr, y_arr, eps=0.01, num_iter=100):
    """
    forward stagewise regression算法(前向梯度算法)
    是一種近似的 lasso算法
    :param x_arr:
    :param y_arr:
    :param eps:每次特征權(quán)重的變化步長
    :param num_iter: 迭代次數(shù)
    :return:
    """
    x_mat = np.mat(x_arr)
    y_mat = np.mat(y_arr).T
    y_mean = np.mean(y_mat, 0)
    y_mat = y_mat - y_mean
    x_mean = np.mean(x_mat, 0)
    x_var = np.var(x_mat, 0)
    x_mat = (x_mat - x_mean) / x_var
    m, n = np.shape(x_mat)
    ws = np.zeros((n, 1))
    ws_best = ws.copy()
    return_mat = np.zeros((num_iter, n))  # 保存每次迭代最好的權(quán)重值
    for i in range(num_iter):
        # print(ws.T)
        lowest_error = np.inf
        for j in range(n):
            for sign in [-1, 1]:
                ws_test = ws.copy()
                ws_test[j] += eps * sign
                y_test = x_mat * ws_test
                rss_err = rss_error(y_mat.A, y_test.A)  # 將矩陣轉(zhuǎn)為數(shù)組
                if rss_err < lowest_error:
                    lowest_error = rss_err
                    ws_best = ws_test
        ws = ws_best.copy()
        return_mat[i, :] = ws.T
    return return_mat

逐步回歸算法的主要有點在于他可以幫助人們理解現(xiàn)有的模型并作出改進。當構(gòu)建了一個模型后,可以運行逐步回歸算法找出重要的特征,即使停止那些不重要特征的收集。

總結(jié)

上面提到的這些線性回歸算法,我們應(yīng)該怎么選擇呢?一般來說有一點正則項的表現(xiàn)更好,因此通常你應(yīng)該避免使用簡單的線性回歸。嶺回歸是一個很好的首選項,但是如果你的特征僅有少數(shù)是真正有用的,你應(yīng)該選擇Lasso和彈性網(wǎng)絡(luò)。就像我們討論的那樣,它兩能夠?qū)o用特征的權(quán)重降為零。一般來說,彈性網(wǎng)絡(luò)的表現(xiàn)要比Lasso好,因為當特征數(shù)量比樣例的數(shù)量大的時候,或者特征之間有很強的相關(guān)性時,Lasso可能會表現(xiàn)的不規(guī)律。

參考文檔

  1. 《吳恩達cs229 課程講義》
  2. 《機器學(xué)習(xí)實戰(zhàn)》
  3. 機器學(xué)習(xí)實戰(zhàn)_線性回歸&邏輯回歸(二)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容