リッジ回帰の実装:


17

私はPython / CモジュールでRidge Regressionを実装していますが、この「小さな」問題に遭遇しました。考え方は、「統計学習の要素」の65ページのプロットのように、ほぼ等間隔の有効自由度をサンプリングすることです。つまり、サンプル:

df(λ)=i=1pdi2di2+λ,
di2XTXdf(λmax)0df(λmin)=pλmax=ipdi2/cλmaxdi2cc=0.1λmin=0

タイトルが示唆するように、その後、Iはサンプルに必要λからのλminλmaxように、いくつかのスケールでdf(λ)に、たとえば、(約)サンプリングされますcからpまでの0.1間隔...これを行う簡単な方法はありますか?ニュートン・ラプソン法を使用して、各\ lambdaの方程式\ mathrm {df}(\ lambda)を解くことを考えましたが、これは、特にpが大きい場合に繰り返しを追加しすぎます。助言がありますか?cpdf(λ)λp


1
この関数は、\ lambda \ geq 0の減少する有理有理関数ですλ0。根は、特にダイアディックグリッド上で選択された場合、非常にすばやく見つける必要があります。
枢機

@枢機,、あなたはおそらく正しいです。ただし、可能であれば、「デフォルト」グリッドがあるかどうかを知りたいと思います。たとえば、\ lambda = log(s)\ lambda_ {max} / log(s_ {max})を実行してグリッドを取得しようとしましたλ=log(s)λmax/log(smax)。ここでs=(1,2,...,smax)、ある程度の自由度ではかなりうまく機能しましたが、df(λ)pとして爆発しました。これにより、λのグリッドを選択するためのきちんとした方法があるのではないかと思うようになりました。これが存在しない場合、私も喜んで知るでしょう(「良い方法は存在しない」ということを知って、コード内にニュートン・ラプソンメソッドを喜んで残すことができるので)。
ネストール

あなたが直面している潜在的な困難をよりよく理解するために、典型的な最悪の値は何ですか?固有値分布についてアプリオリに知っていることはありますか?p
枢機

@cardinal、私のアプリケーションでの典型的な値はから範囲ですが、できるだけ一般的にしたいです。固有値分布については、それほど多くありません。は、列に予測子を含む行列であり、常に直交するとは限りません。15 40 Xp1540X
ネスター

1
ニュートン-ラフソンは、典型的に根を見つける内の精度へ手順との小さな値。ステップを超えることはほとんどありません。大きな値の場合、最大ステップが必要になる場合があります。各ステップには計算が必要なので、計算の合計量は重要ではありません。実際、適切な開始値が選択されている場合、ステップ数はに依存していないようです(すべてのが平均に等しい場合に使用するものを選択します)。 3 4 p = 40 d f λ 6 30 O p p d i101234p=40df(λ)630O(p)pdi
whuber

回答:


19

これは長い答えです。それで、ここでそれの短編版を提供しましょう。

  • このルート発見の問題に対する優れた代数的解決法はないため、数値アルゴリズムが必要です。
  • 関数は多くの素晴らしいプロパティがあります。これらを利用して、各ルートへの単調な収束を保証するこの問題のためのニュートン法の特殊バージョンを作成できます。df(λ)
  • R最適化の試みがない脳死のコードでさえ、数秒でのサイズ100のグリッドを計算できます。慎重に記述されたコードは、これを少なくとも2〜3桁削減します。p=100000C

単調な収束を保証するために、以下に示す2つのスキームがあります。1つは以下に示す境界を使用します。これは、場合によってはニュートンステップまたは2つを節約するのに役立つようです。

:およびサイズ100の自由度の均一グリッド。固有値はパレート分布であるため、非常に歪んでいます。以下は、各ルートを見つけるためのニュートンのステップ数の表です。p=100000

# Table of Newton iterations per root.
# Without using lower-bound check.
  1  3  4  5  6 
  1 28 65  5  1 
# Table with lower-bound check.
  1  2  3 
  1 14 85 

このため、閉じた形の解は存在しないであろう一般的に、しかし、そこにある標準のルート発見方法を使用して非常に効果的かつ安全なソリューションを生成するために使用することができる構造の存在がたくさん。

深く掘り下げる前に、関数のいくつかのプロパティと結果を収集しましょう

df(λ)=i=1pdi2di2+λ.

プロパティ0:は有理関数です。(これは定義から明らかです。) 結果0:ルートを見つけるための一般的な代数解は存在しません。これは、次数同等の多項式根探索問題があるため、が極端に小さい(つまり5未満)場合、一般的な解は存在しません。そのため、数値法が必要になります。dfλ
df(λ)y=0pp

プロパティ1:関数は凸で、減少し。(派生物を取ります。) 結果1(a):ニュートンのルート検索アルゴリズムは、この状況で非常にうまく動作します。ましょう自由との所望度ですなわち、対応するルート。特に、我々はから始めた場合、任意の初期値(したがって、)、次に、ニュートンステップの反復のシーケンス収束する単調にユニークなソリューションdfλ0
yλ0y=df(λ0)λ1<λ0df(λ1)>yλ1,λ2,λ0
結果1(b):さらに、で開始する場合、最初のステップは、そこから前の結果まで単調に解になります(注意を参照)未満)。直観的には、この最後の事実は、ルートの右側から開始すると、微分はの凸性のために浅すぎるため、最初のニュートンステップはルートの左側のどこかに移動するためです。NB以来ありません負のための一般的な凸でλ1>λ0λ2λ0dfdfλ、これは、目的のルートの左側から開始することを好む強力な理由を提供します。そうでなければ、我々はニュートンステップは、非凸の部分のどこかに私たちを置くことが推定根、負の値が生じていないことを再確認する必要が。 結果1(c):あるのルートが見つかったら、最初の推測の保証としてとなるようにを使用して、からルートを検索します2番目のルートの左側。したがって、収束はそこから単調であることが保証されます。df
y1y2<y1λ1df(λ1)=y1

