解決的二分類問題,如手寫識別0-9 html
目標:邏輯迴歸返回一個機率值[0-1]python
邏輯迴歸的特色:快、效果好、容易實時在線預測、利於分析算法
方法:定義一個條件機率,如p(Y|X)至關於用模型來捕獲輸入X和輸出Y之間的關係,如數組
對於二分類問題,因爲p(Y|X)的值域在[-∞,+∞],爲了令其至於範圍壓縮到[-1,1]之間,故推薦使用sigmoid
函數,故得
兩式子合併,可得網絡
前面說道使用該函數是因爲其定義域是[-∞,+∞],且值域是[-1,1]故選擇該函數,這樣的說法其實並不能服衆,畢竟probit
也具備相同的性質。事實上選用sigmoid
的意義在於,指數族分佈exponential family
所具備的最佳(即maximum entropy
最大熵)性質機器學習
熵本來是信息論中的概念,用在機率分佈上能夠表示這個分佈中所包含的不肯定度,熵越大不肯定度越大。因此你們能夠想象到,均勻分佈熵最大,由於基本新數據是任何值的機率都均等。ide
而咱們如今關心的是,給定某些假設以後,熵最大的分佈。也就是說這個分佈應該在知足我假設的前提下越均勻越好。好比你們熟知的正態分佈,正是假設已知mean
和variance
後熵最大的分佈。此時回過來看logistic regression
,這裏假設了什麼呢?函數
(bernoulli distribution)
,因此咱們只須要知道 P(Y|X)bernoulli
的exponential family
形式,以下學習
所謂決策邊界就是可以把樣本正確分類的一條邊界,在這個分類點上,大於這個邊界點,分類爲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)
對於有些機器學習問題,咱們的目標函數是對樣本的損失函數。假設訓練樣本集有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,這是很是理想的狀況,而此時就出現了所謂過擬合現象
事實上在擬閤中會出現過擬合和欠擬合兩種現象
帶着問題出發:
其實正則化項是對參數的控制。其目的主要有兩個
總而言之,避免w過大,L1正則化和L2正則化上能夠看作是損失函數的懲罰
正則項有三種:L0、L一、L2
保證參數稀疏化來防止過擬合,能夠用非零參數,來進行特徵選擇。可是L0正則化很差求,所以採用L1正則化。L1正則化是L0正則化的最優凸近似,比L0容易求解,而且能夠實現稀疏的效果。
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正則化能夠防止模型過擬合(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');
scipy.optimize.minimize(fun, x0, args=(), method=None, jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None)
解釋
準備數據
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))
運行結果如圖所示
決策邊界,咱們不妨分別來看看正則化係數lambda太大過小分別會出現什麼狀況:
能夠理解爲專門生成多項式特徵,而且多項式包含的是相互影響的特徵集,從低維空間往高維空間進行映射,好比:一個輸入樣本是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')
參數: