非負のリッジ回帰を実行するにはどうすればよいですか?非負の投げ縄はで利用できますscikit-learn
が、リッジの場合、ベータの非負を強制できません。実際、負の係数を取得しています。これがなぜか誰か知っていますか?
また、通常の最小二乗法でリッジを実装できますか?これを別の質問に移動しました:OLS回帰の観点からリッジ回帰を実装できますか?
非負のリッジ回帰を実行するにはどうすればよいですか?非負の投げ縄はで利用できますscikit-learn
が、リッジの場合、ベータの非負を強制できません。実際、負の係数を取得しています。これがなぜか誰か知っていますか?
また、通常の最小二乗法でリッジを実装できますか?これを別の質問に移動しました:OLS回帰の観点からリッジ回帰を実装できますか?
回答:
「これがなぜなのか知っている人はいますか?」に対するかなりの気候への答えは、単に負でないリッジ回帰ルーチンを実装するのに十分なほど気にしていないということです。主な理由の1つは、人々がすでに負でないエラスティックネットルーチン(たとえば、こことここ)の実装を開始していること です。エラスティックネットには、特殊なケースとしてリッジ回帰が含まれています(本質的にLASSO部分にゼロの重みを設定しています)。これらの作品は比較的新しいため、scikit-learnまたは同様の汎用パッケージにまだ組み込まれていません。コードについては、これらの論文の著者に問い合わせることをお勧めします。
編集:
@amoebaと私がコメントで議論したように、これの実際の実装は比較的単純です。たとえば、次のような回帰問題があるとします。
ここで、とはどちらも次のような標準法線です:。標準化された予測変数を使用しているため、後で正規化する必要がないことに注意してください。簡単にするため、切片も含めません。標準の線形回帰を使用して、この回帰問題をすぐに解決できます。したがって、Rでは次のようになります。
rm(list = ls());
library(MASS);
set.seed(123);
N = 1e6;
x1 = rnorm(N)
x2 = rnorm(N)
y = 2 * x1 - 1 * x2 + rnorm(N,sd = 0.2)
simpleLR = lm(y ~ -1 + x1 + x2 )
matrixX = model.matrix(simpleLR); # This is close to standardised
vectorY = y
all.equal(coef(simpleLR), qr.solve(matrixX, vectorY), tolerance = 1e-7) # TRUE
最後の行に注目してください。ほとんどすべての線形回帰ルーチンは、QR分解を使用してを推定します。同じことをリッジ回帰問題にも使用したいと思います。この時点で、@ whuberによるこの投稿を読んでください。この手順を正確に実装します。つまり、元の設計行列に対角行列と応答ベクトルにゼロをます。このようにして、元のリッジ回帰問題をとして 再表現できここで、拡張バージョンを象徴します。これらのノートのスライド18から19もチェックして、完全であることを確認してください。したがって、Rでは次のようになります。
myLambda = 100;
simpleRR = lm.ridge(y ~ -1 + x1 + x2, lambda = myLambda)
newVecY = c(vectorY, rep(0, 2))
newMatX = rbind(matrixX, sqrt(myLambda) * diag(2))
all.equal(coef(simpleRR), qr.solve(newMatX, newVecY), tolerance = 1e-7) # TRUE
そしてそれは動作します。さて、リッジ回帰の部分を得ました。ただし、別の方法で解決することもできます。これは、残差二乗和がコスト関数である最適化問題として定式化し、それに対して最適化することもできます。。案の定、それを行うことができます。
myRSS <- function(X,y,b){ return( sum( (y - X%*%b)^2 ) ) }
bfgsOptim = optim(myRSS, par = c(1,1), X = newMatX, y= newVecY,
method = 'L-BFGS-B')
all.equal(coef(simpleRR), bfgsOptim$par, check.attributes = FALSE,
tolerance = 1e-7) # TRUE
予想通り再び機能します。だから今私たちはただ欲しい:ここで。これは単に同じ最適化問題ですが、解が負にならないように制約されています。
bfgsOptimConst = optim(myRSS, par = c(1,1), X=newMatX, y= newVecY,
method = 'L-BFGS-B', lower = c(0,0))
all(bfgsOptimConst$par >=0) # TRUE
(bfgsOptimConst$par) # 2.000504 0.000000
これは、元の非負のリッジ回帰タスクが、単純な制約付き最適化問題として再公式化することで解決できることを示しています。いくつかの警告:
optim
のL-BFGS-Bの引数を。範囲を受け入れるのは、最も一般的なRソルバーです。きっと数十の優れたソルバーが見つかるはずです。ポイント5のコード:
myRidgeRSS <- function(X,y,b, lambda){
return( sum( (y - X%*%b)^2 ) + lambda * sum(b^2) )
}
bfgsOptimConst2 = optim(myRidgeRSS, par = c(1,1), X = matrixX, y = vectorY,
method = 'L-BFGS-B', lower = c(0,0), lambda = myLambda)
all(bfgsOptimConst2$par >0) # TRUE
(bfgsOptimConst2$par) # 2.000504 0.000000
エラスティックネットを実装するRパッケージのglmnet、つまりlassoとridgeはこれを可能にします。パラメータlower.limits
とを使用するとupper.limits
、各ウェイトの最小値または最大値を個別に設定できるため、下限を0に設定すると、非負の弾性ネット(投げ縄/尾根)が実行されます。
pythonラッパーhttps://pypi.python.org/pypi/glmnet/2.0.0もあります。
解決しようとしていることを思い出してください:
以下と同等です。
さらに代数を使って:
疑似Pythonでの解決策は、単に次のようにすることです。
Q = A'A + lambda*I
c = - A'y
x,_ = scipy.optimize.nnls(Q,c)
参照:形式の正則化器を使用して、非負の最小二乗をスパースする方法は?
もう少し一般的な答えについては。