機器學習sklearn(57):演算法例項(十四)分類(七)邏輯迴歸(二)linear_model.LogisticRegression(一) 重要引數
阿新 • • 發佈:2021-06-27
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可以看見,當我們選擇L1正則化的時候,許多特徵的引數都被設定為了0,這些特徵在真正建模的時候,就不會出現在我們的模型當中了,而L2正則化則是對所有的特徵都給出了引數。 究竟哪個正則化的效果更好呢?還是都差不多?= 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 = [] 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期:資料預處理和特徵工程中的程式碼。