線性迴歸總結

CharlesDavid_coder發表於2020-12-26

線性迴歸

線性迴歸簡介

線性迴歸應用場景

  • 房價預測

  • 銷售額度預測

  • 貸款額度預測

    舉例:

在這裡插入圖片描述

什麼是線性迴歸

定義與公式

線性迴歸(Linear regression)是利用迴歸方程(函式)一個或多個自變數(特徵值)和因變數(目標值)之間關係進行建模的一種分析方式。

  • 特點:只有一個自變數的情況稱為單變數回歸,多於一個自變數情況的叫做多元迴歸

在這裡插入圖片描述

  • 線性迴歸用矩陣表示舉例

在這裡插入圖片描述

那麼怎麼理解呢?我們來看幾個例子

  • 期末成績:0.7×考試成績+0.3×平時成績
  • 房子價格 = 0.02×中心區域的距離 + 0.04×城市一氧化氮濃度 + (-0.12×自住房平均房價) + 0.254×城鎮犯罪率

上面兩個例子,我們看到特徵值與目標值之間建立了一個關係,這個關係可以理解為線性模型

線性迴歸的特徵與目標的關係分析

線性迴歸當中主要有兩種模型,**一種是線性關係,另一種是非線性關係。**在這裡我們只能畫一個平面更好去理解,所以都用單個特徵或兩個特徵舉例子。

  • 線性關係

    • 單變數線性關係:

    在這裡插入圖片描述

    • 多變數線性關係:

    在這裡插入圖片描述

註釋:單特徵與目標值的關係呈直線關係,或者兩個特徵與目標值呈現平面的關係

更高維度的我們不用自己去想,記住這種關係即可

  • 非線性關係

在這裡插入圖片描述

註釋:為什麼會這樣的關係呢?原因是什麼?

如果是非線性關係,那麼迴歸方程可以理解為:w1x1+w2x22+w3x32

線性迴歸api初步使用

線性迴歸API

sklearn.linear_model.LinearRegression()

  • LinearRegression.coef_:迴歸係數

舉例

在這裡插入圖片描述

步驟分析

  • 1.獲取資料集
  • 2.資料基本處理(該案例中省略)
  • 3.特徵工程(該案例中省略)
  • 4.機器學習
  • 5.模型評估(該案例中省略)

程式碼過程

  • 匯入模組
from sklearn.linear_model import LinearRegression
  • 構造資料集
x = [[80, 86],
[82, 80],
[85, 78],
[90, 90],
[86, 82],
[82, 90],
[78, 80],
[92, 94]]
y = [84.2, 80.6, 80.1, 90, 83.2, 87.6, 79.4, 93.4]
  • 機器學習-- 模型訓練
# 例項化API
estimator = LinearRegression()
# 使用fit方法進行訓練
estimator.fit(x,y)

print(estimator.coef_)#.coef_:迴歸係數 coefficient
res = estimator.predict([[100, 80]])
print(res)
#[0.3 0.7]
#[86.]

數學:求導

常見函式的導數

在這裡插入圖片描述

導數的四則運算

在這裡插入圖片描述

