邏輯迴歸實戰,一文把理論和實踐結合

背景

解決的二分類問題,如手寫識別0-9 html

目標:邏輯迴歸返回一個機率值[0-1]python

邏輯迴歸的特色:快、效果好、容易實時在線預測、利於分析算法

方法:定義一個條件機率,如p(Y|X)至關於用模型來捕獲輸入X和輸出Y之間的關係,如數組

邏輯迴歸實戰,一文把理論和實踐結合

推導

對於二分類問題,因爲p(Y|X)的值域在[-∞,+∞],爲了令其至於範圍壓縮到[-1,1]之間,故推薦使用sigmoid函數,故得
邏輯迴歸實戰,一文把理論和實踐結合
兩式子合併,可得
邏輯迴歸實戰,一文把理論和實踐結合網絡

關於使用sigmoid

前面說道使用該函數是因爲其定義域是[-∞,+∞],且值域是[-1,1]故選擇該函數,這樣的說法其實並不能服衆,畢竟probit也具備相同的性質。事實上選用sigmoid的意義在於,指數族分佈exponential family所具備的最佳(即maximum entropy 最大熵)性質機器學習

熵本來是信息論中的概念,用在機率分佈上能夠表示這個分佈中所包含的不肯定度,熵越大不肯定度越大。因此你們能夠想象到,均勻分佈熵最大,由於基本新數據是任何值的機率都均等。ide

而咱們如今關心的是,給定某些假設以後,熵最大的分佈。也就是說這個分佈應該在知足我假設的前提下越均勻越好。好比你們熟知的正態分佈,正是假設已知meanvariance後熵最大的分佈。此時回過來看logistic regression,這裏假設了什麼呢?函數

  1. 在建模預測 Y|X,並認爲 Y|X 服從貝努力分佈(bernoulli distribution),因此咱們只須要知道 P(Y|X)
  2. 須要一個線性模型,因此 P(Y|X) = f(wx+b)。接下來咱們就只須要知道 f 是什麼就好了。而咱們能夠經過最大熵原則推出的這個 f,就是sigmoid。

bernoulliexponential family形式,以下
邏輯迴歸實戰,一文把理論和實踐結合學習

決策邊界 decision boundary

所謂決策邊界就是可以把樣本正確分類的一條邊界,在這個分類點上,大於這個邊界點,分類爲1,小於這個邊界點,主要有線性決策邊界(linear decision boundaries)和非線性決策邊界(non-linear decision boundaries)。注意:決策邊界是假設函數的屬性,由參數決定,而不是由數據集的特徵決定。測試

經過該指標是用來判斷是否是線性分類器,LR是線性分類器,證實以下
邏輯迴歸實戰,一文把理論和實踐結合

注意到w^T x+b=0也表明一條直線,不妨假設X有兩個特徵x1,x2,那麼有w1x1+w2x2+b=0

經過決策邊界,咱們將構造目標函數,其意義在於,最大化似然。即最大化咱們見到的是樣本數據機率,反過來思考,至關於咱們見到的樣本和數據,就是咱們將來獲得的模型產生的。LR的目標函數是凸函數

好比說,咱們擁有數據集:
邏輯迴歸實戰,一文把理論和實踐結合
前面咱們獲得
邏輯迴歸實戰,一文把理論和實踐結合

能夠獲得最大化目標函數:
邏輯迴歸實戰,一文把理論和實踐結合
其計算過程以下:
邏輯迴歸實戰,一文把理論和實踐結合

爲了高效求極值這個時候就須要使用梯度降低

梯度降低

邏輯迴歸實戰,一文把理論和實踐結合

梯度降低算法Gradient Descent Optimization是神經網絡模型訓練最經常使用的優化算法。對於深度學習模型,基本都是採用梯度降低算法來進行優化訓練的。梯度降低算法背後的原理:目標函數 J(θ) 關於參數 θ 的梯度將是損失函數loss function 上升最快的方向。而咱們要最小化loss,只須要將參數沿着梯度相反的方向前進一個步長,就能夠實現目標函數loss function的降低。這個步長 η 又稱爲學習速率。其特色是穩定,但必定能夠找到全局最優。參數更新公式以下:
邏輯迴歸實戰,一文把理論和實踐結合

其中 ∇J(θ) 是參數的梯度,根據計算目標函數採用數據量的不一樣,梯度降低算法又能夠分爲批量梯度降低算法Batch Gradient Descent,隨機梯度降低算法Stochastic Gradient Descent和小批量梯度降低算法Mini-batch Gradient Descent。對於批量梯度降低算法,其 J(θ) 是在整個訓練集上計算的,若是數據集比較大,可能會面臨內存不足問題,並且其收斂速度通常比較慢。隨機梯度降低算法是另一個極端, J(θ) 是針對訓練集中的一個訓練樣本計算的,又稱爲在線學習,即獲得了一個樣本,就能夠執行一次參數更新。因此其收斂速度會快一些,可是有可能出現目標函數值震盪現象,由於高頻率的參數更新致使了高方差。小批量梯度降低算法是折中方案,選取訓練集中一個小批量樣本(通常是2的倍數,如32,64,128等)計算,這樣能夠保證訓練過程更穩定,並且採用批量訓練方法也能夠利用矩陣計算的優點。這是目前最經常使用的梯度降低算法。

