コードを間違えたとは思いません。これは出力の解釈の問題です。
Lassoは、どの個別リグレッサが他のリグレッサより「予測的」であるかを示していません。係数をゼロと推定する組み込みの傾向があります。ペナルティ係数が大きいほど、その傾向は大きくなります。ログ(λ )
交差検証プロットは、より多くの係数が強制的にゼロにされると、モデルがデータセットからランダムに削除された値のサブセットを予測するより良い仕事をすることを示しています。すべての係数がゼロのときに最良の交差検証済み予測エラー(ここでは「二項偏差」として測定)が達成された場合、リグレッサのサブセットの線形結合が結果の予測に役立つ可能性がないことを疑う必要があります。
これを確認するには、すべてのリグレッサから独立したランダムな応答を生成し、フィッティング手順をそれらに適用します。データセットをエミュレートする簡単な方法を次に示します。
n <- 570
k <- 338
set.seed(17)
X <- data.frame(matrix(floor(runif(n*(k+1), 0, 2)), nrow=n,
dimnames=list(1:n, c("y", paste0("x", 1:k)))))
データフレームにX
は、「y」という名前の1つのランダムバイナリ列と、他の338個のバイナリ列(名前は関係ありません)があります。私はこれらの変数に対して「y」を回帰するためにあなたのアプローチを使用しましたが、-注意してください-応答ベクトルy
とモデルマトリックスがx
一致することを確認しました(データに欠損値がある場合、それらは一致しない可能性があります) :
f <- y ~ . - 1 # cv.glmnet will include its own intercept
M <- model.frame(f, X)
x <- model.matrix(f, M)
y <- model.extract(M, "response")
fit <- cv.glmnet(x, y, family="binomial")
結果は著しくあなたのものに似ています:
plot(fit)
実際、これらの完全にランダムなデータを使用しても、Lassoは依然として9つの非ゼロ係数推定値を返します(構造上、正しい値がすべてゼロであることはわかっていますが)。しかし、完璧を期待するべきではありません。さらに、フィッティングは相互検証のためにデータのサブセットをランダムに削除することに基づいているため、通常、実行ごとに同じ出力が得られません。この例では、2回目の呼び出しで、ゼロ以外の係数が1つcv.glmnet
だけの近似が生成されます。このため、時間がある場合は、フィッティング手順を数回再実行し、どの係数推定値が常に非ゼロであるかを追跡することを常にお勧めします。これらのデータ(数百のリグレッサを含む)の場合、これを9回繰り返すのに数分かかります。
sim <- cbind(as.numeric(coef(fit)),
replicate(9, as.numeric(coef(cv.glmnet(x, y, family="binomial")))))
plot(1:k, rowMeans(sim[-1,] != 0) + runif(k, -0.025, 0.025),
xlab="Coefficient Index", ylab="Frequency not zero (jittered)",
main="Results of Repeated Cross-Validated Lasso Fits")
これらのリグレッサのうち8つは、近似の約半分でゼロ以外の推定値を持っています。それらの残りはゼロ以外の推定値を持つことはありません。これは、係数自体が本当にゼロの場合でも、ラッソが非ゼロの係数推定をどの程度含めるかを示しています。