1. 程式人生 > 其它 >機器學習sklearn(57):演算法例項(十四)分類(七)邏輯迴歸(二)linear_model.LogisticRegression(一) 重要引數

機器學習sklearn(57):演算法例項(十四)分類(七)邏輯迴歸(二)linear_model.LogisticRegression(一) 重要引數

class sklearn.linear_model.LogisticRegression (penalty=’l2’, dual=False, tol=0.0001, C=1.0,fifit_intercept=True, intercept_scaling=1, class_weight=None, random_state=None, solver=’warn’, max_iter=100,multi_class=’warn’, verbose=0, warm_start=False, n_jobs=None)

1 二元邏輯迴歸的損失函式

1.1 損失函式的概念與解惑 1.2【選學】二元邏輯迴歸損失函式的數學解釋,公式推導與解惑

2 重要引數penalty & C

2.1 正則化
from sklearn.linear_model import LogisticRegression as LR
from sklearn.datasets import load_breast_cancer
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
data 
= load_breast_cancer() X = data.data y = data.target data.data.shape lrl1 = LR(penalty="l1",solver="liblinear",C=0.5,max_iter=1000) lrl2 = LR(penalty="l2",solver="liblinear",C=0.5,max_iter=1000) #邏輯迴歸的重要屬性coef_,檢視每個特徵所對應的引數 lrl1 = lrl1.fit(X,y) lrl1.coef_ (lrl1.coef_ != 0).sum(axis=1) lrl2 = lrl2.fit(X,y) lrl2.coef_
可以看見,當我們選擇L1正則化的時候,許多特徵的引數都被設定為了0,這些特徵在真正建模的時候,就不會出現在我們的模型當中了,而L2正則化則是對所有的特徵都給出了引數。 究竟哪個正則化的效果更好呢?還是都差不多?
l1 = []
l2 = []
l1test = []
l2test = []
Xtrain, Xtest, Ytrain, Ytest = train_test_split(X,y,test_size=0.3,random_state=420)
for i in np.linspace(0.05,1,19):
  lrl1 = LR(penalty="l1",solver="liblinear",C=i,max_iter=1000)
  lrl2 = LR(penalty="l2",solver="liblinear",C=i,max_iter=1000)
  
  lrl1 = lrl1.fit(Xtrain,Ytrain)
  l1.append(accuracy_score(lrl1.predict(Xtrain),Ytrain))
  l1test.append(accuracy_score(lrl1.predict(Xtest),Ytest))
  lrl2 = lrl2.fit(Xtrain,Ytrain)
  l2.append(accuracy_score(lrl2.predict(Xtrain),Ytrain))
  l2test.append(accuracy_score(lrl2.predict(Xtest),Ytest))
graph = [l1,l2,l1test,l2test]
color = ["green","black","lightgreen","gray"]
label = ["L1","L2","L1test","L2test"]  
plt.figure(figsize=(6,6))
for i in range(len(graph)):
  plt.plot(np.linspace(0.05,1,19),graph[i],color[i],label=label[i])
plt.legend(loc=4) #圖例的位置在哪裡?4表示,右下角
plt.show()
可見,至少在我們的乳腺癌資料集下,兩種正則化的結果區別不大。但隨著C的逐漸變大,正則化的強度越來越小,模型在訓練集和測試集上的表現都呈上升趨勢,直到C=0.8左右,訓練集上的表現依然在走高,但模型在未知資料集上的表現開始下跌,這時候就是出現了過擬合。我們可以認為,C設定為0.8會比較好。在實際使用時,基本就預設使用l2正則化,如果感覺到模型的效果不好,那就換L1試試看。 2.2 邏輯迴歸中的特徵工程 高效的嵌入法embedded
from sklearn.linear_model import LogisticRegression as LR
from sklearn.datasets import load_breast_cancer
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import cross_val_score
from sklearn.feature_selection import SelectFromModel
data = load_breast_cancer()
data.data.shape
LR_ = LR(solver="liblinear",C=0.9,random_state=420)
cross_val_score(LR_,data.data,data.target,cv=10).mean()
X_embedded = SelectFromModel(LR_,norm_order=1).fit_transform(data.data,data.target)
X_embedded.shape
cross_val_score(LR_,X_embedded,data.target,cv=10).mean()
fullx = []
fsx = []
threshold = np.linspace(0,abs((LR_.fit(data.data,data.target).coef_)).max(),20) k=0
for i in threshold:
  X_embedded = SelectFromModel(LR_,threshold=i).fit_transform(data.data,data.target)
  fullx.append(cross_val_score(LR_,data.data,data.target,cv=5).mean())
  fsx.append(cross_val_score(LR_,X_embedded,data.target,cv=5).mean())
  print((threshold[k],X_embedded.shape[1]))
  k+=1
  