導數與梯度

下面是計算函數梯度的一個例子:
邏輯迴歸實戰,一文把理論和實踐結合
其中∇稱爲梯度算子,它做用於一個多元函數,獲得一個向量。

一維度的純量x的梯度,一般用f'(x)表示。

多維度的向量x的梯度,一般用∇f(x)表示。

也就是說一維的純量x的梯度就是算f(x)對x的微分,多維的向量x的梯度就是算f(x)對x全部元素的偏微分

例如:
邏輯迴歸實戰,一文把理論和實踐結合
假設咱們的x有兩個維度的參數,梯度就分別須要對不一樣維度的參數作偏微分
邏輯迴歸實戰,一文把理論和實踐結合
可導函數在某一點處取得極值的必要條件是梯度爲0,梯度爲0的點稱爲函數的駐點,這是疑似極值點。須要注意的是,梯度爲0只是函數取極值的必要條件而不是充分條件,即梯度爲0的點可能不是極值點。至因而極大值仍是極小值,要看二階導數

注意求導

在這裏咱們可能會問:直接求函數的導數(梯度),而後令導數(梯度)爲0,解方程,問題不就解決了嗎?事實上沒這麼簡單,由於這個方程可能很難解。好比下面的函數:
邏輯迴歸實戰,一文把理論和實踐結合
咱們分別對x和y求偏導數,並令它們爲0,獲得下面的方程組:
邏輯迴歸實戰,一文把理論和實踐結合
這個方程很是難以求解,對於有指數函數,對數函數,三角函數的方程,咱們稱爲超越方程,求解的難度並不比求極值自己小。

求解

精確的求解不太可能,所以只能求近似解,這稱爲數值計算。工程上實現時一般採用的是迭代法,它從一個隨機初始點 X0 開始,反覆使用某種規則從 Xk 移動到下一個點 X k+1 ,構造這樣一個數列,直到收斂到梯度爲0的點處。即有下面的極限成立:
邏輯迴歸實戰,一文把理論和實踐結合
這些規則通常會利用一階導數信息即梯度;或者二階導數信息Hessian矩陣。這樣迭代法的核心是獲得這樣的由上一個點肯定下一個點的迭代公式:
邏輯迴歸實戰,一文把理論和實踐結合
這個過程就像咱們處於山上的某一位置,要到山底找水喝,所以咱們必須到達最低點處:
邏輯迴歸實戰,一文把理論和實踐結合

此時咱們沒有全局信息,根本就不知道哪裏是地勢最低的點,只能想辦法往山下走,走 一步看一步。剛開始咱們在山上的某一點處,每一步,咱們都往地勢更低的點走,以指望能走到山底。

Hessian矩陣,一個多元函數的二階偏導數構成的方陣,描述了函數的局部曲率。黑塞矩陣最先於19世紀由德國數學家Ludwig Otto Hesse提出,並以其名字命名。黑塞矩陣經常使用於牛頓法解決優化問題,利用黑塞矩陣可斷定多元函數的極值問題。在工程實際問題的優化設計中,所列的目標函數每每很複雜,爲了使問題簡化,經常將目標函數在某點鄰域展開成泰勒多項式來逼近原函數,此時函數在某點泰勒展開式的矩陣形式中會涉及到黑塞矩陣。

若是Hessian矩陣正定,函數有極小值
若是Hessian矩陣負定,函數有極大值
若是Hessian矩陣不定,則不是極值點(鞍點)
這和一元函數的結果相似,Hessian矩陣能夠看作是一元函數的二階導數對多元函數的推廣。一元函數的極值判別法爲,假設在某點處導數等於0,則:

若是二階導數大於0,函數有極小值
若是二階導數小於0,函數有極大值
若是二階導數等於0,狀況不定

存在惟一解

利用如下函數測試梯度降低法,固然了多維度也是如此

邏輯迴歸實戰,一文把理論和實踐結合

這個例子基本上學習率能夠不用過小,就能夠很快就找到解,後面有跑不一樣學習率看幾回能夠得出近似解。
邏輯迴歸實戰,一文把理論和實踐結合
剛纔提到咱們須要先設定一個初始化的「解」,此例不妨設x(0)=20(故意跟最佳值有差距)

注意:紅色線是法線,藍色線是切線,法線和切線這兩條線是垂直的,但由於x軸和y軸刻度不同,因此看不出來它是垂直的。

邏輯迴歸實戰,一文把理論和實踐結合

邏輯迴歸實戰,一文把理論和實踐結合

邏輯迴歸實戰,一文把理論和實踐結合

邏輯迴歸實戰,一文把理論和實踐結合

從這四個圖咱們能夠發現學習率對求解影響很大,學習率過低,須要更新不少次才能到最佳解,學習率過高,有可能會形成梯度走不進去局部極值(雖然也能夠擺脫局部極值的問題)。尤爲是當學習率是1的時候,基本上梯度降低法根本走不到局部極小值,一直在左右對跳,因此最優解有不少衍生的方式或更先進的方式去解決這些問題。好比批量梯度降低算法Batch Gradient Descent,隨機梯度降低算法Stochastic Gradient Descent和小批量梯度降低算法Mini-batch Gradient Descent

推導

咱們來看一元函數的泰勒展開,以便於更好的理解多元函數的泰勒展開。假設一個一元函數n階可導,它的泰勒展開式爲:
邏輯迴歸實戰,一文把理論和實踐結合
若是在某一點處導數值大於0(+),則函數在此處是增函數,加大x的值函數值會增長,減少x的值(-)函數會減少。相反的,若是在某一點處導數值小於0(-),則函數是減函數,增長x的值函數值會減少(+),減少x的值函數會增長。所以咱們能夠得出一個結論:若是x的變化很小,而且變化值與導數值反號,則函數值降低。對於一元函數,x的變化只有兩個方向,要麼朝左,要麼朝右。

下面咱們把這一結論推廣到多元函數的狀況。多元函數 f(x) 在x點處的泰勒展開爲:
邏輯迴歸實戰,一文把理論和實踐結合
這裏咱們忽略了二次及更高的項。其中,一次項是梯度向量∇f(x)與自變量增量Δx的內積(∇f(x))^T Δx,這等價於一元函數的 f'(x0)(x-x0) 。這樣,函數的增量與自變量的增量Δx 、函數梯度的關係能夠表示爲:
邏輯迴歸實戰,一文把理論和實踐結合
若是Δx足夠小,在x的某一鄰域內,則咱們能夠忽略二次及以上的項,則有:
邏輯迴歸實戰,一文把理論和實踐結合
這裏的狀況比一元函數複雜多了,是一個向量,Δx有無窮多種方向,若是能保證:
邏輯迴歸實戰,一文把理論和實踐結合
則有:
邏輯迴歸實戰,一文把理論和實踐結合

令函數值遞減,這就是下山的正確方向。由於有:
邏輯迴歸實戰,一文把理論和實踐結合
此時,||·||表示向量的模, θ 是向量 ∇f(x) 和 Δx 的夾角。由於向量的模必定大於等於0,若是
邏輯迴歸實戰,一文把理論和實踐結合
只有當:
邏輯迴歸實戰,一文把理論和實踐結合
時 cos θ 有極小值-1,此時梯度和 Δx 反向,即夾角爲180度。所以當向量 Δx 的模大小必定時,當:
邏輯迴歸實戰,一文把理論和實踐結合
即在梯度相反的方向函數值降低的最快。此時有:
邏輯迴歸實戰,一文把理論和實踐結合
函數的降低值爲:
邏輯迴歸實戰,一文把理論和實踐結合
只要梯度不爲0,往梯度的反方向走函數值必定是降低的。直接用 Δx=-∇f(x) 可能會有問題,由於 x+ Δx 可能會超出x的鄰域範圍以外,此時是不能忽略泰勒展開中的二次及以上的項的,所以步伐不能太大。通常設:
邏輯迴歸實戰,一文把理論和實踐結合
其中 α 爲一個接近於0的正數,稱爲步長,由人工設定,用於保證 x+ Δx 在x的鄰域內,從而能夠忽略泰勒展開中二次及更高的項,則有:
邏輯迴歸實戰,一文把理論和實踐結合
從初始點 X0 開始,使用以下迭代公式:
邏輯迴歸實戰,一文把理論和實踐結合
只要沒有到達梯度爲0的點,則函數值會沿着序列 Xk 遞減,最終會收斂到梯度爲0的點,這就是梯度降低法。迭代終止的條件是函數的梯度值爲0(實際實現時是接近於0),此時認爲已經達到極值點。注意咱們找到的是梯度爲0的點,這不必定就是極值點,後面會說明。梯度降低法只須要計算函數在某些點處的梯度,實現簡單,計算量小。

實現細節問題

在訓練的過程當中難免會遇到一些細節的問題,最基本的就是調參了

初始值的設定

通常的,對於不帶約束條件的優化問題,咱們能夠將初始值設置爲0,或者設置爲隨機數,對於神經網絡的訓練,通常設置爲隨機數,這對算法的收斂相當重要

學習率的設定

學習率設置爲多少,也是實現時須要考慮的問題。最簡單的,咱們能夠將學習率設置爲一個很小的正數,如0.001。另外,能夠採用更復雜的策略,在迭代的過程當中動態的調整學習率的值。好比前1萬次迭代爲0.001,接下來1萬次迭代時設置爲0.0001。

面臨的問題

這個是實際上是要基於業務來考慮的,由於在現實層面上,局部極值不可避免

局部極小值

有些函數可能有多個局部極小值點,下面是一個例子:
邏輯迴歸實戰,一文把理論和實踐結合

這張圖中的函數有3個局部極值點,分別是A,B和C,但只有A纔是全局極小值,梯度降低法可能迭代到B或者C點處就終止。

存在局部最小值

設計一個有局部極小值和全域極小值的函數,到四次方,如令x=10,函數的值就很大
邏輯迴歸實戰,一文把理論和實踐結合
咱們須要先設定一個初始化的「解」,此例我設定x(0)=-20(故意跟最佳值有差距)
邏輯迴歸實戰,一文把理論和實踐結合
能夠看到學習率過小,初始值很差,解就會掉到局部極小值。
邏輯迴歸實戰,一文把理論和實踐結合
當學習率爲0.0004對此例子來講,雖然步伐夠大跳出了局部極值,但到全域極值時,由於步伐太大,因此走不到最好的值。
邏輯迴歸實戰,一文把理論和實踐結合

這個學習率(0.0003)對此例子來講就夠了,能夠走到全域極值。

鞍點

鞍點是指梯度爲0,Hessian矩陣既不是正定也不是負定,即不定的點。下面是鞍點的一個例子,假設有函數:
邏輯迴歸實戰,一文把理論和實踐結合
顯然在(0, 0)這點處不是極值點,但梯度爲0,下面是梯度降低法的運行結果:
邏輯迴歸實戰,一文把理論和實踐結合
在這裏,梯度降低法遇到了鞍點,認爲已經找到了極值點,從而終止迭代過程,而這根本不是極值點。

對於怎麼逃離局部極小值點和鞍點,有一些解決方案,在這裏咱們暫時不細講,之後有機會再專門寫文章介紹。對於凸優化問題,不會遇到上面的局部極小值與鞍點問題,即梯度降低法必定能找到全局最優解。凸優化的概念將在SIGAI後續的文章中介紹。

沒有極值

雖說微分能夠找極值,但不少函數既無最大值,也無最小值,由於函數的長相彎彎曲曲不少次,有局部極值或鞍部,因此一次微分等於0求得的多是極值,也能夠是相對極值。好比這個例子
邏輯迴歸實戰,一文把理論和實踐結合
這個方程式能夠找到極值「解」讓f(x)最小即f(x)=16,但這個值真的是最小嗎?
不妨找個點隨便代入,如

邏輯迴歸實戰,一文把理論和實踐結合

這個值比微分的最佳解還要小,因此能夠得知微分等於0找到的不必定是最佳解,因此用梯度降低法,能夠找到更好的解。

下圖我將上式子畫出來它的座標跟微分解還有梯度法如何讓解更新。
邏輯迴歸實戰,一文把理論和實踐結合
這邊我只跑100次,由於解在無窮大的地方,但能夠看到loss值不斷在變小中。

總結步驟

邏輯迴歸實戰,一文把理論和實踐結合

步驟概括

最小化F(w)

  1. 設置初始w,計算F(w)
  2. 計算梯度∇F(w)
    降低方向:dir = -∇F(w)
  3. 嘗試梯度更新
    w new = w + 步長 ∗ dir 獲得降低後的 w new和F(w new)
  4. 若是 F(w new)-F(W)較小,中止; 不然 w=w; F(w)=F(w new)跳到第2步

隨機梯度降低法

對於有些機器學習問題,咱們的目標函數是對樣本的損失函數。假設訓練樣本集有N個樣本,訓練時優化的目標是這個數據集上的平均損失函數:
邏輯迴歸實戰,一文把理論和實踐結合
其中L(w,xi,yi) 是對單個訓練樣本 (xi,yi) 的損失函數,w是須要學習的參數。若是訓練時每次都用全部樣本計算梯度並更新,成本過高,做爲改進能夠在每次迭代時選取一批樣本,將損失函數定義在這些樣本上。

批量隨機梯度降低法在每次迭代中使用上面目標函數的隨機逼近值,即只使用 M\<-N 個樣原本近似計算損失函數。在每次迭代時要優化的目標函數變爲:
邏輯迴歸實戰,一文把理論和實踐結合
已經證實,隨機梯度降低法在數學指望的意義下收斂,即隨機採樣產生的梯度的指望值是真實的梯度。由於每次迭代時的目標函數其實是不同的,所以隨機梯度降低法並不能保證每次迭代時函數值必定降低。

  • 每次從訓練樣本中抽取一個樣本進行更新, 每次都不用遍歷全部數據集,迭代速度快, 須要迭代更屢次數
  • 每次選取方向不必定是最優

