日萌社
人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度學習實戰(不定時更新)
2.1 線性迴歸簡介
1 線性迴歸應用場景
-
房價預測
-
銷售額度預測
-
貸款額度預測
舉例:
2 什麼是線性迴歸
2.1 定義與公式
線性迴歸(Linear regression)是利用迴歸方程(函數)對一個或多個自變量(特徵值)和因變量(目標值)之間關係進行建模的一種分析方式。
-
特點:只有一個自變量的情況稱爲單變量回歸,多於一個自變量情況的叫做多元迴歸
那麼怎麼理解呢?我們來看幾個例子
- 期末成績:0.7×考試成績+0.3×平時成績
- 房子價格 = 0.02×中心區域的距離 + 0.04×城市一氧化氮濃度 + (-0.12×自住房平均房價) + 0.254×城鎮犯罪率
上面兩個例子,我們看到特徵值與目標值之間建立了一個關係,這個關係可以理解爲線性模型。
2.2 線性迴歸的特徵與目標的關係分析
線性迴歸當中主要有兩種模型,一種是線性關係,另一種是非線性關係。在這裏我們只能畫一個平面更好去理解,所以都用單個特徵或兩個特徵舉例子。
-
線性關係
- 單變量線性關係:
註釋:單特徵與目標值的關係呈直線關係,或者兩個特徵與目標值呈現平面的關係
更高維度的我們不用自己去想,記住這種關係即可
-
非線性關係
3 小結
- 線性迴歸的定義【瞭解】
- 利用迴歸方程(函數)對一個或多個自變量(特徵值)和因變量(目標值)之間關係進行建模的一種分析方式
- 線性迴歸的分類【知道】
- 線性關係
- 非線性關係
2.2 線性迴歸api初步使用
1 線性迴歸API
- sklearn.linear_model.LinearRegression()
- LinearRegression.coef_:迴歸係數
2.1 步驟分析
- 1.獲取數據集
- 2.數據基本處理(該案例中省略)
- 3.特徵工程(該案例中省略)
- 4.機器學習
- 5.模型評估(該案例中省略)
2.2 代碼過程
- 導入模塊
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)
estimator.coef_
estimator.predict([[100, 80]])
3 小結
- sklearn.linear_model.LinearRegression()
- LinearRegression.coef_:迴歸係數
linear_demo.py
# coding:utf-8
from sklearn.linear_model import LinearRegression
# 1.獲取數據
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]
# 2.模型訓練
# 2.1 實例化一個估計器
estimator = LinearRegression()
# 2.2 使用fit方法進行訓練
estimator.fit(x, y)
# 打印對應的係數:
print("線性迴歸的係數是:\n", estimator.coef_)
# 打印的預測結果是:
print("輸出預測結果:\n", estimator.predict([[100, 80]]))
2.3 數學:求導
1 常見函數的導數
2 導數的四則運算
4 矩陣(向量)求導 [瞭解]
3 小結
- 常見函數的求導方式和導數的四則運算
2.4 線性迴歸的損失和優化
假設剛纔的房子例子,真實的數據之間存在這樣的關係:
真實關係:真實房子價格 = 0.02×中心區域的距離 + 0.04×城市一氧化氮濃度 + (-0.12×自住房平均房價) + 0.254×城鎮犯罪率
那麼現在呢,我們隨意指定一個關係(猜測)
隨機指定關係:預測房子價格 = 0.25×中心區域的距離 + 0.14×城市一氧化氮濃度 + 0.42×自住房平均房價 + 0.34×城鎮犯罪率
請問這樣的話,會發生什麼?真實結果與我們預測的結果之間是不是存在一定的誤差呢?類似這樣樣子
既然存在這個誤差,那我們就將這個誤差給衡量出來
1 損失函數
總損失定義爲:
如何去減少這個損失,使我們預測的更加準確些?既然存在了這個損失,我們一直說機器學習有自動學習的功能,在線性迴歸這裏更是能夠體現。這裏可以通過一些優化方法去優化(其實是數學當中的求導功能)迴歸的總損失!!!
2 優化算法
如何去求模型當中的W,使得損失最小?(目的是找到最小損失對應的W值)
- 線性迴歸經常使用的兩種優化算法
- 正規方程
- 梯度下降法
2.1 正規方程
2.1.1 什麼是正規方程
2.1.2 正規方程求解舉例
以下表示數據爲例:
2.1.3 正規方程的推導
- 推導方式一:
把該損失函數轉換成矩陣寫法:
其中y是真實值矩陣,X是特徵值矩陣,w是權重矩陣
對其求解關於w的最小值,起止y,X 均已知二次函數直接求導,導數爲零的位置,即爲最小值。
求導:
正規方程的另一種推導方式
1.損失表示方式
總損失定義爲:
2.2 梯度下降(Gradient Descent)
2.2.1 什麼是梯度下降
梯度下降法的基本思想可以類比爲一個下山的過程。
假設這樣一個場景:
一個人被困在山上,需要從山上下來(i.e. 找到山的最低點,也就是山谷)。但此時山上的濃霧很大,導致可視度很低。
因此,下山的路徑就無法確定,他必須利用自己周圍的信息去找到下山的路徑。這個時候,他就可以利用梯度下降算法來幫助自己下山。
具體來說就是,以他當前的所處的位置爲基準,尋找這個位置最陡峭的地方,然後朝着山的高度下降的地方走,(同理,如果我們的目標是上山,也就是爬到山頂,那麼此時應該是朝着最陡峭的方向往上走)。然後每走一段距離,都反覆採用同一個方法,最後就能成功的抵達山谷。
梯度下降的基本過程就和下山的場景很類似。
首先,我們有一個可微分的函數。這個函數就代表着一座山。
我們的目標就是找到這個函數的最小值,也就是山底。
根據之前的場景假設,最快的下山的方式就是找到當前位置最陡峭的方向,然後沿着此方向向下走,對應到函數中,就是找到給定點的梯度 ,然後朝着梯度相反的方向,就能讓函數值下降的最快!因爲梯度的方向就是函數值變化最快的方向。 所以,我們重複利用這個方法,反覆求取梯度,最後就能到達局部的最小值,這就類似於我們下山的過程。而求取梯度就確定了最陡峭的方向,也就是場景中測量方向的手段。
2.2.2 梯度的概念
梯度是微積分中一個很重要的概念
-
在單變量的函數中,梯度其實就是函數的微分,代表着函數在某個給定點的切線的斜率;
-
在多變量函數中,梯度是一個向量,向量有方向,梯度的方向就指出了函數在給定點的上升最快的方向;
-
在微積分裏面,對多元函數的參數求∂偏導數,把求得的各個參數的偏導數以向量的形式寫出來,就是梯度。
-
這也就說明了爲什麼我們需要千方百計的求取梯度!我們需要到達山底,就需要在每一步觀測到此時最陡峭的地方,梯度就恰巧告訴了我們這個方向。梯度的方向是函數在給定點上升最快的方向,那麼梯度的反方向就是函數在給定點下降最快的方向,這正是我們所需要的。所以我們只要沿着梯度的反方向一直走,就能走到局部的最低點!
2.2.3 梯度下降舉例
- 1. 單變量函數的梯度下降
- 2.多變量函數的梯度下降
2.2.4 梯度下降(Gradient Descent)公式
1) α是什麼含義?
α在梯度下降算法中被稱作爲學習率或者步長,意味着我們可以通過α來控制每一步走的距離,以保證不要步子跨的太大扯着蛋,哈哈,其實就是不要走太快,錯過了最低點。同時也要保證不要走的太慢,導致太陽下山了,還沒有走到山下。所以α的選擇在梯度下降法中往往是很重要的!α不能太大也不能太小,太小的話,可能導致遲遲走不到最低點,太大的話,會導致錯過最低點!
- 2) 爲什麼梯度要乘以一個負號?
梯度前加一個負號,就意味着朝着梯度相反的方向前進!我們在前文提到,梯度的方向實際就是函數在此點上升最快的方向!而我們需要朝着下降最快的方向走,自然就是負的梯度的方向,所以此處需要加上負號
我們通過兩個圖更好理解梯度下降的過程
所以有了梯度下降這樣一個優化算法,迴歸就有了"自動學習"的能力
-
優化動態圖演示
3 梯度下降和正規方程的對比
3.1 兩種方法對比
梯度下降 | 正規方程 |
---|---|
需要選擇學習率 | 不需要 |
需要迭代求解 | 一次運算得出 |
特徵數量較大可以使用 | 需要計算方程,時間複雜度高O(n3) |
經過前面的介紹,我們發現最小二乘法適用簡潔高效,比梯度下降這樣的迭代法似乎方便很多。但是這裏我們就聊聊最小二乘法的侷限性。
3.2 算法選擇依據:
- 小規模數據:
- 正規方程:LinearRegression(不能解決擬合問題)
- 嶺迴歸
- 大規模數據:
- 梯度下降法:SGDRegressor
經過前面介紹,我們發現在真正的開發中,我們使用梯度下降法偏多(深度學習中更加明顯),下一節中我們會進一步介紹梯度下降法的一些原理。
4 小結
- 損失函數【知道】
- 最小二乘法
- 線性迴歸優化方法【知道】
- 正規方程
- 梯度下降法
- 正規方程 -- 一蹴而就【知道】
- 利用矩陣的逆,轉置進行一步求解
- 只是適合樣本和特徵比較少的情況
- 梯度下降法 — 循序漸進【知道】
- 梯度的概念
- 單變量 -- 切線
- 多變量 -- 向量
- 梯度下降法中關注的兩個參數
- α -- 就是步長
- 步長太小 -- 下山太慢
- 步長太大 -- 容易跳過極小值點(*)
- 爲什麼梯度要加一個負號
- 梯度方向是上升最快方向,負號就是下降最快方向
- α -- 就是步長
- 梯度的概念
- 梯度下降法和正規方程選擇依據【知道】
- 小規模數據:
- 正規方程:LinearRegression(不能解決擬合問題)
- 嶺迴歸
- 大規模數據:
- 梯度下降法:SGDRegressor
- 小規模數據:
2.5 梯度下降方法介紹
上一節中給大家介紹了最基本的梯度下降法實現流程,本節我們將進一步介紹梯度下降法的詳細過算法推導過程和常見的梯度下降算法。
1 詳解梯度下降算法
1.1梯度下降的相關概念複習
在詳細瞭解梯度下降的算法之前,我們先複習相關的一些概念。
1.2 梯度下降法的推導流程
1) 先決條件: 確認優化模型的假設函數和損失函數。
在下面一節中,咱們會詳細講到梯度下降法的變種,他們主要的區別就是對樣本的採用方法不同。這裏我們採用的是用所有樣本。
2 梯度下降法大家族
首先,我們來看一下,常見的梯度下降算法有:
- 全梯度下降算法(Full gradient descent),
- 隨機梯度下降算法(Stochastic gradient descent),
- 小批量梯度下降算法(Mini-batch gradient descent),
- 隨機平均梯度下降算法(Stochastic average gradient descent)
它們都是爲了正確地調節權重向量,通過爲每個權重計算一個梯度,從而更新權值,使目標函數儘可能最小化。其差別在於樣本的使用方式不同。
2.1 全梯度下降算法(FG)
批量梯度下降法,是梯度下降法最常用的形式,具體做法也就是在更新參數時使用所有的樣本來進行更新。
計算訓練集所有樣本誤差,對其求和再取平均值作爲目標函數。
權重向量沿其梯度相反的方向移動,從而使當前目標函數減少得最多。
注意:
-
因爲在執行每次更新時,我們需要在整個數據集上計算所有的梯度,所以批梯度下降法的速度會很慢,同時,批梯度下降法無法處理超出內存容量限制的數據集。
-
批梯度下降法同樣也不能在線更新模型,即在運行的過程中,不能增加新的樣本。
2.2 隨機梯度下降算法(SG)
由於FG每迭代更新一次權重都需要計算所有樣本誤差,而實際問題中經常有上億的訓練樣本,故效率偏低,且容易陷入局部最優解,因此提出了隨機梯度下降算法。
其每輪計算的目標函數不再是全體樣本誤差,而僅是單個樣本誤差,即每次只代入計算一個樣本目標函數的梯度來更新權重,再取下一個樣本重複此過程,直到損失函數值停止下降或損失函數值小於某個可以容忍的閾值。
此過程簡單,高效,通常可以較好地避免更新迭代收斂到局部最優解。其迭代形式爲
但是由於,SG每次只使用一個樣本迭代,若遇上噪聲則容易陷入局部最優解。
2.3 小批量梯度下降算法(mini-batch)
小批量梯度下降算法是FG和SG的折中方案,在一定程度上兼顧了以上兩種方法的優點。
每次從訓練樣本集上隨機抽取一個小樣本集,在抽出來的小樣本集上採用FG迭代更新權重。
被抽出的小樣本集所含樣本點的個數稱爲batch_size,通常設置爲2的冪次方,更有利於GPU加速處理。
特別的,若batch_size=1,則變成了SG;若batch_size=n,則變成了FG.其迭代形式爲
上式中,也就是我們從m個樣本中,選擇x個樣本進行迭代(1<x<m),
2.4 隨機平均梯度下降算法(SAG)
在SG方法中,雖然避開了運算成本大的問題,但對於大數據訓練而言,SG效果常不盡如人意,因爲每一輪梯度更新都完全與上一輪的數據和梯度無關。
隨機平均梯度算法克服了這個問題,在內存中爲每一個樣本都維護一箇舊的梯度,隨機選擇第i個樣本來更新此樣本的梯度,其他樣本的梯度保持不變,然後求得所有梯度的平均值,進而更新了參數。
如此,每一輪更新僅需計算一個樣本的梯度,計算成本等同於SG,但收斂速度快得多。
其迭代形式爲:
- 我們知道sgd是當前權重減去步長乘以梯度,得到新的權重。sag中的a,就是平均的意思,具體說,就是在第k步迭代的時候,我考慮的這一步和前面n-1個梯度的平均值,當前權重減去步長乘以最近n個梯度的平均值。
- n是自己設置的,當n=1的時候,就是普通的sgd。
- 這個想法非常的簡單,在隨機中又增加了確定性,類似於mini-batch sgd的作用,但不同的是,sag又沒有去計算更多的樣本,只是利用了之前計算出來的梯度,所以每次迭代的計算成本遠小於mini-batch sgd,和sgd相當。效果而言,sag相對於sgd,收斂速度快了很多。這一點下面的論文中有具體的描述和證明。
- SAG論文鏈接:https://arxiv.org/pdf/1309.2388.pdf
3 小結
- 全梯度下降算法(FG)【知道】
- 在進行計算的時候,計算所有樣本的誤差平均值,作爲我的目標函數
- 隨機梯度下降算法(SG)【知道】
- 每次只選擇一個樣本進行考覈
- 小批量梯度下降算法(mini-batch)【知道】
- 選擇一部分樣本進行考覈
- 隨機平均梯度下降算法(SAG)【知道】
- 會給每個樣本都維持一個平均值,後期計算的時候,參考這個平均值
梯度下降法算法比較和進一步優化
常見的梯度下降算法有:
- 全梯度下降算法(Full gradient descent),
- 隨機梯度下降算法(Stochastic gradient descent),
- 小批量梯度下降算法(Mini-batch gradient descent),
- 隨機平均梯度下降算法(Stochastic average gradient descent)
它們都是爲了正確地調節權重向量,通過爲每個權重計算一個梯度,從而更新權值,使目標函數儘可能最小化。其差別在於樣本的使用方式不同。
我們通過一個數據集案例進行對比,查看他們的區別
1 算法比較
爲了比對四種基本梯度下降算法的性能,我們通過一個邏輯二分類實驗來說明。本文所用的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收斂效果不穩定的缺點。
2 梯度下降優化算法
以下這些算法主要用於深度學習優化
- 動量法
- 其實動量法(SGD with monentum)就是SAG的姐妹版
- SAG是對過去K次的梯度求平均值
- SGD with monentum 是對過去所有的梯度求加權平均
- Nesterov加速梯度下降法
- 類似於一個智能球,在重新遇到斜率上升時候,能夠知道減速
- Adagrad
- 讓學習率使用參數
- 對於出現次數較少的特徵,我們對其採用更大的學習率,對於出現次數較多的特徵,我們對其採用較小的學習率。
- Adadelta
- Adadelta是Adagrad的一種擴展算法,以處理Adagrad學習速率單調遞減的問題。
- RMSProp
- 其結合了梯度平方的指數移動平均數來調節學習率的變化。
- 能夠在不穩定(Non-Stationary)的目標函數情況下進行很好地收斂。
- Adam
- 結合AdaGrad和RMSProp兩種優化算法的優點。
- 是一種自適應的學習率算法
2.6 線性迴歸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來指定學習率。
- loss:損失類型
- 屬性:
- SGDRegressor.coef_:迴歸係數
- SGDRegressor.intercept_:偏置
sklearn提供給我們兩種實現的API, 可以根據選擇使用
小結
- 正規方程
- sklearn.linear_model.LinearRegression()
- 梯度下降法
- sklearn.linear_model.SGDRegressor()
2.7 案例:波士頓房價預測
1 案例背景介紹
- 數據介紹
給定的這些特徵,是專家們得出的影響房價的結果屬性。我們此階段不需要自己去探究特徵是否有用,只需要使用這些特徵。到後面量化很多特徵需要我們自己去尋找
2 案例分析
迴歸當中的數據大小不一致,是否會導致結果影響較大。所以需要做標準化處理。
- 數據分割與標準化處理
- 迴歸預測
- 線性迴歸的算法效果評估
3 迴歸性能評估
均方誤差(Mean Squared Error)MSE)評價機制:
4 代碼實現
4.1 正規方程
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, random_state=22)
# 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)
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)
return None
4.2 梯度下降法
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, random_state=22)
# 3.特徵工程-標準化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.fit_transform(x_test)
# 4.機器學習-線性迴歸(特徵方程)
estimator = SGDRegressor(max_iter=1000)
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)
return None
我們也可以嘗試去修改學習率
estimator = SGDRegressor(max_iter=1000,learning_rate="constant",eta0=0.1)
此時我們可以通過調參數,找到學習率效果更好的值。
5 小結
- 正規方程和梯度下降法api在真實案例中的使用【知道】
- 線性迴歸性能評估【知道】
- 均方誤差
2.8 欠擬合和過擬合
1 定義
- 過擬合:一個假設在訓練數據上能夠獲得比其他假設更好的擬合, 但是在測試數據集上卻不能很好地擬合數據,此時認爲這個假設出現了過擬合的現象。(模型過於複雜)
- 欠擬合:一個假設在訓練數據上不能獲得更好的擬合,並且在測試數據集上也不能很好地擬合數據,此時認爲這個假設出現了欠擬合的現象。(模型過於簡單)
那麼是什麼原因導致模型複雜?線性迴歸進行訓練學習的時候變成模型會變得複雜,這裏就對應前面再說的線性迴歸的兩種關係,非線性關係的數據,也就是存在很多無用的特徵或者現實中的事物特徵跟目標值的關係並不是簡單的線性關係。
2 原因以及解決辦法
- 欠擬合原因以及解決辦法
- 原因:學習到數據的特徵過少
- 解決辦法:
- 1)添加其他特徵項,有時候我們模型出現欠擬合的時候是因爲特徵項不夠導致的,可以添加其他特徵項來很好地解決。例如,“組合”、“泛化”、“相關性”三類特徵是特徵添加的重要手段,無論在什麼場景,都可以照葫蘆畫瓢,總會得到意想不到的效果。除上面的特徵之外,“上下文特徵”、“平臺特徵”等等,都可以作爲特徵添加的首選項。
- 2)添加多項式特徵,這個在機器學習算法裏面用的很普遍,例如將線性模型通過添加二次項或者三次項使模型泛化能力更強。
- 過擬合原因以及解決辦法
- 原因:原始特徵過多,存在一些嘈雜特徵, 模型過於複雜是因爲模型嘗試去兼顧各個測試數據點
- 解決辦法:
- 1)重新清洗數據,導致過擬合的一個原因也有可能是數據不純導致的,如果出現了過擬合就需要我們重新清洗數據。
- 2)增大數據的訓練量,還有一個原因就是我們用於訓練的數據量太小導致的,訓練數據佔總數據的比例過小。
- 3)正則化
- 4)減少特徵維度,防止維災難
3 正則化
3.1 什麼是正則化
在解決迴歸過擬閤中,我們選擇正則化。但是對於其他機器學習算法如分類算法來說也會出現這樣的問題,除了一些算法本身作用之外(決策樹、神經網絡),我們更多的也是去自己做特徵選擇,包括之前說的刪除、合併一些特徵
在學習的時候,數據提供的特徵有些影響模型複雜度或者這個特徵的數據點異常較多,所以算法在學習的時候儘量減少這個特徵的影響(甚至刪除某個特徵的影響),這就是正則化
注:調整時候,算法並不知道某個特徵影響,而是去調整參數得出優化的結果
3.2 正則化類別
- L2正則化
- 作用:可以使得其中一些W的都很小,都接近於0,削弱某個特徵的影響
- 優點:越小的參數說明模型越簡單,越簡單的模型則越不容易產生過擬合現象
- Ridge迴歸
- L1正則化
- 作用:可以使得其中一些W的值直接爲0,刪除這個特徵的影響
- LASSO迴歸
4 小結
- 欠擬合【掌握】
- 在訓練集上表現不好,在測試集上表現不好
- 解決方法:
- 繼續學習
- 1.添加其他特徵項
- 2.添加多項式特徵
- 繼續學習
- 過擬合【掌握】
- 在訓練集上表現好,在測試集上表現不好
- 解決方法:
- 1.重新清洗數據集
- 2.增大數據的訓練量
- 3.正則化
- 4.減少特徵維度
- 正則化【掌握】
- 通過限制高次項的係數進行防止過擬合
- L1正則化
- 理解:直接把高次項前面的係數變爲0
- Lasso迴歸
- L2正則化
- 理解:把高次項前面的係數變成特別小的值
- 嶺迴歸
向量與矩陣的範數
1.向量的範數
2.矩陣的範數
設:向量,矩陣,例如矩陣A爲:
A=[2, 3, -5, -7;
4, 6, 8, -4;
6, -11, -3, 16];
2.9 正則化線性模型
- Ridge Regression 嶺迴歸
- Lasso 迴歸
- Elastic Net 彈性網絡
- Early stopping
1 Ridge Regression (嶺迴歸,又名 Tikhonov regularization)
嶺迴歸是線性迴歸的正則化版本,即在原來的線性迴歸的 cost function 中添加正則項(regularization term):
以達到在擬合數據的同時,使模型權重儘可能小的目的,嶺迴歸代價函數:
2 Lasso Regression(Lasso 迴歸)
Lasso 迴歸是線性迴歸的另一種正則化版本,正則項爲權值向量的ℓ1範數。
Lasso迴歸的代價函數 :
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 也是正則化迭代學習的方法之一。
其做法爲:在驗證錯誤率達到最小值的時候停止訓練。
5 小結
- Ridge Regression 嶺迴歸
- 就是把係數添加平方項
- 然後限制係數值的大小
- α值越小,係數值越大,α越大,係數值越小
- Lasso 迴歸
- 對係數值進行絕對值處理
- 由於絕對值在頂點處不可導,所以進行計算的過程中產生很多0,最後得到結果爲:稀疏矩陣
- Elastic Net 彈性網絡
- 是前兩個內容的綜合
- 設置了一個r,如果r=0--嶺迴歸;r=1--Lasso迴歸
- Early stopping
- 通過限制錯誤率的閾值,進行停止
2.10 線性迴歸的改進-嶺迴歸
1 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):
2 觀察正則化程度的變化,對結果的影響?
- 正則化力度越大,權重係數會越小
- 正則化力度越小,權重係數會越大
3 波士頓房價預測
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)
4 小結
- sklearn.linear_model.Ridge(alpha=1.0, fit_intercept=True,solver="auto", normalize=False)【知道】
- 具有l2正則化的線性迴歸
- alpha -- 正則化
- 正則化力度越大,權重係數會越小
- 正則化力度越小,權重係數會越大
- normalize
- 默認封裝了,對數據進行標準化處理
price_predict.py
# coding:utf-8
"""
# 1.獲取數據
# 2.數據基本處理
# 2.1 分割數據
# 3.特徵工程-標準化
# 4.機器學習-線性迴歸
# 5.模型評估
"""
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, RidgeCV, Ridge
from sklearn.metrics import mean_squared_error
def linear_model1():
"""
線性迴歸:正規方程
:return:
"""
# 1.獲取數據
boston = load_boston()
# print(boston)
# 2.數據基本處理
# 2.1 分割數據
x_train, x_test, y_train, y_test = train_test_split(boston.data, boston.target, test_size=0.2)
# 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)
print("這個模型的偏置是:\n", estimator.intercept_)
print("這個模型的係數是:\n", estimator.coef_)
# 5.模型評估
# 5.1 預測值
y_pre = estimator.predict(x_test)
# print("預測值是:\n", y_pre)
# 5.2 均方誤差
ret = mean_squared_error(y_test, y_pre)
print("均方誤差:\n", ret)
def linear_model2():
"""
線性迴歸:梯度下降法
:return:
"""
# 1.獲取數據
boston = load_boston()
# print(boston)
# 2.數據基本處理
# 2.1 分割數據
x_train, x_test, y_train, y_test = train_test_split(boston.data, boston.target, test_size=0.2)
# 3.特徵工程-標準化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.fit_transform(x_test)
# 4.機器學習-線性迴歸
# estimator = SGDRegressor(max_iter=1000, learning_rate="constant", eta0=0.001)
estimator = SGDRegressor(max_iter=1000)
estimator.fit(x_train, y_train)
print("這個模型的偏置是:\n", estimator.intercept_)
print("這個模型的係數是:\n", estimator.coef_)
# 5.模型評估
# 5.1 預測值
y_pre = estimator.predict(x_test)
# print("預測值是:\n", y_pre)
# 5.2 均方誤差
ret = mean_squared_error(y_test, y_pre)
print("均方誤差:\n", ret)
def linear_model3():
"""
線性迴歸:嶺迴歸
:return:None
"""
# 1.獲取數據
boston = load_boston()
# print(boston)
# 2.數據基本處理
# 2.1 分割數據
x_train, x_test, y_train, y_test = train_test_split(boston.data, boston.target, test_size=0.2)
# 3.特徵工程-標準化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.fit_transform(x_test)
# 4.機器學習-線性迴歸
# estimator = Ridge(alpha=1.0)
estimator = RidgeCV(alphas=(0.001, 0.01, 0.1, 1, 10, 100))
estimator.fit(x_train, y_train)
print("這個模型的偏置是:\n", estimator.intercept_)
print("這個模型的係數是:\n", estimator.coef_)
# 5.模型評估
# 5.1 預測值
y_pre = estimator.predict(x_test)
# print("預測值是:\n", y_pre)
# 5.2 均方誤差
ret = mean_squared_error(y_test, y_pre)
print("均方誤差:\n", ret)
if __name__ == '__main__':
linear_model1()
linear_model2()
linear_model3()
2.11 模型的保存和加載
1 sklearn模型的保存和加載API
- from sklearn.externals import joblib
- 保存:joblib.dump(estimator, 'test.pkl')
- 加載:estimator = joblib.load('test.pkl')
2 線性迴歸的模型保存加載案例
def load_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)
x_test = transfer.fit_transform(x_test)
# 4.機器學習-線性迴歸(嶺迴歸)
# # 4.1 模型訓練
# estimator = Ridge(alpha=1)
# estimator.fit(x_train, y_train)
#
# # 4.2 模型保存
# joblib.dump(estimator, "./data/test.pkl")
# 4.3 模型加載
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_)
# 5.2 評價
# 均方誤差
error = mean_squared_error(y_test, y_predict)
print("誤差爲:\n", error)
3 小結
- sklearn.externals import joblib【知道】
- 保存:joblib.dump(estimator, 'test.pkl')
- 加載:estimator = joblib.load('test.pkl')
- 注意:
- 1.保存文件,後綴名是**.pkl
- 2.加載模型是需要通過一個變量進行承接
model_dump_load.py
# coding:utf-8
# coding:utf-8
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, RidgeCV, Ridge
from sklearn.metrics import mean_squared_error
from sklearn.externals import joblib
def dump_load():
"""
模型保存和加載
:return:None
"""
# 1.獲取數據
boston = load_boston()
# print(boston)
# 2.數據基本處理
# 2.1 分割數據
x_train, x_test, y_train, y_test = train_test_split(boston.data, boston.target, random_state=22, test_size=0.2)
# 3.特徵工程-標準化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.fit_transform(x_test)
# # 4.機器學習-線性迴歸
# # 4.1 模型訓練
# # estimator = Ridge(alpha=1.0)
# estimator = RidgeCV(alphas=(0.001, 0.01, 0.1, 1, 10, 100))
# estimator.fit(x_train, y_train)
#
# # 4.2 模型保存
# joblib.dump(estimator, "./data/test.pkl")
# 4.3 模型加載
estimator = joblib.load("./data/test.pkl")
print("這個模型的偏置是:\n", estimator.intercept_)
print("這個模型的係數是:\n", estimator.coef_)
# 5.模型評估
# 5.1 預測值
y_pre = estimator.predict(x_test)
# print("預測值是:\n", y_pre)
# 5.2 均方誤差
ret = mean_squared_error(y_test, y_pre)
print("均方誤差:\n", ret)
if __name__ == '__main__':
dump_load()