ラッ疎回帰のCVがガチャなので禁を犯してcv.foldsを書き換える記事

最近ビッグデータ占い師の研究をしており、関数型言語Rと格闘しています。

LASSO回帰という便利な回帰があります。
Ridge回帰との主な違いとして、Ridgeは名詞、LASSOは略語*1です。
高次元空間ではL1-normが1となる点の集合が成す多面体の角っこがトゲトゲするので、二乗和誤差の等高線が軸上でぶつかりやすくなるため、パラメータの多くが0になります。

glmnetとlarsという2種類のパッケージがあるが、前者はなんかR3.0.3では使えなかった。
後者は正則化項の係数を交差検定で決定できるcv.larsなる関数がある。これで自動的に決定したい。

N <- 10  # N-fold cross validation
cv.result <- cv.lars( ....., N )

で色々計算し、

lambda <- cv.result$index[which.min(cv.result$cv)]

で最適な生息加工の係数lambdaを得る。
cv.larsは、入力された事例を乱数に基づいてN個のグループに分割し、N分割交差確認でパラメータを決定する。
入力事例が少ないと、ランダムゆえ推定値が安定しない。交差検定ガチャ。なんとかしたい。

普通に考えて事例数Dのデータに対して、D分割をすれば、分割にランダム要素がなくなるため、結果も安定する。

でも以下のようにしてcv.larsが内部で呼ぶcv.foldsを書き換えても良さそう。

tmp <- function(n, folds) {
  comb <- combn(1:n, 1)
  rv <- list()
  for (i in 1:ncol(comb)) {
    rv[[sprintf("%d", i)]] <- as.numeric(comb[,i])
  }
  return(rv)
}

unlockBinding("cv.folds", environment(fun=lars))
assignInNamespace("cv.folds", tmp, ns="lars", envir=environment(fun=lars))
assign("cv.folds", tmp, envir=environment(lars))
lockBinding("cv.folds", environment(lars))
cv.folds <- tmp  # 今のnamespaceにも残滓が残るので。

ちなみに後半部では、名前空間を†解錠†してcv.foldsを†リライト†しています。

combnの第二引数を1から整数Kへ書き換えると、データ集合からKこの元を取り出す全ての組み合わせをfold-out集合とするようになる。
もはや分割ではない(これも交差確認と呼べるのか?)。第二引数を1から2へ変えて試しても、結果が一致しない。何がどう違うんだろう。

アイスコーヒーおいしい〜

*1:LASSO: least absolute shrinkage and selection operator