邏輯迴歸實戰,一文把理論和實踐結合
批量梯度降低和隨機梯度降低,折中的方法:Mini-batch Gradent Descen

正則化項

從上文可知,
邏輯迴歸實戰,一文把理論和實踐結合
當w變得很是大的時候,咱們會發現p(y=1|x,w)≈1,p(y=0|x,w)≈0,這是很是理想的狀況,而此時就出現了所謂過擬合現象

事實上在擬閤中會出現過擬合和欠擬合兩種現象

  • 欠擬合
    • 模型沒有很好的捕捉到數據特徵
    • 學習不充分,致使沒有很好擬合
    • 方案
      • 模型複雜化
      • 增長訓練輪數
  • 過擬合
    • 過分訓練,增強了對噪聲學習
    • 過分擬合樣本,泛化性差
    • 方案
      • 交叉驗證
      • 增長數據
      • 特徵篩選
      • 正則化

帶着問題出發:

  • 正則項存在的意義是什麼,爲何要使用正則項?正則項是如何防止過擬合的?
  • 有哪幾種正則項,如何表示,它們的相同點和不一樣點是什麼?
  • 不一樣正則項的使用場景是什麼,如何選取正則項呢?

爲何要使用正則化項

其實正則化項是對參數的控制。其目的主要有兩個

  1. 實現參數的稀疏,這樣能夠簡化模型,避免過擬合。在一個模型中重要的特徵並非不少,若是考慮全部的特徵都是有做用的,那麼就會對訓練集進行充分的擬合,致使在測試集的表現並非很好,因此咱們須要稀疏參數,簡化模型。
  2. 儘量保證參數小一些,這又是爲啥呢?由於越是複雜的模型,它會對全部的樣本點進行擬合,若是在這裏包含異常的樣本,就會在小區間內產生很大的波動,不一樣於平均水平的高點或者低點,這樣的話,會致使其導數很大,咱們知道在多項式導數中,只有參數很是大的時候,纔會產生較大的導數,因此模型越複雜,參數值也就越大。爲了不這種過分的擬合,須要控制參數值的大小。

總而言之,避免w過大,L1正則化和L2正則化上能夠看作是損失函數的懲罰

正則項的分類

正則項有三種:L0、L一、L2

  • L0正則化的值是模型參數中非零參數的個數。
  • L1正則化表示各個參數絕對值之和。
  • L2正則化標識各個參數的平方的和的開方值。

L0正則化

保證參數稀疏化來防止過擬合,能夠用非零參數,來進行特徵選擇。可是L0正則化很差求,所以採用L1正則化。L1正則化是L0正則化的最優凸近似,比L0容易求解,而且能夠實現稀疏的效果。

L1正則化

L1正則化能夠產生稀疏權值矩陣,即產生一個稀疏模型,能夠用於特徵選擇

L1正則化也叫lasso,它每每是替代L0正則化來防止過擬合的。爲啥用L1範數,由於L1範數就==是各個參數的絕對值相加==,咱們已知,參數的值的大小和模型的複雜度是成正比的,所以複雜模型,L1範數就會大,致使損失函數大。下面定量的分析:

在原始的代價函數後面加上一個L1正則化項,即全部權重w的絕對值的和,乘以λ/n。以下:
邏輯迴歸實戰,一文把理論和實踐結合
計算導數得:
邏輯迴歸實戰,一文把理論和實踐結合
上式中sgn(w)表示w的符號。那麼權重w的更新規則爲:
邏輯迴歸實戰,一文把理論和實踐結合

如今來觀察正則求導項,可知當w爲正時,更新後的w變小;當w爲負時,更新後的w變大。所以它的效果就是讓w往0靠,使網絡中的權重儘量爲0,也就至關於減少了網絡複雜度,防止過擬合。另外,上面沒有提到一個問題,當w爲0時怎麼辦?當w等於0時,|w|是不可導的,因此咱們只能按照原始的未經正則化的方法去更新w,這就至關於去掉ηλsgn(w)/n這一項,因此咱們能夠規定sgn(0)=0,這樣就把w=0的狀況也統一進來了。

注意到L1正則化是權值的絕對值之和,J是帶有絕對值符號的函數,所以J是不徹底可微的。機器學習的任務就是要經過一些方法(好比梯度降低)求出損失函數的最小值。考慮二維的狀況,即只有兩個權值w1和w2,此時L=|w1|+|w2|,對於梯度降低法,求解J的過程能夠畫出等值線,同時L1正則化的函數L也能夠在w1w2的二維平面上畫出來。以下圖:

邏輯迴歸實戰,一文把理論和實踐結合
在圖中,當J等值線與L首次相交的地方就是最優解。上圖中J與L在L的一個頂點處相交,這個頂點就是最優解。注意到這個頂點的值是(w1,w2)=(0,w)。能夠直觀想象,由於L函數有不少突出的角(二維狀況下四個,多維狀況下更多),J與這些角接觸的機率會遠大於與L其它部位接觸的機率,而在這些角上,會有不少權值等於0,這就是爲何L1正則化能夠產生稀疏模型,進而能夠用於特徵選擇。

L2正則化

L2正則化能夠防止模型過擬合(overfitting);必定程度上,L1也能夠防止過擬合

L2正則化也是防止過擬合的,緣由和L1同樣同樣的,就是形式不一樣。L2範數是各參數的平方和再求平方根。對於L2的每一個元素都很小,可是不會爲0,只是接近0,參數越小說明模型越簡單,也就越不容易產生過擬合。L2正則化也叫作「嶺迴歸」。

來讓咱們看看具體的例子,對於房屋價格預測咱們可能有上百種特徵,與剛剛所講的多項式例子不一樣,咱們並不知道 哪些是高階多項式的項。因此,若是咱們有一百個特徵,咱們並不知道如何選擇關聯度更好的參數,如何縮小參數的數目等等。所以在正則化裏,咱們要作的事情,就是把減少咱們的代價函數(例子中是線性迴歸的代價函數)全部的參數值,由於咱們並不知道是哪個或哪幾個要去縮小。所以,咱們須要修改代價函數,在這後面添加一項,就像咱們在方括號裏的這項。當咱們添加一個額外的正則化項的時候,咱們收縮了每一個參數。

爲何加了一項就讓參數儘可能小呢,由於只要你想讓J最小,那麼θ確定儘量的去小。

如今進行定量的分析:

L2正則化就是在代價函數後面再加上一個正則化項:
邏輯迴歸實戰,一文把理論和實踐結合

C0表明原始的代價函數,後面那一項就是L2正則化項,它是這樣來的:全部參數w的平方的和,除以訓練集的樣本大小n。λ就是正則項係數,權衡正則項與C0項的比重。另外還有一個係數1/2,1/2常常會看到,主要是爲了後面求導的結果方便,後面那一項求導會產生一個2,與1/2相乘恰好湊整。L2正則化項是怎麼避免overfitting的呢?咱們推導一下看看,先求導:
邏輯迴歸實戰,一文把理論和實踐結合
能夠發現L2正則化項對b的更新沒有影響,可是對於w的更新有影響:

邏輯迴歸實戰,一文把理論和實踐結合
在不使用L2正則化時,求導結果中w前係數爲1,如今w前面係數爲 1-ηλ/n ,由於η、λ、n都是正的,在樣本量充足的時候,1-ηλ/n小於1,它的效果是減少w,這也就是權重衰減的由來。固然考慮到後面的導數項,w最終的值可能增大也可能減少。

同理,假設有以下帶L2正則化的損失函數,一樣能夠畫出他們在二維平面上的圖形,以下:
邏輯迴歸實戰,一文把理論和實踐結合

L2正則化二維平面下L2正則化的函數圖形是個圓,與方形相比,被磨去了棱角。所以J與L相交時使得w1或w2等於零的機率小了許多,這就是爲何L2正則化不具備稀疏性的緣由。

總結

L1會趨向於產生少許的特徵,而其餘的特徵都是0,而L2會選擇更多的特徵,這些特徵都會接近於0。Lasso在特徵選擇時候很是有用,而Ridge就只是一種規則化而已。在全部特徵中只有少數特徵起重要做用的狀況下,選擇Lasso比較合適,由於它能自動選擇特徵。而若是全部特徵中,大部分特徵都能起做用,並且起的做用很平均,那麼使用Ridge也許更合適。

理論聯繫實際

接下來咱們將利用一些私有的脫敏數據進行試驗,邏輯迴歸以及正則化項

邏輯迴歸

加載數據

def loaddata(file, delimeter):
    data = np.loadtxt(file, delimiter=delimeter)
    print('Dimensions: ',data.shape)
    print(data[:5,:])
    return(data)

data = loaddata('./data/sample_1.txt', ',')

整理訓練樣本

np.c_是按行鏈接兩個矩陣,就是把兩矩陣左右相加,要求行數相等,這麼作的目的在於能夠將b擴展進矩陣中

X = np.c_[np.ones((data.shape[0],1)), data[:,0:2]]
y = np.c_[data[:,2]]

而容許這麼擴展的原理在於
邏輯迴歸實戰,一文把理論和實踐結合

可視化數據
```python
def plotData(data, label_x, label_y, label_pos, label_neg, axes=None):
    # 得到正負樣本的下標(即哪些是正樣本,哪些是負樣本)
    neg = data[:,2] == 0
    pos = data[:,2] == 1

    if axes == None:
        axes = plt.gca() # 獲取圖的座標信息

    axes.scatter(data[pos][:,0], data[pos][:,1], marker='*', c='r', s=30, linewidth=2, label=label_pos)
    axes.scatter(data[neg][:,0], data[neg][:,1], c='c', s=30, label=label_neg)
    axes.set_xlabel(label_x)
    axes.set_ylabel(label_y)
    axes.legend(frameon= True, fancybox = True);

plotData(data, 'English', 'Math', 'Pass', 'Fail')

邏輯迴歸實戰,一文把理論和實踐結合
接下來則是開始訓練數據,首先是定義sigmoid函數

def sigmoid(z):
    return(1 / (1 + np.exp(-z)))

接下來定義損失函數,也就是偏差函數,即前文咱們提到的

邏輯迴歸實戰,一文把理論和實踐結合

def lossFunction(theta, X, y):
    m = y.size
    h = sigmoid(X.dot(theta))
    J = -1.0*(1.0/m)*(np.log(h).T.dot(y)+np.log(1-h).T.dot(1-y))

    if np.isnan(J[0]):
        return(np.inf)
    return J[0]

接着定義梯度降低函數

def gradient(theta, X, y):
    m = y.size
    h = sigmoid(X.dot(theta.reshape(-1,1)))

    grad =(1.0/m)*X.T.dot(h-y)

    return(grad.flatten())

即便用X的特徵和權重相乘而獲得預測值h,以後預測值減去真實值再乘x,也就是前文所說推導的公式
邏輯迴歸實戰,一文把理論和實踐結合
此時,咱們已然準備好了相關的函數,如今須要初始化函數由於不知道最優參數是啥,故直接用np.zeros初始化爲0

initial_theta = np.zeros(X.shape[1])
loss = lossFunction(initial_theta, X, y)
grad = gradient(initial_theta, X, y)
print('Loss: \n', loss)
print('Grad: \n', grad)

獲得結果,這個至關於作了一輪的迭代
邏輯迴歸實戰,一文把理論和實踐結合
爲了執行多輪迭代,咱們須要使用minimize函數

res = minimize(lossFunction, initial_theta, args=(X,y), jac=gradient, options={'maxiter':400})
print(res)

獲得結果

邏輯迴歸實戰,一文把理論和實踐結合

其中x: array([-25.16131634, 0.2062316 , 0.20147143])第一個參數是他的偏置,後面兩個參數則是對應X的第一列和第二列的特徵

最後對結果進行預測

def predict(theta, X, threshold=0.5):
    p = sigmoid(X.dot(theta.T)) >= threshold
    return(p.astype('int'))

sigmoid(np.array([1, 81, 57]).dot(res.x.T))

獲得一個值,0.9537929840904646能夠認爲接近於1,預測是準確的,以後可視化處理

plt.scatter(81, 57, s=60, c='y', marker='v', label='(81, 57)')
plotData(data, 'English', 'Math', 'Pass', 'Fail')
x1_min, x1_max = X[:,1].min(), X[:,1].max(),
x2_min, x2_max = X[:,2].min(), X[:,2].max(),
xx1, xx2 = np.meshgrid(np.linspace(x1_min, x1_max), np.linspace(x2_min, x2_max))

print(xx1.shape)

h = sigmoid(np.c_[np.ones((xx1.ravel().shape[0],1)), xx1.ravel(), xx2.ravel()].dot(res.x.T))
h = h.reshape(xx1.shape)
plt.contour(xx1, xx2, h, 1, linewidths=1, colors='b');

邏輯迴歸實戰,一文把理論和實踐結合

minimize函數

scipy.optimize.minimize(fun, x0, args=(), method=None, jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None)

解釋

  • fun: 求最小值的目標函數
  • x0:變量的初始猜想值,若是有多個變量,須要給每一個變量一個初始猜想值。minimize是局部最優的解法.
  • args:常數值,fun中沒有數字,都以變量的形式表示,對於常數項,須要在這裏給值
  • method:求極值的方法,官方文檔給了不少種。通常使用默認。該參數表明採用的方式,默認是BFGS, L-BFGS-B, SLSQP中的一種,可選TNC
  • jac:該參數就是計算梯度的函數,和fun參數相似,第一個必須爲theta且其shape必須爲(n,)即一維數組,最後返回的梯度也必須爲一個一維數組
  • constraints:約束條件,針對fun中爲參數的部分進行約束限制
  • options能夠設置最大迭代輪數,以字典的形式來進行設置,例如:options={'maxiter':400}

正則化項

準備數據

data = loaddata('./data/sample_2.txt', ',')

y = np.c_[data[:,2]]
X = data[:,0:2]

plotData(data, 'x', 'y', 'y = 1', 'y = 0')

咱們的目標就是將這批數據進行分類,好比畫一個圈,圈內和圈外涇渭分明?

邏輯迴歸實戰,一文把理論和實踐結合

poly = PolynomialFeatures(10) # 多項式特徵,最高10維,例如[a,b]的多項式交互式輸出[1,a,b,ab]
XX = poly.fit_transform(data[:,0:2])
# 看看形狀(特徵映射後x有多少維了)
print(XX.shape)

定義損失函數

def lossFunctionReg(theta, reg, *args):
    m = y.size
    h = sigmoid(XX.dot(theta))

    J = -1.0*(1.0/m)*(np.log(h).T.dot(y)+np.log(1-h).T.dot(1-y)) + (reg/(2.0*m))*np.sum(np.square(theta[1:]))
    #  (reg/(2.0*m))*np.sum(np.square(theta[1:]))  即L2正則,開平方加和

    if np.isnan(J[0]):
        return(np.inf)
    return(J[0])

定義gd

def gradientReg(theta, reg, *args):
    m = y.size
    h = sigmoid(XX.dot(theta.reshape(-1,1)))

    grad = (1.0/m)*XX.T.dot(h-y) + (reg/m)*np.r_[[[0]],theta[1:].reshape(-1,1)]
    # (reg/m)*np.r_[[[0]],theta[1:].reshape(-1,1)] 這個是L2正則的求導

    return(grad.flatten())

初始化參數

init_theta = np.zeros(XX.shape[1])
# 初始化權重
lossFunctionReg(init_theta, 1, XX, y)

進行正則化項

fig, axes = plt.subplots(1,4, sharey = True, figsize=(17,5))

for i, C in enumerate([0.0, 1.0, 10.0, 100.0]):
    # 最優化 costFunctionReg
    res2 = minimize(lossFunctionReg, init_theta, args=(C, XX, y), jac=gradientReg, options={'maxiter':10000})

    # 準確率
    accuracy = 100.0*sum(predict(res2.x, XX) == y.ravel())/y.size    

    # 對X,y的散列繪圖
    plotData(data, 'x', 'y', 'y = 1', 'y = 0', axes.flatten()[i])

    # 畫出決策邊界
    x1_min, x1_max = X[:,0].min(), X[:,0].max(),
    x2_min, x2_max = X[:,1].min(), X[:,1].max(),
    xx1, xx2 = np.meshgrid(np.linspace(x1_min, x1_max), np.linspace(x2_min, x2_max))
    h = sigmoid(poly.fit_transform(np.c_[xx1.ravel(), xx2.ravel()]).dot(res2.x))
    h = h.reshape(xx1.shape)
    axes.flatten()[i].contour(xx1, xx2, h, [0.5], linewidths=1, colors='g');       
    axes.flatten()[i].set_title('Train acc {}% with lambda = {}'.format(np.round(accuracy, decimals=2), C))

運行結果如圖所示

image

決策邊界,咱們不妨分別來看看正則化係數lambda太大過小分別會出現什麼狀況:

  • Lambda = 0 : 就是沒有正則化,這樣的話,就過擬合咯
  • Lambda = 1||10 : 這纔是正確的打開方式
  • Lambda = 100 : 正則化項太激進,致使基本就沒擬合出決策邊界

PolynomialFeatures

能夠理解爲專門生成多項式特徵,而且多項式包含的是相互影響的特徵集,從低維空間往高維空間進行映射,好比:一個輸入樣本是2維的。形式如[a,b] ,則二階多項式的特徵集以下[1,a,b,a^2,ab,b^2]。經過這種形式,能夠輕鬆的將x擴展爲X向量

sklearn.preprocessing.PolynomialFeatures(degree=2, *, interaction_only=False, include_bias=True, order='C')

參數:

  • degree: integer,多項式階數,默認爲2;
  • interaction_only : boolean, default = False,若是值爲true(默認是false),則會產生相互影響的特徵集;
  • include_bias : boolean,是否包含誤差列。

參考內容

  1. https://www.zhihu.com/question/35322351/answer/67193153
  2. https://medium.com/@chih.sheng.huang821/%E6%A9%9F%E5%99%A8%E5%AD%B8%E7%BF%92-%E5%9F%BA%E7%A4%8E%E6%95%B8%E5%AD%B8-%E4%BA%8C-%E6%A2%AF%E5%BA%A6%E4%B8%8B%E9%99%8D%E6%B3%95-gradient-descent-406e1fd001f
  3. https://www.jianshu.com/p/70487abdf96b
  4. https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html
  5. https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.PolynomialFeatures.html
相關文章
相關標籤/搜索