glmnet包可以對一系列調優參數值同時計算參數估計。
該包可以用於線性迴歸,也可以擬合廣義線性模型,如邏輯迴歸,多項式迴歸,泊松迴歸,cox迴歸。
初始glmnet
> install.packages("glmnet")
trying URL 'https://cran.rstudio.com/bin/windows/contrib/3.4/glmnet_2.0-13.zip'
Content type 'application/zip' length 1769153 bytes (1.7 MB)
downloaded 1.7 MB
package ‘glmnet’ successfully unpacked and MD5 sums checked
The downloaded binary packages are in
C:\Users\LLJiang\AppData\Local\Temp\RtmpCswyie\downloaded_packages
> library(glmnet)
載入需要的程輯包:Matrix
載入需要的程輯包:foreach
Loaded glmnet 2.0-13
Warning messages:
1: 程輯包‘glmnet’是用R版本3.4.3 來建造的
2: 程輯包‘foreach’是用R版本3.4.3 來建造的
> dat=read.csv("https://raw.githubusercontent.com/happyrabbit/DataScientistR/master/Data/SegData.csv")
#對數據進行一些清理,刪除錯誤的樣本觀測,消費金額不能爲負數
> dat=subset(dat,store_exp>0&online_exp>0)
> trainx=dat[,grep("Q",names(dat))]
#將實體店消費量和在線消費之和當作因變量
#得到總消費量=實體店消費+在線消費
> trainy=dat$store_exp+dat$online_exp
> glmfit=glmnet(as.matrix(trainx),trainy)
>
我們可以通過plot(),coef(),predict()等函數來得到相應的信息。
> plot(glmfit,label=T)
>
圖中每種顏色的線代表對應一個自變量,展示的是隨着Lasso罰函數對應調優參數的變化,各個變量對應的參數估計路徑。
圖中有上下兩個X軸標度,下X軸是調優參數變化對應最優解的一階範數值,上X軸是調優參數對應的非0參數估計個數,也就是Lasso模型的自由度。
> print(glmfit)
Call: glmnet(x = as.matrix(trainx), y = trainy)
Df %Dev Lambda
[1,] 0 0.0000 3042.000
[2,] 2 0.1038 2771.000
[3,] 2 0.1919 2525.000
[4,] 2 0.2650 2301.000
[5,] 3 0.3264 2096.000
[6,] 3 0.3894 1910.000
[7,] 3 0.4417 1741.000
[8,] 3 0.4852 1586.000
[9,] 3 0.5212 1445.000
[10,] 3 0.5512 1317.000
[11,] 3 0.5760 1200.000
如上,第一例Df表示非0估計的參數個數
第二列%Dev解釋方差百分比
第三列表示Lambda調優參數的取值。
當%Dev百分比只發生微小變化時,算法會提前停止。
> coef(glmfit,s=1200)
11 x 1 sparse Matrix of class "dgCMatrix"
1
(Intercept) 2255.2221
Q1 -390.9214
Q2 653.6437
Q3 624.4068
Q4 .
Q5 .
Q6 .
Q7 .
Q8 .
Q9 .
Q10 .
>
如上,當最優參數爲1200時,只有3個變量的參數估計非0.
> newdat=matrix(sample(1:9,30,replace=T),nrow=3)
> predict(glmfit,newdat,s=c(1741,2000))
1 2
[1,] 6331.299 6142.796
[2,] 3662.438 3921.191
[3,] 6242.257 6445.598
>
如上,結果中每列分別對應一個最優參數取值的預測。
需要通過交互校驗進行參數調優。
> cvfit=cv.glmnet(as.matrix(trainx),trainy)
> plot(cvfit)
>
如上圖,紅色的點是不同調優參數取值對應的交互校驗均方誤差,灰色的線是相應置信區間。
兩條虛線表示選中的兩個調優參數。左邊的那個調優參數值對應的是最小交互校驗均方誤差,右邊的那個調優參數值是離最小均方誤差一個標準差的調優參數值。
> cvfit$lambda.min
[1] 13.79349
> cvfit$lambda.1se
[1] 1316.656
>
也可以採用如下方式查看不同調優參數值對應的迴歸參數估計
> coef(cvfit,s="lambda.1se")
11 x 1 sparse Matrix of class "dgCMatrix"
1
(Intercept) 2221.0392
Q1 -340.6045
Q2 629.6860
Q3 585.1639
Q4 .
Q5 .
Q6 .
Q7 .
Q8 .
Q9 .
Q10 .
>
收縮線性迴歸
線性迴歸又兩種,一種是高斯家族模型,其中因變量是一個向量。
另一種是多元高斯,也就是多元響應變量情況,此時因變量是一個矩陣,參數也是矩陣。
> fit=glmnet(as.matrix(trainx),trainy,alpha=0.2,nlambda=20)
> print(fit,digits=4)
Call: glmnet(x = as.matrix(trainx), y = trainy, alpha = 0.2, nlambda = 20)
Df %Dev Lambda
[1,] 0 0.0000 15210.000
[2,] 4 0.2502 9366.000
[3,] 6 0.4590 5768.000
[4,] 7 0.5848 3552.000
[5,] 9 0.6502 2188.000
[6,] 9 0.6823 1347.000
[7,] 9 0.6967 829.700
[8,] 9 0.7033 511.000
[9,] 9 0.7064 314.700
[10,] 9 0.7080 193.800
[11,] 9 0.7088 119.300
[12,] 9 0.7093 73.500
[13,] 9 0.7095 45.270
[14,] 9 0.7096 27.880
[15,] 9 0.7096 17.170
[16,] 9 0.7096 10.570
[17,] 10 0.7096 6.511
[18,] 10 0.7096 4.010
> plot(fit,xvar="lambda",label=T)
>
由上圖,可以看到,隨着調優參數的增大,參宿逐步向0收縮。
Q1,Q2,Q3,Q8參數估計差不多在最後才收縮爲0.
說明這幾個變量對解釋因變量最重要。
> plot(fit,xvar="dev",label=T)
>
上圖爲解釋方差的百分比的路徑圖
其中橫座標爲解釋方差百分比時的路徑圖和之前不太一樣。
非0參數個數越多,即使方差百分比就越大。
到最右端的時候,解釋方差百分比變化很小,但是參數估計卻急劇增大。
由上圖我們可以看出,Q7對模型擬合幾乎不起作用。
通過以下代碼可以查看你想要的取值是不是已經調優擬合過
> any(fit$lambda==1000)
[1] FALSE
>
上面結果表明調優參數=1000這個取值不在調優取值內。
通常情況下用線性插值就可以,不需要重新擬合模型。
我們可以在新的數據集中預測結果
> newdat=matrix(sample(1:9,30,replace=T),nrow=3)
> predict(fit,newdat,type="response",s=1000)
1
[1,] 5674.221
[2,] 10990.417
[3,] 3684.514
> predict(fit,newdat,
#得到的是線性插值參數估計
type="coefficients",s=1000)
11 x 1 sparse Matrix of class "dgCMatrix"
1
(Intercept) 1177.37262
Q1 -483.29175
Q2 850.50376
Q3 645.89528
Q4 60.82823
Q5 163.98503
Q6 192.23258
Q7 .
Q8 -193.76827
Q9 198.42621
Q10 -132.20608
>
type=”nonzero”將會返回一個向量告訴你,那些自變量的參數估計非0
> predict(fit,newdat,type="nonzero",s=1000)
X1
1 1
2 2
3 3
4 4
5 5
6 6
7 8
8 9
9 10
>
type.measure=”class”僅僅適用於二項迴歸和多項邏輯迴歸,其使用的是誤判率。
type.measure=”auc”只針對二分類邏輯迴歸,使用的是ROC線下的面積。
type.measure=”mae”絕對誤差均值可以用於除了cox模型之外的其他所有模型。
> cvfit=cv.glmnet(as.matrix(trainx),trainy,type.measure="mae",nfolds=20)
> cvfit$lambda.min
[1] 7.191939
> predict(cvfit,newx=newdat,s="lambda.min")
1
[1,] 8992.229
[2,] 11106.268
[3,] 7238.749
> coef(cvfit,s="lambda.min")
11 x 1 sparse Matrix of class "dgCMatrix"
1
(Intercept) -2410.85923
Q1 -301.81607
Q2 675.95354
Q3 689.31828
Q4 218.49555
Q5 600.75548
Q6 673.01104
Q7 .
Q8 -90.21178
Q9 359.73608
Q10 -299.33332
>
此外,也可以自己指定交互校驗的樣本分層情況
> foldid=sample(1:10,size=length(trainy),replace=T)
> cv1=cv.glmnet(as.matrix(trainx),trainy,foldid=foldid,alpha=1)
> cv.2=cv.glmnet(as.matrix(trainx),trainy,foldid=foldid,alpha=.2)
> cv.5=cv.glmnet(as.matrix(trainx),trainy,foldid=foldid,alpha=.5)
> cv0=cv.glmnet(as.matrix(trainx),trainy,foldid=foldid,alpha=0)
> plot(log(cv1$lambda),cv1$cvm,pch=19,col=2,xlab="log(Lambda)",ylab=cv1$name)
>
> points(log(cv.5$lambda),cv.5$cvm,col=1)
> points(log(cv.2$lambda),cv.2$cvm,col=3)
> points(log(cv0$lambda),cv0$cvm,col=4)
> legend("topleft",legend=c("alpha=1","alpha=0.5","alpha=0.2","alpha=0"),pch=19,col=c(2,1,3,4))
>
由上圖所示,不同alpha的取值對應的最優均方誤差幾乎相同。