R語言筆記之廣義線性模型壓縮方法1

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的取值對應的最優均方誤差幾乎相同。

發佈了53 篇原創文章 · 獲贊 27 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章