天天看點

logistic模型 python_機器學習模型4 Logistic回歸-基于Python sklearn的實作

1、模型原理

(另一台電腦上,待補充)

回顧下線性回歸的損失函數,由于線性回歸是連續的,是以可以使用模型誤差的的平方和來定義損失函數。但是邏輯回歸不是連續的,自然線性回歸損失函數定義的經驗就用不上了。不過我們可以用最大似然法來推導出我們的損失函數。

2、Python3中sklearn關于Logistic回歸的代碼實作

(1)概述

在scikit-learn中,與邏輯回歸有關的主要是這3個類。LogisticRegression, LogisticRegressionCV 和logistic_regression_path。

其中LogisticRegression和LogisticRegressionCV的主要差別是:

LogisticRegressionCV使用了交叉驗證來選擇正則化系數C。而LogisticRegression需要自己每次指定一個正則化系數。

即LogisticRegression不做交叉驗證 ,也就是整個輸入作為訓練集來訓練模型參數。而LogisticRegressionCV則會将訓練集分成若幹份,每次選擇一部分訓練集來訓練模型,一部分樣本做驗證集來測試模型優劣,多次驗證後選擇最好的模型參數。

是以兩者肯定有差異。一般來說,會用後面一個。不過如果你用了其他一些網格搜尋方法(比如 GridSearchCV),自帶交叉驗證的話,那麼用第一個就可以了。

除了交叉驗證,以及選擇正則化系數C以外, LogisticRegression和LogisticRegressionCV的使用方法基本相同。

logistic_regression_path類則比較特殊,它拟合資料後,不能直接來做預測,隻能為拟合資料選擇合适邏輯回歸的系數和正則化系數。主要是用在模型選擇的時候。一般情況用不到這個類,是以後面不再講述logistic_regression_path類。

此外,scikit-learn裡面有個容易讓人誤解的類RandomizedLogisticRegression,雖然名字裡有邏輯回歸的詞,但是主要是用L1正則化的邏輯回歸來做特征選擇的,屬于次元規約的算法類,不屬于我們常說的分類算法的範疇。

(2)LogisticRegression和LogisticRegressionCV參數介紹

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

sklearn.linear_model.LogisticRegressionCV(Cs=10, fit_intercept=True, cv=None, dual=False, penalty=’l2’, scoring=None, solver=’lbfgs’, tol=0.0001, max_iter=100, class_weight=None, n_jobs=1, verbose=0, refit=True, intercept_scaling=1.0, multi_class=’ovr’, random_state=None)

關鍵參數介紹:

-penalty, 字元型,可選‘l1’ or ‘l2’, 預設為 ‘l2’,這個參數是選擇正則化項的,分别對應的L1正則化和L2正則化。

在調參時如果我們主要的目的隻是為了解決過拟合,一般penalty選擇L2正則化就夠了。但是如果選擇L2正則化發現還是過拟合,即預測效果差的時候,就可以考慮L1正則化。另外,如果模型的特征非常多,我們希望一些不重要的特征系數歸零,進而讓模型系數稀疏化的話,也可以使用L1正則化。

penalty參數的選擇會影響我們損失函數優化算法的選擇。即參數solver的選擇,如果是L2正則化,那麼4種可選的算法{‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’}都可以選擇。但是如果penalty是L1正則化的話,就隻能選擇‘liblinear’了。這是因為L1正則化的損失函數不是連續可導的,而{‘newton-cg’, ‘lbfgs’,‘sag’}這三種優化算法時都需要損失函數的一階或者二階連續導數。而‘liblinear’并沒有這個依賴。

具體使用了這4個算法有什麼不同以及有什麼影響,在solver參數作出說明。

-solver, 字元型,可選‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’, ‘saga’, LR預設為'liblinear',LRCV預設為 ‘lbfgs’,這個參數決定了我們對邏輯回歸損失函數的優化方法,有4種算法可以選擇,分别是:

a) liblinear:使用了開源的liblinear庫實作,内部使用了坐标軸下降法來疊代優化損失函數。

b) lbfgs:拟牛頓法的一種,利用損失函數二階導數矩陣即海森矩陣來疊代優化損失函數。

c) newton-cg:也是牛頓法家族的一種,利用損失函數二階導數矩陣即海森矩陣來疊代優化損失函數。

d) sag:即随機平均梯度下降,是梯度下降法的變種,和普通梯度下降法的差別是每次疊代僅僅用一部分的樣本來計算梯度,适合于樣本資料多的時候。

d) saga:随機優化SAG的變種。

從上面的描述可以看出,newton-cg, lbfgs和sag這三種優化算法時都需要損失函數的一階或者二階連續導數,是以不能用于沒有連續導數的L1正則化,隻能用于L2正則化。而liblinear通吃L1正則化和L2正則化。

同時,sag每次僅僅使用了部分樣本進行梯度疊代,是以當樣本量少的時候不要選擇它,而如果樣本量非常大,比如大于10萬,sag是第一選擇。但是sag不能用于L1正則化,是以當你有大量的樣本,又需要L1正則化的話就要自己做取舍了。要麼通過對樣本采樣來降低樣本量,要麼回到L2正則化。

從上面的描述,大家可能覺得,既然newton-cg, lbfgs和sag這麼多限制,如果不是大樣本,我們選擇liblinear不就行了嘛!錯,因為liblinear也有自己的弱點!我們知道,邏輯回歸有二進制邏輯回歸和多元邏輯回歸。對于多元邏輯回歸常見的有one-vs-rest(OvR)和many-vs-many(MvM)兩種。而MvM一般比OvR分類相對準确一些。郁悶的是liblinear隻支援OvR,不支援MvM,這樣如果我們需要相對精确的多元邏輯回歸時,就不能選擇liblinear了。也意味着如果我們需要相對精确的多元邏輯回歸不能使用L1正則化了。

具體OvR和MvM有什麼不同我們下一節講。

官方說明:

對于小型資料集,'liblinear'是一個不錯的選擇,而'sag'和'saga'對大的資料集來說速度更快。

對于多類問題,隻有'newton-cg','sag','saga'和'lbfgs'能處理多項式損失(可能就是我們常說的MvM); 'liblinear'僅限于OvR的情況。

'newton-cg','lbfgs'和'sag'隻能處理L2正則化,而'liblinear'和'saga'可以處理L1正則化,原因在上面已經提到。

“liblinear”在LogisticRegressionCV中可能會更慢,因為它不處理熱啟動。

請注意,“sag”和“saga”快速收斂僅在具有大緻相同比例的特征上得到保證。可以使用sklearn.preprocessing中的縮放器預處理資料。

-multi_class, 字元型,可選為‘ovr’,或者‘multinomial’,預設為‘ovr’。這個參數決定我們的分類方式。

ovr即前面提到的one-vs-rest(OvR),而multinomial即前面提到的many-vs-many(MvM)。如果是二進制邏輯回歸,ovr和multinomial并沒有任何差別,差別主要在多元邏輯回歸上。

OvR的思想很簡單,無論你是多少元邏輯回歸,我們都可以看做二進制邏輯回歸。具體做法是,對于第K類的分類決策,我們把所有第K類的樣本作為正例,除了第K類樣本以外的所有樣本都作為負例,然後在上面做二進制邏輯回歸,得到第K類的分類模型。其他類的分類模型獲得以此類推。

而MvM則相對複雜,這裡舉MvM的特例one-vs-one(OvO)作講解。如果模型有T類,我們每次在所有的T類樣本裡面選擇兩類樣本出來,不妨記為T1類和T2類,把所有的輸出為T1和T2的樣本放在一起,把T1作為正例,T2作為負例,進行二進制邏輯回歸,得到模型參數。我們一共需要T(T-1)/2次分類。

從上面的描述可以看出OvR相對簡單,但分類效果相對略差(這裡指大多數樣本分布情況,某些樣本分布下OvR可能更好)。而MvM分類相對精确,但是分類速度沒有OvR快。

如果選擇了ovr,則4種損失函數的優化方法liblinear,newton-cg, lbfgs和sag都可以選擇。但是如果選擇了multinomial,則隻能選擇newton-cg, lbfgs和sag了。

-class_weight,可以自己設定為dict形式(即{0:0.2,1:0.8}此種形式,為每個類别賦權)或者為‘balanced’,預設為None。這個參數是來确定類别權重的。

當預設None不填的時候,即不考慮權重,或者說所有類型的權重一樣。

當自定義dict的時候,則按照自定義的權重。

當選擇‘balanced’的時候,那麼類庫會根據訓練樣本量來計算權重。某種類型樣本量越多,則權重越低,樣本量越少,則權重越高。

那麼class_weight有什麼作用呢?在分類模型中,我們經常會遇到兩類問題:

第一種是誤分類的代價很高。比如對合法使用者和非法使用者進行分類,将非法使用者分類為合法使用者的代價很高,我們甯願将合法使用者分類為非法使用者,這時可以人工再甄别,但是卻不願将非法使用者分類為合法使用者。這時,我們可以适當提高非法使用者的權重。

第二種是樣本是高度失衡的,比如我們有合法使用者和非法使用者的二進制樣本資料10000條,裡面合法使用者有9995條,非法使用者隻有5條,如果我們不考慮權重,則我們可以将所有的測試集都預測為合法使用者,這樣預測準确率理論上有99.95%,但是卻沒有任何意義。這時,我們可以選擇balanced,讓類庫自動提高非法使用者樣本的權重。

提高了某種分類的權重,相比不考慮權重,會有更多的樣本分類劃分到高權重的類别,進而可以解決上面兩類問題。

當然,對于第二種樣本失衡的情況,我們還可以考慮用下一節講到的樣本權重參數: sample_weight,而不使用class_weight。sample_weight在下一節講。

-sample_weight,這個參數不是在模型訓練時需要設定的參數,而是在fit時,可能會用到的。為數組array格式。

由于樣本可能存在不失衡的問題,導緻樣本不是總體樣本的無偏估計,進而可能導緻我們的模型預測能力下降。遇到這種情況,我們可以通過調節樣本權重來嘗試解決這個問題。調節樣本權重的方法有兩種,第一種是在class_weight使用balanced。第二種是在調用fit函數時,通過sample_weight來自己調節每個樣本權重。

在scikit-learn做邏輯回歸時,如果上面兩種方法都用到了,那麼樣本的真正權重是class_weight*sample_weight.

其它通用參數介紹:

-dual,布爾型,預設值是False。

Ture時,表示使用dual formulation,僅僅适用于liblinear且L2正則化時。

False時,表示使用primal formulation,當n_samples > n_features,首選False。

-tol,浮點型,預設值為1e-4,該參數用于指定判斷算法收斂的門檻值。

-fit_intercept,布爾型,預設值為True,指定是否應将常量(即平常所說的偏差或截距)添加到決策函數中。

-intercept_scaling,浮點型,預設為1。

隻有當使用liblinear且fit_intercept設定為ture的時候,該參數才有用。

在這種情況下,x變為[x,intercept_scaling],即一個“合成”特征被附加到執行個體向量中, 該“合成”特征的常數值等于intercept_scaling。

截距變為intercept_scaling * synthetic_feature_weight。

注意! 合成特征權重與所有其他特征一樣,需經過L1 / L2正則化。 為了減小正則化對合成特征權重(并是以對截距)的影響,必須增加intercept_scaling。

-random_state,可選,可以是int整數型,也可以是RandomState instance, 或者是 None。預設是None。隻有當solver選擇‘sag’ 或者是‘liblinear’時使用。

該參數表示在随機資料混洗時使用的僞随機數生成器的種子。

如果是int,則random_state是随機數生成器使用的種子;

如果是RandomState執行個體,則random_state是随機數生成器;

如果為None,則随機數生成器是np.random使用的RandomState執行個體。

-max_iter,整數型,預設值為100。僅适用于solver選擇newton-cg,sag和lbfgs時,表示求解器收斂的最大疊代次數。

-verbose,整數型,預設值為0,适用于solver選擇liblinear或bfgs時,将verbose設定為任何正數以表示冗長度。

-n_jobs,整數型,預設值為1,僅适用于multi_class=ovr時,用于指定并行運算的CPU數量。且,需要注意的是,如果solver選擇liblinear,則不管multi_class設定為ovr或multinomial,這個參數都會被忽略。

如果給定值為-1,則使用所有CPU。

LogisticRegression個性化參數介紹:

-C,浮點型,預設值為1.0。該參數表示正則化的懲罰系數。應該是一個正的浮點數。

-warm_start,布爾型,預設值為False。

設定為True時,下次訓練是以追加的形式進行,否則,就會重新全部計算。

warm_start對于liblinear沒用,支援lbfgs,newton-cg,sag,saga。

LogisticRegressionCV個性化參數介紹:

-Cs,一個整數型或浮點型數的清單,預設為10。

Each of the values in Cs describes the inverse of regularization strength. If Cs is as an int, then a grid of Cs values are chosen in a logarithmic scale between 1e-4 and 1e4. Like in support vector machines, smaller values specify stronger regularization.

-cv,可以是整數型,或者是一個交叉驗證生成器,預設為None.

預設的交叉驗證生成器是分層K-Folds。

如果設定為某一整數,則它代表使用的折疊數(即我們說的10折交叉驗證之類的。)

-refit,布爾型,預設為Ture。

If set to True, the scores are averaged across all folds, and the coefs and the C that corresponds to the best score is taken, and a final refit is done using these parameters.

Otherwise the coefs, intercepts and C that correspond to the best scores across folds are averaged.

我的了解是,如果選擇ture,則coefs和c的值是在多次交叉驗證中,選擇表現最好的那組參數值。如果是false,則coefs和c的值是取多次交叉驗證過程中,得到的多組參數值的平均數。(望指正!)