約11000の観測値と143の変数を含むデータセットの75%に線形回帰モデルを当てはめます。
gl.fit <- lm(y[1:ceiling(length(y)*(3/4))] ~ ., data= x[1:ceiling(length(y)*(3/4)),]) #3/4 for training
、そして私は0.43のR ^ 2を得ました。次に、残りのデータを使用してテストデータを予測してみました。
ytest=y[(ceiling(length(y)*(3/4))+1):length(y)] x.test <- cbind(1,x[(ceiling(length(y)*(3/4))+1):length(y),]) #The rest for test yhat <- as.matrix(x.test)%*%gl.fit$coefficients #Calculate the predicted values
ここで、テストデータのR ^ 2値を計算したいと思います。それを計算する簡単な方法はありますか?
ありがとうございました
ここにはいくつかの問題があります。まず、これはlm(...)
を使用する良い方法ではありません。 lm(...)
は、データフレームで使用することを目的としており、式はdfの列を参照します。したがって、データが2つのベクトルx
とy
にあると仮定すると、
_set.seed(1) # for reproducible example
x <- 1:11000
y <- 3+0.1*x + rnorm(11000,sd=1000)
df <- data.frame(x,y)
# training set
train <- sample(1:nrow(df),0.75*nrow(df)) # random sample of 75% of data
fit <- lm(y~x,data=df[train,])
_
これでfit
はトレーニングセットに基づくモデルを持ちます。このようにlm(...)
を使用すると、たとえば、行列の乗算をすべて行わずに予測を生成できます。
2番目の問題は、R二乗の定義です。 従来の定義 は次のとおりです。
1-SS.residuals/SS.total
トレーニングセット()およびトレーニングセットのみ、
SS.total = SS.regression + SS.residual
そう
SS.regression = SS.total-SS.residual、
したがって
R.sq = SS.regression/SS.total
したがって、R.sqはモデルによって説明されるデータセットの変動性の割合であり、常に0から1の間になります。
あなたはこれを以下で見ることができます。
_SS.total <- with(df[train,],sum((y-mean(y))^2))
SS.residual <- sum(residuals(fit)^2)
SS.regression <- sum((fitted(fit)-mean(df[train,]$y))^2)
SS.total - (SS.regression+SS.residual)
# [1] 1.907349e-06
SS.regression/SS.total # fraction of variation explained by the model
# [1] 0.08965502
1-SS.residual/SS.total # same thing, for model frame ONLY!!!
# [1] 0.08965502
summary(fit)$r.squared # both are = R.squared
# [1] 0.08965502
_
ただし、これはテストセットでは機能しません(たとえば、モデルから予測を行う場合)。
_test <- -train
test.pred <- predict(fit,newdata=df[test,])
test.y <- df[test,]$y
SS.total <- sum((test.y - mean(test.y))^2)
SS.residual <- sum((test.y - test.pred)^2)
SS.regression <- sum((test.pred - mean(test.y))^2)
SS.total - (SS.regression+SS.residual)
# [1] 8958890
# NOT the fraction of variability explained by the model
test.rsq <- 1 - SS.residual/SS.total
test.rsq
# [1] 0.0924713
# fraction of variability explained by the model
SS.regression/SS.total
# [1] 0.08956405
_
この不自然な例では大きな違いはありませんが、R平方を持つことは非常に可能です。 0未満の値(この方法で定義した場合)。
たとえば、モデルがテストセットで非常に貧弱な予測子である場合、残差は実際にはテストセットの全変動よりも大きくなる可能性があります。これは、トレーニングセットから派生したモデルを使用するよりも、平均を使用してテストセットがより適切にモデル化されていると言うことと同じです。
(この例のように)ランダムなサンプルを取得するのではなく、データの最初の4分の3をトレーニングセットとして使用していることに気付きました。 y
のx
への依存性が非線形であり、x
が正しい場合、テストセットで負のR-sqを取得できます。
以下のOPのコメントに関して、テストセットでモデルを評価する1つの方法は、モデル内とモデル外の平均二乗誤差(MSE)を比較することです。
_mse.train <- summary(fit)$sigma^2
mse.test <- sum((test.pred - test.y)^2)/(nrow(df)-length(train)-2)
_
トレーニングセットとテストセットの両方が通常同じ分散で分布し、同じモデル式に従う平均を持つと仮定すると、比率は(n.train-2)と(n.test-)のF分布を持つ必要があります。 2)自由度。 F検定に基づいてMSEが大幅に異なる場合、モデルはテストデータにうまく適合しません。
Test.yとpred.yとxをプロットしましたか?これだけで多くのことがわかります。
ベースラインとは何かを覚えておかなければならないので、テストデータのR-2乗を計算するのは少し難しいです。ベースライン予測は、トレーニングデータの平均です。
したがって、上記の@jlhowardによって提供された例を拡張します。
_SS.test.total <- sum((test.y - mean(df[train,]$y))^2)
SS.test.residual <- sum((test.y - test.pred)^2)
SS.test.regression <- sum((test.pred - mean(df[train,]$y))^2)
SS.test.total - (SS.test.regression+SS.test.residual)
# [1] 11617720 not 8958890
test.rsq <- 1 - SS.test.residual/SS.test.total
test.rsq
# [1] 0.09284556 not 0.0924713
# fraction of variability explained by the model
SS.test.regression/SS.test.total
# [1] 0.08907705 not 0.08956405
_
更新:miscTools::rSquared()
関数は、R-squaredが計算されるときに、モデルがトレーニングされるのと同じデータセットで計算されると仮定します
_yy <- y - mean(y)
_
ここの184行目の舞台裏: https://github.com/cran/miscTools/blob/master/R/utils.R
関数が必要な場合は、miscTools
パッケージにrSquared
関数があります。
require(miscTools)
r2 <- rSquared(ytest, resid = ytest-yhat)
(アウトオブ)サンプルでR2メジャーを使用すると、R2の解釈の特定の側面が失われます。
Rを使用する場合は、関数modelr::rsquare
をお勧めします。これは、トレーニングサンプルではなく、テストサンプルのSSR合計を使用することに注意してください(一部の人々が主張しているようです)。
ここでは、トレーニングデータに3つのポイントしかない例を取り上げます。したがって、モデルが不良であり、サンプル外のパフォーマンスが低いという高いリスクがあります。実際、R2が負であることがわかります!
library(modelr)
train <- mtcars[c(1,3,4),]
test <- mtcars[-c(1,3,4),]
mod <- lm(carb ~ drat, data = train)
列車のデータを計算する:
## train
y_train <- train$carb
SSR_y_train <- sum((y_train-mean(y_train))^2)
cor(fitted(mod), y_train)^2
#> [1] 0.2985092
rsquare(mod, train)
#> [1] 0.2985092
1-sum(residuals(mod)^2)/SSR_y_train
#> [1] 0.2985092
テストデータで計算:
## test
pred_test <- predict(mod, newdata = test)
y_test <- test$carb
SSR_y_test <- sum((y_test-mean(y_test))^2)
cor(pred_test, y_test)^2
#> [1] 0.01737236
rsquare(mod, test)
#> [1] -0.6769549
1- 28* var(pred_test-y_test)/SSR_y_train
#> [1] -19.31621
1- 28* var(pred_test-y_test)/SSR_y_test
#> [1] -0.6769549