プロパティ2:「安全な」開始点を提供するための合理的な境界が存在します。凸引数とジェンセンの不等式を使用すると、次の境界があります 結果2:これは、を満たすルートが したがって、共通定数まで、調和平均と算術平均の間にルートを挟みました。

p1+λpdi2df(λ)pidi2idi2+pλ.
λ0df(λ0)=y
()11pidi2(pyy)λ0(1pidi2)(pyy).
di2

これは、すべてのについてであると仮定しています。そうでない場合は、正ののみを考慮し、を正の数で置き換えることにより、同じ境界が成立します。NB:すべての想定してであるため、で、境界は常に自明ではありません(たとえば、下限は常に負ではありません)。di>0idipdidf(0)=pdi>0y(0,p]

ここでの「典型的な」例のプロットであると。自由度のためにサイズ10のグリッドを重ねました。これらは、プロットの水平線です。緑の縦線は下限に対応しています。df(λ)p=400()

グリッドと境界を使用したdofプロットの例

アルゴリズムといくつかのサンプルRコード

自由の所望度のグリッド所与の非常に効率的なアルゴリズムに降順でそれらをソートした後であるが順次、次の出発点として前のルートを使用して、それぞれのルートを見つけます1.各ルートが次のルートの下限よりも大きいかどうかを確認することでこれをさらに調整でき、そうでない場合は、代わりに下限で次の反復を開始できます。y1,yn(0,p]

以下にR、最適化を試みていないのサンプルコードを示します。以下に見られるように、たとえR丁寧に言えば、ループでは恐ろしく、ひどく、ひどく遅いにもかかわらず、それはまだ非常に高速です。

# Newton's step for finding solutions to regularization dof.

dof <- function(lambda, d) { sum(1/(1+lambda / (d[d>0])^2)) }
dof.prime <- function(lambda, d) { -sum(1/(d[d>0]+lambda / d[d>0])^2) }

newton.step <- function(lambda, y, d)
{ lambda - (dof(lambda,d)-y)/dof.prime(lambda,d) }

# Full Newton step; Finds the root of y = dof(lambda, d).
newton <- function(y, d, lambda = NA, tol=1e-10, smart.start=T)
{
    if( is.na(lambda) || smart.start )
        lambda <- max(ifelse(is.na(lambda),0,lambda), (sum(d>0)/y-1)/mean(1/(d[d>0])^2))
    iter <- 0
    yn   <- Inf
    while( abs(y-yn) > tol )
    {
        lambda <- max(0, newton.step(lambda, y, d)) # max = pedantically safe
        yn <- dof(lambda,d)
        iter = iter + 1
    }
    return(list(lambda=lambda, dof=y, iter=iter, err=abs(y-yn)))
}

以下は、点のグリッドとベクトル(!ではありません)をとる最終的な完全なアルゴリズムです。di di2

newton.grid <- function(ygrid, d, lambda=NA, tol=1e-10, smart.start=TRUE)
{
    p <- sum(d>0)
    if( any(d < 0) || all(d==0) || any(ygrid > p) 
        || any(ygrid <= 0) || (!is.na(lambda) && lambda < 0) )
        stop("Don't try to fool me. That's not nice. Give me valid inputs, please.")
    ygrid <- sort(ygrid, decreasing=TRUE)
    out    <- data.frame()
    lambda <- NA
    for(y in ygrid)
    {
        out <- rbind(out, newton(y,d,lambda, smart.start=smart.start))
        lambda <- out$lambda[nrow(out)]
    }
    out
}

サンプル関数呼び出し

set.seed(17)
p <- 100000
d <- sqrt(sort(exp(rexp(p, 10)),decr=T))
ygrid <- p*(1:100)/100
# Should take ten seconds or so.
out <- newton.grid(ygrid,d)

この回答を参照できるように、質問をお気に入りに追加します。枢機posting、この詳細な分析を投稿していただきありがとうございます。
マクロ

素晴らしい答え:-)、提案と答えをありがとう。
ネスター

1

さらに、完全な正規化パスを効率的に計算する方法がいくつかあります。

  1. GPS
  2. glmnet
  3. gcdnet

上記はすべてRパッケージです。Pythonを使用しているためscikit-learnにはridge、lasso、elastic netの実装が含まれています。


1
olsR rmsパッケージの関数は、数値最適化を使用して、効果的なAICを使用して最適なペナルティを見つけることができます。ただし、常に簡単とは限らない最大のペナルティを提供する必要があります。
フランクハレル

0

以下のソースによると可能な代替案は次のようです:

閉じた形式のソリューション: df(λ)=tr(X(XX+λIp)1X)

ソルバーとして正規方程式を使用する場合、または分散共分散推定値を計算する場合は、すでにを計算している必要があります。このアプローチは、さまざまなで係数を推定する場合に最適に機能します。(XX+λIp)1λ

ソース:https : //onlinecourses.science.psu.edu/stat857/node/155

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.