"lm" を使用せずに R で通常の最小二乗 ( OLS ) 推定値を計算したいのですが、これにはいくつかの理由があります。まず、「lm」は、私の場合はデータ サイズが問題であることを考慮して、必要のない多くのもの (適合値など) も計算します。第二に、OLS を別の言語で実装する前に R で自分自身を実装できるようにしたい (たとえば C で GSL を使用する)。
ご存知かもしれませんが、モデルは次のとおりです。Y=Xb+E; E〜N(0、シグマ^ 2)で。以下で詳しく説明するように、b は平均 (b0) と別の係数 (b1) の 2 つのパラメーターを持つベクトルです。最後に、実行する線形回帰ごとに、b1 (効果サイズ) の推定値、その標準誤差、sigma^2 (残差分散)、および R^2 (決定係数) の推定値が必要です。
これが私のデータです。N 個のサンプルがあります (例: 個人、N~=100)。サンプルごとに、Y 出力 (応答変数、Y~=10^3) と X ポイント (説明変数、X~=10^6) があります。Y出力を別々に扱いたい、つまり. Y 線形回帰を開始したい: 出力 1 用に 1 つ、出力 2 用に 1 つなど。それから...最終的にポイントXに。
これは、 「lm」の速度と、行列代数を介した OLS 推定の計算速度をチェックするための私のR コードです。
まず、ダミー データをシミュレートします。
nb.samples <- 10 # N
nb.points <- 1000 # X
x <- matrix(data=replicate(nb.samples,sample(x=0:2,size=nb.points, replace=T)),
nrow=nb.points, ncol=nb.samples, byrow=F,
dimnames=list(points=paste("p",seq(1,nb.points),sep=""),
samples=paste("s",seq(1,nb.samples),sep="")))
nb.outputs <- 10 # Y
y <- matrix(data=replicate(nb.outputs,rnorm(nb.samples)),
nrow=nb.samples, ncol=nb.outputs, byrow=T,
dimnames=list(samples=paste("s",seq(1,nb.samples),sep=""),
outputs=paste("out",seq(1,nb.outputs),sep="")))
すぐ下で使用される私自身の関数は次のとおりです。
GetResFromCustomLinReg <- function(Y, xi){ # both Y and xi are N-dim vectors
n <- length(Y)
X <- cbind(rep(1,n), xi) #
p <- 1 # nb of explanatory variables, besides the mean
r <- p + 1 # rank of X: nb of indepdt explanatory variables
inv.XtX <- solve(t(X) %*% X)
beta.hat <- inv.XtX %*% t(X) %*% Y
Y.hat <- X %*% beta.hat
E.hat <- Y - Y.hat
E2.hat <- (t(E.hat) %*% E.hat)
sigma2.hat <- (E2.hat / (n - r))[1,1]
var.covar.beta.hat <- sigma2.hat * inv.XtX
se.beta.hat <- t(t(sqrt(diag(var.covar.beta.hat))))
Y.bar <- mean(Y)
R2 <- 1 - (E2.hat) / (t(Y-Y.bar) %*% (Y-Y.bar))
return(c(beta.hat[2], se.beta.hat[2], sigma2.hat, R2))
}
組み込みの「lm」を使用したコードは次のとおりです。
res.bi.all <- apply(x, 1, function(xi){lm(y ~ xi)})
これが私のカスタム OLS コードです。
res.cm.all <- apply(x, 1, function(xi){apply(y, 2, GetResFromCustomLinReg, xi)})
上記の値でこの例を実行すると、次のようになります。
> system.time( res.bi.all <- apply(x, 1, function(xi){lm(y ~ xi)}) )
user system elapsed
2.526 0.000 2.528
> system.time( res.cm.all <- apply(x, 1, function(xi){apply(y, 2, GetResFromCustomLinReg, xi)}) )
user system elapsed
4.561 0.000 4.561
(そして、当然、N、X、Y を増やすと悪化します。)
もちろん、"lm" には応答行列 (y~xi) の各列を個別に "自動的に" フィッティングするという優れた特性がありますが、Y 回 (yi~xi ごとに) "適用" する必要があります。しかし、これが私のコードが遅い唯一の理由ですか? これを改善する方法を知っている人はいますか?
(非常に長い質問で申し訳ありませんが、最小限でありながら包括的な例を提供しようとしました。)
> sessionInfo()
R version 2.12.2 (2011-02-25)
Platform: x86_64-redhat-linux-gnu (64-bit)