plt.figure(figsize=(20,5))
plt.plot(threshold,fullx,label="full")
plt.plot(threshold,fsx,label="feature selection")
plt.xticks(threshold)
plt.legend()
plt.show()
然而,這種方法其實是比較無效的,大家可以用學習曲線來跑一跑:當threshold越來越大,被刪除的特徵越來越多,模型的效果也越來越差,模型效果最好的情況下需要保證有17個以上的特徵。實際上我畫了細化的學習曲線,如果要保證模型的效果比降維前更好,我們需要保留25個特徵,這對於現實情況來說,是一種無效的降維:需要30個指標來判斷病情,和需要25個指標來判斷病情,對醫生來說區別不大。 2)第二種調整方法,是調邏輯迴歸的類LR_,通過畫C的學習曲線來實現:
fullx = []
fsx = []
C=np.arange(0.01,10.01,0.5)
for i in C:
  LR_ = LR(solver="liblinear",C=i,random_state=420)
  
  fullx.append(cross_val_score(LR_,data.data,data.target,cv=10).mean())
  
  X_embedded = SelectFromModel(LR_,norm_order=1).fit_transform(data.data,data.target)
  fsx.append(cross_val_score(LR_,X_embedded,data.target,cv=10).mean())
  
print(max(fsx),C[fsx.index(max(fsx))])
plt.figure(figsize=(20,5))
plt.plot(C,fullx,label="full")
plt.plot(C,fsx,label="feature selection")
plt.xticks(C)
plt.legend()
plt.show()
繼續細化學習曲線:
fullx = []
fsx = []
C=np.arange(6.05,7.05,0.005)
for i in C:
  LR_ = LR(solver="liblinear",C=i,random_state=420)
  
  fullx.append(cross_val_score(LR_,data.data,data.target,cv=10).mean())
  
  X_embedded = SelectFromModel(LR_,norm_order=1).fit_transform(data.data,data.target)
  fsx.append(cross_val_score(LR_,X_embedded,data.target,cv=10).mean())
  
print(max(fsx),C[fsx.index(max(fsx))])
plt.figure(figsize=(20,5))
plt.plot(C,fullx,label="full")
plt.plot(C,fsx,label="feature selection")
plt.xticks(C)
plt.legend()
plt.show()
#驗證模型效果:降維之前
LR_ = LR(solver="liblinear",C=6.069999999999999,random_state=420)
cross_val_score(LR_,data.data,data.target,cv=10).mean()
#驗證模型效果:降維之後
LR_ = LR(solver="liblinear",C=6.069999999999999,random_state=420)
X_embedded = SelectFromModel(LR_,norm_order=1).fit_transform(data.data,data.target)
cross_val_score(LR_,X_embedded,data.target,cv=10).mean()
X_embedded.shape
這樣我們就實現了在特徵選擇的前提下,保持模型擬合的高效,現在,如果有一位醫生可以來為我們指點迷津,看看剩下的這些特徵中,有哪些是對針對病情來說特別重要的,也許我們還可以繼續降維。當然,除了嵌入法,係數累加法或者包裝法也是可以使用的。 比較麻煩的係數累加法 係數累加法的原理非常簡單。在PCA中,我們通過繪製累積可解釋方差貢獻率曲線來選擇超引數,在邏輯迴歸中我們可以使用係數coef_來這樣做,並且我們選擇特徵個數的邏輯也是類似的:找出曲線由銳利變平滑的轉折點,轉折點之前被累加的特徵都是我們需要的,轉折點之後的我們都不需要。不過這種方法相對比較麻煩,因為我們要先對特徵係數進行從大到小的排序,還要確保我們知道排序後的每個係數對應的原始特徵的位置,才能夠正確找出那些重要的特徵。如果要使用這樣的方法,不如直接使用嵌入法來得方便。 簡單快速的包裝法 相對的,包裝法可以直接設定我們需要的特徵個數,邏輯迴歸在現實中運用時,可能會有”需要5~8個變數”這種需求,包裝法此時就非常方便了。不過邏輯迴歸的包裝法的使用和其他演算法一樣,並不具有特別之處,因此在這裡就不在贅述,具體大家可以參考03期:資料預處理和特徵工程中的程式碼。