これは長い答えです。それで、ここでそれの短編版を提供しましょう。
- このルート発見の問題に対する優れた代数的解決法はないため、数値アルゴリズムが必要です。
- 関数は多くの素晴らしいプロパティがあります。これらを利用して、各ルートへの単調な収束を保証するこの問題のためのニュートン法の特殊バージョンを作成できます。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=1pd2id2i+λ.
プロパティ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+λp∑d−2i≤df(λ)≤p∑id2i∑id2i+pλ.
λ0df(λ0)=y11p∑id−2i(p−yy)≤λ0≤(1p∑id2i)(p−yy).(⋆)
d2i
これは、すべてのについてであると仮定しています。そうでない場合は、正ののみを考慮し、を正の数で置き換えることにより、同じ境界が成立します。NB:すべての想定してであるため、で、境界は常に自明ではありません(たとえば、下限は常に負ではありません)。di>0idipdidf(0)=pdi>0y∈(0,p]
ここでの「典型的な」例のプロットであると。自由度のためにサイズ10のグリッドを重ねました。これらは、プロットの水平線です。緑の縦線は下限に対応しています。df(λ)p=400(⋆)
アルゴリズムといくつかのサンプル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 d2i
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)