練習

  • 3.1 y = x3-2x2+sinx,求f`(x)

在這裡插入圖片描述

  • 3.2 y=ln(sinx), 求dy/dx

在這裡插入圖片描述

矩陣(向量)求導 [瞭解]

在這裡插入圖片描述

參考連結:https://en.wikipedia.org/wiki/Matrix_calculus#Scalar-by-vector_identities

線性迴歸的損失和優化

假設剛才的房子例子,真實的資料之間存在這樣的關係

真實關係:真實房子價格 = 0.02×中心區域的距離 + 0.04×城市一氧化氮濃度 + (-0.12×自住房平均房價) + 0.254×城鎮犯罪率

那麼現在呢,我們隨意指定一個關係(猜測)

隨機指定關係:預測房子價格 = 0.25×中心區域的距離 + 0.14×城市一氧化氮濃度 + 0.42×自住房平均房價 + 0.34×城鎮犯罪率

請問這樣的話,會發生什麼?真實結果與我們預測的結果之間是不是存在一定的誤差呢?類似這樣樣子

在這裡插入圖片描述

既然存在這個誤差,那我們就將這個誤差給衡量出來

損失函式

總損失定義為:

在這裡插入圖片描述

  • yi為第i個訓練樣本的真實值
  • h(xi)為第i個訓練樣本特徵值組合預測函式
  • 又稱最小二乘法

如何去減少這個損失,使我們預測的更加準確些?既然存在了這個損失,我們一直說機器學習有自動學習的功能,線上性迴歸這裡更是能夠體現。這裡可以通過一些優化方法去優化(其實是數學當中的求導功能)迴歸的總損失!!!

優化演算法

如何去求模型當中的W,使得損失最小?(目的是找到最小損失對應的W值)

線性迴歸經常使用的兩種優化演算法

正規方程

什麼是正規方程

在這裡插入圖片描述

理解:X為特徵值矩陣,y為目標值矩陣。直接求到最好的結果

缺點:當特徵過多過複雜時,求解速度太慢並且得不到結果

在這裡插入圖片描述

正規方程求解舉例

以下表示資料為例:

在這裡插入圖片描述

在這裡插入圖片描述
運用正規方程方法求解引數:
在這裡插入圖片描述

正規方程的推導
  • 推導方式一:

把該損失函式轉換成矩陣寫法:
在這裡插入圖片描述

其中y是真實值矩陣,X是特徵值矩陣,w是權重矩陣

對其求解關於w的最小值,起止y,X 均已知二次函式直接求導,導數為零的位置,即為最小值。

求導:
在這裡插入圖片描述

注:式(1)到式(2)推導過程中, X是一個m行n列的矩陣,並不能保證其有逆矩陣,但是右乘XT把其變成一個方陣,保證其有逆矩陣。

式(5)到式(6)推導過程中,和上類似。

  • 推導方式二【擴充】:

https://www.jianshu.com/p/2b6633bd4d47

梯度下降(Gradient Descent)

什麼是梯度下降

梯度下降法的基本思想可以類比為一個下山的過程。

假設這樣一個場景:一個人被困在山上,需要從山上下來(i.e. 找到山的最低點,也就是山谷)。但此時山上的濃霧很大,導致可視度很低。因此,下山的路徑就無法確定,他必須利用自己周圍的資訊去找到下山的路徑。這個時候,他就可以利用梯度下降演算法來幫助自己下山。具體來說就是,以他當前的所處的位置為基準,尋找這個位置最陡峭的地方,然後朝著山的高度下降的地方走,(同理,如果我們的目標是上山,也就是爬到山頂,那麼此時應該是朝著最陡峭的方向往上走)。然後每走一段距離,都反覆採用同一個方法,最後就能成功的抵達山谷。

在這裡插入圖片描述

梯度下降的基本過程就和下山的場景很類似。

首先,我們有一個可微分的函式。這個函式就代表著一座山。

我們的目標就是找到這個函式的最小值,也就是山底。

根據之前的場景假設,最快的下山的方式就是找到當前位置最陡峭的方向,然後沿著此方向向下走,對應到函式中,就是找到給定點的梯度 ,然後朝著梯度相反的方向,就能讓函式值下降的最快!因為梯度的方向就是函式之變化最快的方向。 所以,我們重複利用這個方法,反覆求取梯度,最後就能到達區域性的最小值,這就類似於我們下山的過程。而求取梯度就確定了最陡峭的方向,也就是場景中測量方向的手段。

梯度的概念

梯度是微積分中一個很重要的概念

在單變數的函式中,梯度其實就是函式的微分,代表著函式在某個給定點的切線的斜率

在多變數函式中,梯度是一個向量,向量有方向,梯度的方向就指出了函式在給定點的上升最快的方向

這也就說明了為什麼我們需要千方百計的求取梯度!我們需要到達山底,就需要在每一步觀測到此時最陡峭的地方,梯度就恰巧告訴了我們這個方向。梯度的方向是函式在給定點上升最快的方向,那麼梯度的反方向就是函式在給定點下降最快的方向,這正是我們所需要的。所以我們只要沿著梯度的反方向一直走,就能走到區域性的最低點!

梯度下降舉例
  • 1. 單變數函式的梯度下降**

我們假設有一個單變數的函式 :J(θ) = θ2

函式的微分:J、(θ) = 2θ

初始化,起點為: θ0 = 1

學習率:α = 0.4

我們開始進行梯度下降的迭代計算過程:

在這裡插入圖片描述

如圖,經過四次的運算,也就是走了四步,基本就抵達了函式的最低點,也就是山底

在這裡插入圖片描述

  • 2.多變數函式的梯度下降

我們假設有一個目標函式 ::J(θ) = θ12 + θ22

現在要通過梯度下降法計算這個函式的最小值。我們通過觀察就能發現最小值其實就是 (0,0)點。但是接下 來,我們會從梯度下降演算法開始一步步計算到這個最小值! 我們假設初始的起點為: θ0 = (1, 3)

初始的學習率為:α = 0.1

函式的梯度為:▽:J(θ) =< 2θ1 ,2θ2>

進行多次迭代:

在這裡插入圖片描述

我們發現,已經基本靠近函式的最小值點

在這裡插入圖片描述

梯度下降**(**Gradient Descent)公式

在這裡插入圖片描述

1) α是什麼含義?

α在梯度下降演算法中被稱作為學習率或者步長,意味著我們可以通過α來控制每一步走的距離,以保證不要步子跨的太大扯著蛋,哈哈,其實就是不要走太快,錯過了最低點。同時也要保證不要走的太慢,導致太陽下山了,還沒有走到山下。所以α的選擇在梯度下降法中往往是很重要的!α不能太大也不能太小,太小的話,可能導致遲遲走不到最低點,太大的話,會導致錯過最低點!

2) 為什麼梯度要乘以一個負號

梯度前加一個負號,就意味著朝著梯度相反的方向前進!我們在前文提到,梯度的方向實際就是函式在此點上升最快的方向!而我們需要朝著下降最快的方向走,自然就是負的梯度的方向,所以此處需要加上負號

我們通過兩個圖更好理解梯度下降的過程

在這裡插入圖片描述

在這裡插入圖片描述

所以有了梯度下降這樣一個優化演算法,迴歸就有了"自動學習"的能力

  • 優化動態圖演示

在這裡插入圖片描述

  • 梯度下降和正規方程的對比
梯度下降正規方程
需要選擇學習率不需要
需要迭代求解一次運算得出
特徵數量較大可以使用需要計算方程,時間複雜度高O(n3)
  • 選擇:
    • 小規模資料:
      • LinearRegression(不能解決擬合問題)
      • 嶺迴歸
    • 大規模資料:SGDRegressor

梯度下降法介紹

上一節中給大家介紹了最基本的梯度下降法實現流程,常見的梯度下降演算法有:

  • 全梯度下降演算法(Full gradient descent),
  • 隨機梯度下降演算法(Stochastic gradient descent),
  • 小批量梯度下降演算法(Mini-batch gradient descent),
  • 隨機平均梯度下降演算法(Stochastic average gradient descent)

它們都是為了正確地調節權重向量,通過為每個權重計算一個梯度,從而更新權值,使目標函式儘可能最小化。其差別在於樣本的使用方式不同。

1 全梯度下降演算法(FG)

計算訓練集所有樣本誤差,對其求和再取平均值作為目標函式。

權重向量沿其梯度相反的方向移動,從而使當前目標函式減少得最多。

因為在執行每次更新時,我們需要在整個資料集上計算所有的梯度,所以批梯度下降法的速度會很慢,同時,批梯度下降法無法處理超出記憶體容量限制的資料集。

全梯度下降法同樣也不能線上更新模型,即在執行的過程中,不能增加新的樣本。

其是在整個訓練資料集上計算損失函式關於引數θ的梯度:

在這裡插入圖片描述

2 隨機梯度下降演算法(SG)

由於FG每迭代更新一次權重都需要計算所有樣本誤差,而實際問題中經常有上億的訓練樣本,故效率偏低,且容易陷入區域性最優解,因此提出了隨機梯度下降演算法。

其每輪計算的目標函式不再是全體樣本誤差,而僅是單個樣本誤差,即每次只代入計算一個樣本目標函式的梯度來更新權重,再取下一個樣本重複此過程,直到損失函式值停止下降或損失函式值小於某個可以容忍的閾值。

此過程簡單,高效,通常可以較好地避免更新迭代收斂到區域性最優解。其迭代形式為

在這裡插入圖片描述

每次只使用一個樣本迭代,若遇上噪聲則容易陷入區域性最優解。

其中,x(i)表示一條訓練樣本的特徵值,y(i)表示一條訓練樣本的標籤值

但是由於,SG每次只使用一個樣本迭代,若遇上噪聲則容易陷入區域性最優解。

3 小批量梯度下降演算法(mini-bantch)

小批量梯度下降演算法是FG和SG的折中方案,在一定程度上兼顧了以上兩種方法的優點。

每次從訓練樣本集上隨機抽取一個小樣本集,在抽出來的小樣本集上採用FG迭代更新權重。

被抽出的小樣本集所含樣本點的個數稱為batch_size,通常設定為2的冪次方,更有利於GPU加速處理。

特別的,若batch_size=1,則變成了SG;若batch_size=n,則變成了FG.其迭代形式為

在這裡插入圖片描述

4 隨機平均梯度下降演算法(SAG)

在SG方法中,雖然避開了運算成本大的問題,但對於大資料訓練而言,SG效果常不盡如人意,因為每一輪梯度更新都完全與上一輪的資料和梯度無關。

隨機平均梯度演算法克服了這個問題,在記憶體中為每一個樣本都維護一箇舊的梯度,隨機選擇第i個樣本來更新此樣本的梯度,其他樣本的梯度保持不變,然後求得所有梯度的平均值,進而更新了引數。

如此,每一輪更新僅需計算一個樣本的梯度,計算成本等同於SG,但收斂速度快得多。

演算法比較

為了比對四種基本梯度下降演算法的效能,我們通過一個邏輯二分類實驗來說明。本文所用的Adult資料集來自UCI公共資料庫(http://archive.ics.uci.edu/ml/datasets/Adult)。 資料集共有15081條記錄,包括“性別”“年齡”“受教育情況”“每週工作時常”等14個特徵,資料標記列顯示“年薪是否大於50000美元”。我們將資料集的80%作為訓練集,剩下的20%作為測試集,使用邏輯迴歸建立預測模型,根據資料點的14個特徵預測其資料標記(收入情況)。

以下6幅圖反映了模型優化過程中四種梯度演算法的效能差異。

在這裡插入圖片描述

在圖1和圖2中,橫座標代表有效迭代次數,縱座標代表平均損失函式值。圖1反映了前25次有效迭代過程中平均損失函式值的變化情況,為了便於觀察,圖2放大了第10次到25次的迭代情況。

從圖1中可以看到,四種梯度演算法下,平均損失函式值隨迭代次數的增加而減少FG的迭代效率始終領先,能在較少的迭代次數下取得較低的平均損失函式值。FG與SAG的影像較平滑,這是因為這兩種演算法在進行梯度更新時都結合了之前的梯度;SG與mini-batch的影像曲折明顯,這是因為這兩種演算法在每輪更新梯度時都隨機抽取一個或若干樣本進行計算,並沒有考慮到之前的梯度。

從圖2中可以看到**雖然四條折現的縱座標雖然都趨近於0,但SG和FG較早,mini-batch最晚。**這說明如果想使用mini-batch獲得最優引數,必須對其進行較其他三種梯度演算法更多頻次的迭代。

在圖3,4,5,6中,橫座標表示時間,縱座標表示平均損失函式值。

從圖3中可以看出使用四種演算法將平均損失函式值從0.7降到0.1最多隻需要2.5s,由於本文程式在初始化梯度時將梯度設為了零,故前期的優化效果格外明顯。其中SG在前期的表現最好,僅1.75s便將損失函值降到了0.1,雖然SG無法像FG那樣達到線性收斂,但在處理大規模機器學習問題時,為了節約時間成本和儲存成本,可在訓練的一開始先使用SG,後期考慮到收斂性和精度可改用其他演算法。

從圖4,5,6可以看出,隨著平均損失函式值的不斷減小,SG的效能逐漸反超FG,FG的優化效率最慢,即達到相同平均損失函式值時FG所需要的時間最久。

綜合分析六幅圖我們得出以下結論:

(1)FG方法由於它每輪更新都要使用全體資料集,故花費的時間成本最多,記憶體儲存最大。

(2)SAG在訓練初期表現不佳,優化速度較慢。這是因為我們常將初始梯度設為0,而SAG每輪梯度更新都結合了上一輪梯度值。

(3)綜合考慮迭代次數和執行時間,SG表現效能都很好,能在訓練初期快速擺脫初始梯度值,快速將平均損失函式降到很低。但要注意,在使用SG方法時要慎重選擇步長,否則容易錯過最優解。

(4)mini-batch結合了SG的“膽大”和FG的“心細”,從6幅影像來看,它的表現也正好居於SG和FG二者之間。在目前的機器學習領域,mini-batch是使用最多的梯度下降演算法,正是因為它避開了FG運算效率低成本大和SG收斂效果不穩定的缺點。

梯度下降優化演算法(擴充)

以下這些演算法主要用於深度學習優化

  • 動量法
    • 其實動量法(SGD with monentum)就是SAG的姐妹版
    • SAG是對過去K次的梯度求平均值
    • SGD with monentum 是對過去所有的梯度求加權平均
  • Nesterov加速梯度下降法
    • 類似於一個智慧球,在重新遇到斜率上升時候,能夠知道減速
  • Adagrad
    • 讓學習率使用引數
    • 對於出現次數較少的特徵,我們對其採用更大的學習率,對於出現次數較多的特徵,我們對其採用較小的學習率。
  • Adadelta
    • Adadelta是Adagrad的一種擴充套件演算法,以處理Adagrad學習速率單調遞減的問題。
  • RMSProp
    • 其結合了梯度平方的指數移動平均數來調節學習率的變化。
    • 能夠在不穩定(Non-Stationary)的目標函式情況下進行很好地收斂。
  • Adam
    • 結合AdaGrad和RMSProp兩種優化演算法的優點。
    • 是一種自適應的學習率演算法

參考連結:https://blog.csdn.net/google19890102/article/details/69942970

線性迴歸api再介紹

  • sklearn.linear_model.LinearRegression(fit_intercept=True)
    • 通過正規方程優化
    • fit_intercept:是否計算偏置
    • LinearRegression.coef_:迴歸係數
    • LinearRegression.intercept_:偏置
  • sklearn.linear_model.SGDRegressor(loss=“squared_loss”, fit_intercept=True, learning_rate =‘invscaling’, eta0=0.01)
    • SGDRegressor類實現了隨機梯度下降學習,它支援不同的loss函式和正則化懲罰項來擬合線性迴歸模型。
    • loss:損失型別
      • loss=”squared_loss”: 普通最小二乘法
    • fit_intercept:是否計算偏置
    • learning_rate : string, optional
      • 學習率填充
      • ’constant’: eta = eta0
      • ’optimal’: eta = 1.0 / (alpha * (t + t0)) [default]
      • ‘invscaling’: eta = eta0 / pow(t, power_t)
        • power_t=0.25:存在父類當中
      • 對於一個常數值的學習率來說,可以使用learning_rate=’constant’ ,並使用eta0來指定學習率。
    • SGDRegressor.coef_:迴歸係數
    • SGDRegressor.intercept_:偏置

sklearn提供給我們兩種實現的API, 可以根據選擇使用

案例:波士頓房價預測

  • 資料介紹

在這裡插入圖片描述

在這裡插入圖片描述

給定的這些特徵,是專家們得出的影響房價的結果屬性。我們此階段不需要自己去探究特徵是否有用,只需要使用這些特徵。到後面量化很多特徵需要我們自己去尋找

1 分析

迴歸當中的資料大小不一致,是否會導致結果影響較大。所以需要做標準化處理。

  • 資料分割與標準化處理
  • 迴歸預測
  • 線性迴歸的演算法效果評估

2 迴歸效能評估

均方誤差(Mean Squared Error)MSE)評價機制:

在這裡插入圖片描述

注:yi為預測值,¯y為真實值

  • sklearn.metrics.mean_squared_error(y_true, y_pred)
    • 均方誤差迴歸損失
    • y_true:真實值
    • y_pred:預測值
    • return:浮點數結果

3 程式碼實現

from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression, SGDRegressor
from sklearn.metrics import mean_squared_error


def linear_model1():
    """
    線性迴歸:正規方程
    :return:None
    """
    # 1.獲取資料
    data = load_boston()

    # 2.資料集劃分
    x_train, x_test, y_train, y_test = train_test_split(data.data, data.target)
    # 3.特徵工程-標準化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.fit_transform(x_test)

    # 4.機器學習-線性迴歸(特徵方程)
    estimator = LinearRegression()
    estimator.fit(x_train, y_train)

    # 5.模型評估
    # 5.1 獲取係數等值
    y_predict = estimator.predict(x_test)
    score = estimator.score(x_test, y_test)
    print(score)

    print("預測值為:\n", y_predict)
    print("模型中的係數為:\n", estimator.coef_)
    print("模型中的偏置為:\n", estimator.intercept_)

    # 5.2 評價
    # 均方誤差
    error = mean_squared_error(y_test, y_predict)
    print("誤差為:\n", error)


def linear_model2():
    """
    線性迴歸:梯度下降法
    :return:None
    """
    # 1.獲取資料
    data = load_boston()

    # 2.資料集劃分
    x_train, x_test, y_train, y_test = train_test_split(data.data, data.target)

    # 3.特徵工程-標準化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.fit_transform(x_test)
    # 4.機器學習-線性迴歸(特徵方程)
    estimator = SGDRegressor(max_iter=10000, learning_rate="constant", eta0=0.001)

    # 5.模型評估
    # 5.1 獲取係數等值
    estimator.fit(x_train, y_train)
    y_predict = estimator.predict(x_test)
    score = estimator.score(x_test, y_test)

    print("預測值為:\n", y_predict)
    print("模型中的係數為:\n", estimator.coef_)
    print("模型中的偏置為:\n", estimator.intercept_)
    print(score)
    # 5.2 評價
    # 均方誤差
    error = mean_squared_error(y_test, y_predict)
    print("誤差為:\n", error)


if __name__ == '__main__':
    # linear_model1()
    linear_model2()

我們也可以嘗試去修改學習率

 estimator = SGDRegressor(max_iter=10000, learning_rate="constant", eta0=0.001)

此時我們可以通過調引數,找到學習率效果更好的值。

欠擬合和過擬合

定義

  • 欠擬合:一個假設在訓練資料上不能獲得更好的擬合,並且在測試資料集上也不能很好地擬合資料,此時認為這個假設出現了欠擬合的現象。(模型過於簡單)

  • 過擬合:一個假設在訓練資料上能夠獲得比其他假設更好的擬合, 但是在測試資料集上卻不能很好地擬合資料,此時認為這個假設出現了過擬合的現象。(模型過於複雜)

在這裡插入圖片描述

那麼是什麼原因導致模型複雜?線性迴歸進行訓練學習的時候變成模型會變得複雜,這裡就對應前面再說的線性迴歸的兩種關係,非線性關係的資料,也就是存在很多無用的特徵或者現實中的事物特徵跟目標值的關係並不是簡單的線性關係。

原因以及解決辦法

  • 欠擬合原因以及解決辦法
    • 原因:學習到資料的特徵過少
    • 解決辦法:
      • **1)新增其他特徵項,**有時候我們模型出現欠擬合的時候是因為特徵項不夠導致的,可以新增其他特徵項來很好地解決。例如,“組合”、“泛化”、“相關性”三類特徵是特徵新增的重要手段,無論在什麼場景,都可以照葫蘆畫瓢,總會得到意想不到的效果。除上面的特徵之外,“上下文特徵”、“平臺特徵”等等,都可以作為特徵新增的首選項。
      • 2)新增多項式特徵,這個在機器學習演算法裡面用的很普遍,例如將線性模型通過新增二次項或者三次項使模型泛化能力更強。
  • 過擬合原因以及解決辦法
    • 原因:原始特徵過多,存在一些嘈雜特徵, 模型過於複雜是因為模型嘗試去兼顧各個測試資料點
    • 解決辦法:
      • 1)重新清洗資料,導致過擬合的一個原因也有可能是資料不純導致的,如果出現了過擬合就需要我們重新清洗資料。
      • 2)增大資料的訓練量,還有一個原因就是我們用於訓練的資料量太小導致的,訓練資料佔總資料的比例過小。
      • 3)正則化
      • 4)減少特徵維度,防止維災難

正則化

什麼是正則化

在解決迴歸過擬閤中,我們選擇正則化。但是對於其他機器學習演算法如分類演算法來說也會出現這樣的問題,除了一些演算法本身作用之外(決策樹、神經網路),我們更多的也是去自己做特徵選擇,包括之前說的刪除、合併一些特徵

在這裡插入圖片描述

如何解決?

在這裡插入圖片描述

在學習的時候,資料提供的特徵有些影響模型複雜度或者這個特徵的資料點異常較多,所以演算法在學習的時候儘量減少這個特徵的影響(甚至刪除某個特徵的影響),這就是正則化

注:調整時候,演算法並不知道某個特徵影響,而是去調整引數得出優化的結果

正則化類別
  • L2正則化
    • 作用:可以使得其中一些W的都很小,都接近於0,削弱某個特徵的影響
    • 優點:越小的引數說明模型越簡單,越簡單的模型則越不容易產生過擬合現象
    • Ridge迴歸
  • L1正則化
    • 作用:可以使得其中一些W的值直接為0,刪除這個特徵的影響
    • LASSO迴歸

維災難【擴充知識】

什麼是維災難

隨著維度的增加,分類器效能逐步上升,到達某點之後,其效能便逐漸下降

在這裡插入圖片描述

有一系列的圖片,每張圖片的內容可能是貓也可能是狗;我們需要構造一個分類器能夠對貓、狗自動的分類。首先,要尋找到一些能夠描述貓和狗的特徵,這樣我們的分類演算法就可以利用這些特徵去識別物體。貓和狗的皮毛顏色可能是一個很好的特徵,考慮到紅綠藍構成影像的三基色,因此用圖片三基色各自的平均值稱得上方便直觀。這樣就有了一個簡單的Fisher分類器:

If  0.5*red + 0.3*green + 0.2*blue > 0.6 : return cat;
    else return dog;

使用顏色特徵可能無法得到一個足夠準確的分類器,如果是這樣的話,我們不妨加入一些諸如影像紋理(影像灰度值在其X、Y方向的導數dx、dy),就有5個特徵(Red、Blue、Green、dx、dy)來設計我們的分類器:

也許分類器準確率依然無法達到要求,加入更多的特徵,比如顏色、紋理的統計資訊等等,如此下去,可能會得到上百個特徵。那是不是我們的分類器效能會隨著特徵數量的增加而逐步提高呢?答案也許有些讓人沮喪,事實上,當特徵數量達到一定規模後,分類器的效能是在下降的。

隨著維度(特徵數量)的增加,分類器的效能卻下降了

維數災難與過擬合

我們假設貓和狗圖片的數量是有限的(樣本數量總是有限的),假設有10張圖片,接下來我們就用這僅有的10張圖片來訓練我們的分類器。

在這裡插入圖片描述

增加一個特徵,比如綠色,這樣特徵維數擴充套件到了2維:

增加一個特徵後,我們依然無法找到一條簡單的直線將它們有效分類

在這裡插入圖片描述

再增加一個特徵,比如藍色,擴充套件到3維特徵空間:

在這裡插入圖片描述

在3維特徵空間中,我們很容易找到一個分類平面,能夠在訓練集上有效的將貓和狗進行分類:

在高維空間中,我們似乎能得到更優的分類器效能。

在這裡插入圖片描述

從1維到3維,給我們的感覺是:維數越高,分類效能越優。然而,維數過高將導致一定的問題:在一維特徵空間下,我們假設一個維度的寬度為5個單位,這樣樣本密度為10/5=2;在2維特徵空間下,10個樣本所分佈的空間大小25,這樣樣本密度為10/25=0.4;在3維特徵空間下,10個樣本分佈的空間大小為125,樣本密度就為10/125=0.08.

如果繼續增加特徵數量,隨著維度的增加,樣本將變得越來越稀疏,在這種情況下,也更容易找到一個超平面將目標分開。然而,如果我們將高維空間向低維空間投影,高維空間隱藏的問題將會顯現出來:

過多的特徵導致的過擬合現象:訓練集上表現良好,但是對新資料缺乏泛化能力。

在這裡插入圖片描述

高維空間訓練形成的線性分類器,相當於在低維空間的一個複雜的非線性分類器,這種分類器過多的強調了訓練集的準確率甚至於對一些錯誤/異常的資料也進行了學習,而正確的資料卻無法覆蓋整個特徵空間。為此,這樣得到的分類器在對新資料進行預測時將會出現錯誤。這種現象稱之為過擬合,同時也是維災難的直接體現。

在這裡插入圖片描述

簡單的線性分類器在訓練資料上的表現不如非線性分類器,但由於線性分類器的學習過程中對噪聲沒有對非線性分類器敏感,因此對新資料具備更優的泛化能力。換句話說,通過使用更少的特徵,避免了維數災難的發生(也即避免了高維情況下的過擬合)

由於高維而帶來的資料稀疏性問題:假設有一個特徵,它的取值範圍D在0到1之間均勻分佈,並且對狗和貓來說其值都是唯一的,我們現在利用這個特徵來設計分類器。如果我們的訓練資料覆蓋了取值範圍的20%(e.g 0到0.2),那麼所使用的訓練資料就佔總樣本量的20%。上升到二維情況下,覆蓋二維特徵空間20%的面積,則需要在每個維度上取得45%的取值範圍。在三維情況下,要覆蓋特徵空間20%的體積,則需要在每個維度上取得58%的取值範圍…在維度接近一定程度時,要取得同樣的訓練樣本數量,則幾乎要在每個維度上取得接近100%的取值範圍,或者增加總樣本數量,但樣本數量也總是有限的。

如果一直增加特徵維數,由於樣本分佈越來越稀疏,如果要避免過擬合的出現,就不得不持續增加樣本數量。

在這裡插入圖片描述

資料在高維空間的中心比在邊緣區域具備更大的稀疏性,資料更傾向於分佈在空間的邊緣區域:

不屬於單位圓的訓練樣本比搜尋空間的中心更接近搜尋空間的角點。這些樣本很難分類,因為它們的特徵值差別很大(例如,單位正方形的對角的樣本)。

在這裡插入圖片描述

一個有趣的問題是,當我們增加特徵空間的維度時,圓(超球面)的體積如何相對於正方形(超立方體)的體積發生變化。尺寸d的單位超立方體的體積總是1 ^ d = 1.尺寸d和半徑0.5的內切超球體的體積可以計算為:

在這裡插入圖片描述

在高維空間中,大多數訓練資料駐留在定義特徵空間的超立方體的角落中。如前所述,特徵空間角落中的例項比圍繞超球體質心的例項難以分類。

在這裡插入圖片描述

在高維空間中,大多數訓練資料駐留在定義特徵空間的超立方體的角落中。如前所述,特徵空間角落中的例項比圍繞超球體質心的例項難以分類:

在這裡插入圖片描述

an 8D hypercube which has 2^8 = 256 corners

事實證明,許多事物在高維空間中表現得非常不同。 例如,如果你選擇一個單位平方(1×1平方)的隨機點,它將只有大約0.4%的機會位於小於0.001的邊界(換句話說,隨機點將沿任何維度“極端”這是非常不可能的)。 但是在一個10000維單位超立方體(1×1×1立方體,有1萬個1)中,這個概率大於99.999999%。 高維超立方體中的大部分點都非常靠近邊界。更難區分的是:如果你在一個單位正方形中隨機抽取兩個點,這兩個點之間的距離平均約為0.52。如果在單位三維立方體中選取兩個隨機點,則平均距離將大致為0.66。但是在一個100萬維的超立方體中隨機抽取兩點呢?那麼平均距離將是大約408.25(大約1,000,000 / 6)!

非常違反直覺:當兩個點位於相同的單位超立方體內時,兩點如何分離?這個事實意味著高維資料集有可能非常稀疏:大多數訓練例項可能彼此遠離。當然,這也意味著一個新例項可能離任何訓練例項都很遠,這使得預測的可信度表現得比在低維度資料中要來的差。訓練集的維度越多,過度擬合的風險就越大

理論上講,維度災難的一個解決方案可能是增加訓練集的大小以達到足夠密度的訓練例項。 不幸的是,在實踐中,達到給定密度所需的訓練例項的數量隨著維度的數量呈指數增長。 如果只有100個特徵(比MNIST問題少得多),那麼為了使訓練例項的平均值在0.1以內,需要比可觀察宇宙中的原子更多的訓練例項,假設它們在所有維度上均勻分佈。

對於8維超立方體,大約98%的資料集中在其256個角上。結果,當特徵空間的維度達到無窮大時,從取樣點到質心的最小和最大歐幾里得距離的差與最小距離本身只比趨於零:

在這裡插入圖片描述

距離測量開始失去其在高維空間中測量的有效性,由於分類器取決於這些距離測量,因此在較低維空間中分類通常更容易,其中較少特徵用於描述感興趣物件。

如果理論無限數量的訓練樣本可用,則維度的詛咒不適用,我們可以簡單地使用無數個特徵來獲得完美的分類。訓練資料的大小越小,應使用的功能就越少。如果N個訓練樣本足以覆蓋單位區間大小的1D特徵空間,則需要N ^ 2個樣本來覆蓋具有相同密度的2D特徵空間,並且在3D特徵空間中需要N ^ 3個樣本。換句話說,所需的訓練例項數量隨著使用的維度數量呈指數增長

正則化線性模型

  • Ridge Regression 嶺迴歸
  • Lasso 迴歸
  • Elastic Net 彈性網路
  • Early stopping

1 Ridge Regression (嶺迴歸,又名 Tikhonov regularization)

嶺迴歸是線性迴歸的正則化版本,即在原來的線性迴歸的 cost function 中新增正則項(regularization term):

在這裡插入圖片描述

以達到在擬合資料的同時,使模型權重儘可能小的目的,嶺迴歸代價函式:

在這裡插入圖片描述

  • α=0:嶺迴歸退化為線性迴歸
  • 就是把係數前面新增平方項,然後限制係數值的大小
  • α值越小,係數值越大,α越大,係數值越小

2 Lasso Regression(Lasso 迴歸)

Lasso 迴歸是線性迴歸的另一種正則化版本,正則項為權值向量的ℓ1範數。

  • 對係數值進行絕對值處理
  • 由於絕對值在頂點處不可導,所以進行計算的過程中產生很多0,最後得到結果為:稀疏矩陣

Lasso迴歸的代價函式 :

在這裡插入圖片描述

【注意 】

  • Lasso Regression 的代價函式在 θi=0處是不可導的.
  • 解決方法:在θi=0處用一個次梯度向量(subgradient vector)代替梯度,如下式
  • Lasso Regression 的次梯度向量

在這裡插入圖片描述

Lasso Regression 有一個很重要的性質是:傾向於完全消除不重要的權重。

例如:當α 取值相對較大時,高階多項式退化為二次甚至是線性:高階多項式特徵的權重被置為0。

也就是說,Lasso Regression 能夠自動進行特徵選擇,並輸出一個稀疏模型(只有少數特徵的權重是非零的)。

3 Elastic Net (彈性網路)

彈性網路在嶺迴歸和Lasso迴歸中進行了折中,通過 混合比(mix ratio) r 進行控制:

  • r=0:彈性網路變為嶺迴歸
  • r=1:彈性網路便為Lasso迴歸

彈性網路的代價函式 :

在這裡插入圖片描述

一般來說,我們應避免使用樸素線性迴歸,而應對模型進行一定的正則化處理,那如何選擇正則化方法呢?

小結:

  • 常用:嶺迴歸

  • 假設只有少部分特徵是有用的:

    • 彈性網路
    • Lasso
    • 一般來說,彈性網路的使用更為廣泛。因為在特徵維度高於訓練樣本數,或者特徵是強相關的情況下,Lasso迴歸的表現不太穩定。
  • api:

    • from sklearn.linear_model import Ridge, ElasticNet, Lasso
      

4 Early Stopping [瞭解]

Early Stopping 也是正則化迭代學習的方法之一。

其做法為:在驗證錯誤率達到最小值的時候停止訓練。

線性迴歸的改進-嶺迴歸

API

  • sklearn.linear_model.Ridge(alpha=1.0, fit_intercept=True,solver=“auto”, normalize=False)
    • 具有l2正則化的線性迴歸
    • alpha:正則化力度,也叫 λ
      • λ取值:0~1 1~10
    • solver:會根據資料自動選擇優化方法
      • sag:如果資料集、特徵都比較大,選擇該隨機梯度下降優化
    • normalize:資料是否進行標準化
      • normalize=False:可以在fit之前呼叫preprocessing.StandardScaler標準化資料
    • Ridge.coef_:迴歸權重
    • Ridge.intercept_:迴歸偏置

Ridge方法相當於SGDRegressor(penalty=‘l2’, loss=“squared_loss”),只不過SGDRegressor實現了一個普通的隨機梯度下降學習,推薦使用Ridge(實現了SAG)

  • sklearn.linear_model.RidgeCV(_BaseRidgeCV, RegressorMixin)
    • 具有l2正則化的線性迴歸,可以進行交叉驗證
    • coef_:迴歸係數
class _BaseRidgeCV(LinearModel):
    def __init__(self, alphas=(0.1, 1.0, 10.0),
                 fit_intercept=True, normalize=False,scoring=None,
                 cv=None, gcv_mode=None,
                 store_cv_values=False):

觀察正則化程度的變化,對結果的影響?

在這裡插入圖片描述

  • 正則化力度越大,權重係數會越小
  • 正則化力度越小,權重係數會越大

波士頓房價預測

def linear_model3():
    """
    線性迴歸:嶺迴歸
    :return:
    """
    # 1.獲取資料
    data = load_boston()

    # 2.資料集劃分
    x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, random_state=22)

    # 3.特徵工程-標準化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.fit_transform(x_test)

    # 4.機器學習-線性迴歸(嶺迴歸)
    estimator = Ridge(alpha=1)
    # estimator = RidgeCV(alphas=(0.1, 1, 10))
    estimator.fit(x_train, y_train)

    # 5.模型評估
    # 5.1 獲取係數等值
    y_predict = estimator.predict(x_test)
    print("預測值為:\n", y_predict)
    print("模型中的係數為:\n", estimator.coef_)
    print("模型中的偏置為:\n", estimator.intercept_)

    # 5.2 評價
    # 均方誤差
    error = mean_squared_error(y_test, y_predict)
    print("誤差為:\n", error)

模型的儲存和載入

sklearn模型的儲存和載入API

  • from sklearn.externals import joblib
    • 儲存:joblib.dump(estimator, ‘test.pkl’)
    • 載入:estimator = joblib.load(‘test.pkl’)

線性迴歸的模型儲存載入案例

from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import Ridge
from sklearn.metrics import mean_squared_error
import joblib


def dump_demo():
    """
    線性迴歸:嶺迴歸
    :return:
    """
    # 1.獲取資料
    data = load_boston()

    # 2.資料集劃分
    x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, random_state=22)

    # 3.特徵工程-標準化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)

    # 4.機器學習-線性迴歸(嶺迴歸)
    estimator = Ridge(alpha=1)
    # 模型儲存
    estimator.fit(x_train, y_train)
    joblib.dump(estimator, '../data/test.pkl')


def load_demo():
    """
    線性迴歸:嶺迴歸
    :return:
    """
    # 1.獲取資料
    data = load_boston()

    # 2.資料集劃分
    x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, random_state=22)

    # 3.特徵工程-標準化
    transfer = StandardScaler()
    x_test = transfer.fit_transform(x_test)
    # 模型讀取
    estimator = joblib.load('../data/test.pkl')

    # 5.模型評估
    # 5.1 獲取係數等值
    y_predict = estimator.predict(x_test)
    print("預測值為:\n", y_predict)
    print("模型中的係數為:\n", estimator.coef_)
    print("模型中的偏置為:\n", estimator.intercept_)
    print(estimator.score(x_test, y_test))
    # 5.2 評價
    # 均方誤差
    error = mean_squared_error(y_test, y_predict)
    print("誤差為:\n", error)


if __name__ == '__main__':
    dump_demo()
    load_demo()

相關文章