例:バイナリ結果にglmnetを使用したLASSO回帰


77

私は興味のある結果が二分されglmnetているLASSO回帰の使用に手を出し始めています。以下に小さな模擬データフレームを作成しました。

age     <- c(4, 8, 7, 12, 6, 9, 10, 14, 7) 
gender  <- c(1, 0, 1, 1, 1, 0, 1, 0, 0)
bmi_p   <- c(0.86, 0.45, 0.99, 0.84, 0.85, 0.67, 0.91, 0.29, 0.88)
m_edu   <- c(0, 1, 1, 2, 2, 3, 2, 0, 1)
p_edu   <- c(0, 2, 2, 2, 2, 3, 2, 0, 0)
f_color <- c("blue", "blue", "yellow", "red", "red", "yellow", "yellow", 
             "red", "yellow")
asthma  <- c(1, 1, 0, 1, 0, 0, 0, 1, 1)
# df is a data frame for further use!
df <- data.frame(age, gender, bmi_p, m_edu, p_edu, f_color, asthma)

上記のデータセットの列(変数)は次のとおりです。

  • age (年の子供の年齢)-継続的
  • gender -バイナリ(1 =男性、0 =女性)
  • bmi_p (BMIパーセンタイル)-連続
  • m_edu (母親の最高教育レベル)-通常(0 =高校未満、1 =高校の卒業証書、2 =学士号、3 =学士号取得後の学位)
  • p_edu (父の最高教育レベル)-序数(m_eduと同じ)
  • f_color (お気に入りの原色)-名目(「青」、「赤」、または「黄」)
  • asthma (子喘息の状態)-バイナリ(1 =喘息; 0 =喘息なし)

この例の目的は、6つの潜在的な予測変数(のリストからモデル予測子の喘息の状態を作成するために、LASSOを活用することでagegenderbmi_pm_edup_edu、およびf_color)。明らかにサンプルサイズがここでの問題ですがglmnet、結果がバイナリ(1 =喘息)の場合、フレームワーク内でさまざまなタイプの変数(連続変数、順序変数、名義変数、バイナリ変数)を処理する方法についてより多くの洞察を得ることを望んでいます; 0 =喘息なし)。

そのため、R喘息の状態を予測するために上記のデータでLASSOを使用して、この模擬サンプルの説明とともにサンプルスクリプトを提供したいと思う人はいますか?非常に基本的ではありますが、私、そしておそらくCVの他の多くの人はこれを大いに評価するでしょう!


2
あなたは、データを掲載場合は、より多くの幸運を得るかもしれないdput実際の Rオブジェクト。読者にケーキを焼くだけでなく、つや消しをさせないでください!Rで適切なデータフレームを生成する場合、たとえばfoo、の出力を質問に編集しますdput(foo)
ギャビンシンプソン

ありがとう@GavinSimpson!投稿をデータフレームで更新したので、うまくいけば、フロストなしでケーキを食べることができます!:)
マットライヘンバッハ

2
BMIパーセンタイルを使用すると、ある意味で物理学の法則に反することになります。肥満は、現在の被験者と類似している個人の数ではなく、パーセンタイルが行っている物理的な測定値(長さ、体積、体重)に従って個人に影響を与えます。
フランクハレル

3
BMIパーセンタイルは、私が使用することを好む指標ではありません。ただし、CDCガイドラインでは、身長と体重に加えて年齢と性別も考慮しているため、20歳未満の子供や青少年にはBMIを超えるBMIパーセンタイルを使用することをお勧めします。この例では、これらの変数とデータ値はすべて完全に考慮されています。この例は、ビッグデータを扱う際の現在の作業を反映していません。glmnetバイナリの結果で実際に動作する例を見てみたかっただけです。
マットライヘンバッハ

MCP、SCAD、またはLASSOによってペナルティが課された線形およびロジスティック回帰モデルに適合するncvregと呼ばれるPatrick Brehenyによるパッケージをここに接続します。(cran.r-project.org/web/packages/ncvreg/index.html
bdeonovic

回答:


100
library(glmnet)

age     <- c(4, 8, 7, 12, 6, 9, 10, 14, 7) 
gender  <- as.factor(c(1, 0, 1, 1, 1, 0, 1, 0, 0))
bmi_p   <- c(0.86, 0.45, 0.99, 0.84, 0.85, 0.67, 0.91, 0.29, 0.88) 
m_edu   <- as.factor(c(0, 1, 1, 2, 2, 3, 2, 0, 1))
p_edu   <- as.factor(c(0, 2, 2, 2, 2, 3, 2, 0, 0))
f_color <- as.factor(c("blue", "blue", "yellow", "red", "red", "yellow", 
                       "yellow", "red", "yellow"))
asthma <- c(1, 1, 0, 1, 0, 0, 0, 1, 1)

xfactors <- model.matrix(asthma ~ gender + m_edu + p_edu + f_color)[, -1]
x        <- as.matrix(data.frame(age, bmi_p, xfactors))

# Note alpha=1 for lasso only and can blend with ridge penalty down to
# alpha=0 ridge only.
glmmod <- glmnet(x, y=as.factor(asthma), alpha=1, family="binomial")

# Plot variable coefficients vs. shrinkage parameter lambda.
plot(glmmod, xvar="lambda")

ここに画像の説明を入力してください

通常、カテゴリ変数は最初に因子に変換され、次に予測変数のダミー変数行列が作成され、連続予測変数とともにモデルに渡されます。glmnetはリッジペナルティと投げ縄ペナルティの両方を使用しますが、単独で設定することもできます。

いくつかの結果:

# Model shown for lambda up to first 3 selected variables.
# Lambda can have manual tuning grid for wider range.

glmmod
# Call:  glmnet(x = x, y = as.factor(asthma), family = "binomial", alpha = 1) 
# 
#        Df    %Dev   Lambda
#   [1,]  0 0.00000 0.273300
#   [2,]  1 0.01955 0.260900
#   [3,]  1 0.03737 0.249000
#   [4,]  1 0.05362 0.237700
#   [5,]  1 0.06847 0.226900
#   [6,]  1 0.08204 0.216600
#   [7,]  1 0.09445 0.206700
#   [8,]  1 0.10580 0.197300
#   [9,]  1 0.11620 0.188400
#  [10,]  3 0.13120 0.179800
#  [11,]  3 0.15390 0.171600
# ...

係数はglmmodから抽出できます。ここでは、3つの変数が選択されています。

coef(glmmod)[, 10]
#   (Intercept)           age         bmi_p       gender1        m_edu1 
#    0.59445647    0.00000000    0.00000000   -0.01893607    0.00000000 
#        m_edu2        m_edu3        p_edu2        p_edu3    f_colorred 
#    0.00000000    0.00000000   -0.01882883    0.00000000    0.00000000 
# f_coloryellow 
#   -0.77207831 

最後に、クロス検証を使用してラムダを選択することもできます。

cv.glmmod <- cv.glmnet(x, y=asthma, alpha=1)
plot(cv.glmmod)

ここに画像の説明を入力してください

(best.lambda <- cv.glmmod$lambda.min)
# [1] 0.2732972

4
これはまさに私が+1を探していたものです。唯一の質問は1)0.2732972のクロス検証ラムダで何ができますか?および2)glmmodから、選択された変数は好きな色(黄色)、性別、および父の教育(学士号)ですか?本当にありがとう!
マットライヘンバッハ

4
1)クロス検証を使用して、ラムダと係数を選択します(最小エラー時)。このモックアップには、ローカルの最小値はありません(obsが少なすぎることに関連する警告もありました)。私はすべての係数が収縮ペナルティでゼロに縮小されたと解釈し(最良のモデルはインターセプトのみ)、より多くの(実際の)観測で再実行し、ラムダ範囲を増やす可能性があります。2)はい、coef(glmmod)[、10]を選択した例では... CVまたは結果の解釈を介してモデルのラムダを選択します。あなたの質問を解決したと感じた場合、解決済みとマークしてもらえますか?ありがとう。
パット

2
これがf_color変数をどのように処理するか尋ねることはできますか?因子レベル1から4は、1から2よりも大きなステップと見なされますか、またはこれらはすべて均等に重み付けされ、方向性がなく、カテゴリー的ですか?(すべての順序付けられていない予測子を使用した分析に適用したい。)
beroe

3
この行xfactors <- model.matrix(asthma ~ gender + m_edu + p_edu + f_color)[,-1]は、カテゴリ変数f_colorをコード化します(as.factor前の行で宣言されたとおり)。contrasts.arg引数が指定されない限り、デフォルトのRダミー変数コーディングを使用する必要があります。つまり、f_colorのすべてのレベルは、参照クラスとして使用され、インターセプトに吸収される最初のレベルを除き、等しく重み付けされ、方向性がありません。
アレックス

1
@Alexはmodel.matrix(asthma ~ gender + m_edu + p_edu + f_color + age + bmi_p)[, -1]上記の2行と同じ結果になりませんか?なぜ連続変数を連結するために余分なステップを使用するのdata.frameですか?
ジグガンジャー

6

私が好む方法なので、パッケージenetを使用します。それはもう少し柔軟です。

install.packages('elasticnet')
library(elasticnet)

age <- c(4,8,7,12,6,9,10,14,7) 
gender <- c(1,0,1,1,1,0,1,0,0)
bmi_p <- c(0.86,0.45,0.99,0.84,0.85,0.67,0.91,0.29,0.88)
m_edu <- c(0,1,1,2,2,3,2,0,1)
p_edu <- c(0,2,2,2,2,3,2,0,0)
#f_color <- c("blue", "blue", "yellow", "red", "red", "yellow", "yellow", "red", "yellow")
f_color <- c(0, 0, 1, 2, 2, 1, 1, 2, 1)
asthma <- c(1,1,0,1,0,0,0,1,1)
pred <- cbind(age, gender, bmi_p, m_edu, p_edu, f_color)



enet(x=pred, y=asthma, lambda=0)

4
共有してくれてありがとうelasticnet。ただし、上記のRスクリプトの出力をどうすればよいかわかりません。明確にしていただけますか?前もって感謝します!
マットライヘンバッハ

4

patが提供する優れた例を拡張するだけです。元の問題は、レベル間の固有の順序(0 <1 <2 <3)で順序変数(m_edu、p_edu)を引き起こしました。patの元の回答では、これらは名目上のカテゴリ変数として扱われ、それらの間には順序がありません。私は間違っているかもしれませんが、これらの変数は、モデルが固有の順序を尊重するようにコーディングする必要があると思います。これらが(patの答えのように順序付けられていない因子としてではなく)順序付けられた因子としてコード化されている場合、glmnetは少し異なる結果を与えます...次のコードは順序付けられた因子として順序変数を正しく含み、わずかに異なる結果を与えます:

library(glmnet)

age     <- c(4, 8, 7, 12, 6, 9, 10, 14, 7) 
gender  <- as.factor(c(1, 0, 1, 1, 1, 0, 1, 0, 0))
bmi_p   <- c(0.86, 0.45, 0.99, 0.84, 0.85, 0.67, 0.91, 0.29, 0.88) 
m_edu   <- factor(c(0, 1, 1, 2, 2, 3, 2, 0, 1), 
                  ordered = TRUE)
p_edu   <- factor(c(0, 2, 2, 2, 2, 3, 2, 0, 0), 
                  levels = c(0, 1, 2, 3), 
                  ordered = TRUE)
f_color <- as.factor(c("blue", "blue", "yellow", "red", "red", 
                       "yellow", "yellow", "red", "yellow"))
asthma <- c(1, 1, 0, 1, 0, 0, 0, 1, 1)

xfactors <- model.matrix(asthma ~ gender + m_edu + p_edu + f_color)[, -1]
x        <- as.matrix(data.frame(age, bmi_p, xfactors))

# Note alpha=1 for lasso only and can blend with ridge penalty down to
# alpha=0 ridge only.
glmmod <- glmnet(x, y=as.factor(asthma), alpha=1, family="binomial")

# Plot variable coefficients vs. shrinkage parameter lambda.
plot(glmmod, xvar="lambda")

ここに画像の説明を入力してください


1
ときどき_sci、良いキャッチ-これは、教育レベルの変数をモデル化するより適切な方法です。ご協力ありがとうございます。
マットライヘンバッハ

変数のプロット凡例をどのように追加しますか?たとえば、この例の赤い線は何ですか?
ジグガンジャー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.