2014-09-05 113 views
6

我裝配在我的數據集的75%,其包括線性迴歸模型〜11000次的觀測和143個變量:R平方測試數據

gl.fit <- lm(y[1:ceiling(length(y)*(3/4))] ~ ., data= x[1:ceiling(length(y)*(3/4)),]) #3/4 for training

,並收到R^2 0.43 。然後我嘗試使用其他數據對我的測試數據來預測:

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的值。有沒有簡單的方法來計算?

如果你想有一個功能,miscTools包有rSquared功能謝謝

+0

請參閱[此類似的問題(http://stats.stackexchange.com/questions/863 CrossValidated上的14/higher-r-squared-on-test-data-than-training-data)。 – nrussell 2014-09-05 17:41:13

+0

@nrussell謝謝;我在提到的問題中使用了公式,並得到了一個負數(-0.59)作爲我的R^2值。我對我的lm模型有疑問,我應該添加一個攔截(我認爲R會自動執行)?那爲什麼我會得到負面的R^2呢? – 2014-09-05 18:06:37

+0

您是否在問題下面的評論中使用公式或註釋中的公式?因爲問題中的公式不正確 - 請參閱@Panos對該問題的評論。 – nrussell 2014-09-05 18:41:21

回答

16

這裏有幾個問題。首先,這不是使用lm(...)的好方法。 lm(...)旨在與數據框一起使用,公式表達式引用df中的列。因此,假設你的數據在兩個向量xy

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(...)這種方式可以讓您例如生成預測,而不用全部矩陣乘法。

第二個問題是R平方的定義。所述conventional definition是:

1 - SS.residuals/SS.total

對於訓練集,和訓練ONLY設置,

SS.total = SS。迴歸+ SS.residual

so

SS.regression = SS.total - SS.residual,

因此

R.sq = SS.regression/SS.total

所以R. sq是由模型解釋的數據集中變化的分數,並且始終在0和1之間。

您可以看到th在下面。

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-sq。值小於0(當以這種方式定義時)。

例如,如果模型對於測試集來說是一個非常差的預測變量,那麼殘差實際上可能大於測試集中的總變化量。這相當於說,使用平均值來比使用從訓練集派生的模型更好地模擬測試集。

我注意到,你使用你的數據的前四個季度作爲訓練集,而不是隨機抽樣(如本例中)。如果yx的依賴是非線性的,並且x是有序的,那麼您可以得到具有測試集的負R-sq。

關於下面的OP評論,一種用測試集評估模型的方法是通過比較模型內模型和模型外均方誤差(MSE)。

mse.train <- summary(fit)$sigma^2 
mse.test <- sum((test.pred - test.y)^2)/(nrow(df)-length(train)-2) 

如果我們假設訓練和測試組都通常與相同的方差分佈並且具有遵循相同的模型公式的裝置,則該比率應該有一個F-分佈(n.train-2 )和(n.test-2)自由度。如果MSE基於F測試顯着不同,那麼該模型確實適合測試數據,而不是而不是

你有沒有繪製你的test.y和pred.y和x?只有這一點會告訴你很多。

+0

非常感謝你爲這個精心設計的例子。在這種情況下,在測試數據集上評估我的模型的最佳方式是什麼? – 2014-09-05 21:49:18

+0

我剛剛編輯了這個響應,使它與更傳統的R-sq定義保持一致,但主要結論未變。關於你的問題,請看我最後的評論。 – jlhoward 2014-09-05 22:17:56

+0

像往常一樣的優秀答案。我按照你的建議改變了我的火車/測試組,隨機抽取積分。我不再爲我的測試獲得負R平方(假設它有意義)。我還計算了訓練和測試中小企業:訓練0.00056,測試0.00036,比率約0.65。與此相比:'qf(0.95,長度(列車)-2,長度(測試)-2)= 1.036603',模型正在做一些事情。如果我犯了錯,請糾正我。 – 2014-09-05 22:54:24

2

require(miscTools) 
r2 <- rSquared(ytest, resid = ytest-yhat) 
+0

我找不到這個軟件包:在'C:/Users/Haidar/Documents/R/win-library/3.1'中安裝軟件包' (as'lib'is unspecified) install.packages中的警告: package'micsTools '不可用(對於R版本3.1.1) – 2014-09-05 18:02:29

+0

@H_A,我的錯字,對不起。它是'miscTools'。 – cdeterman 2014-09-05 19:10:53

+0

謝謝,它的工作原理,我仍然對我的R^2產生負面影響,我懷疑我的迴歸/預測程序有問題。 – 2014-09-05 19:31:06

1

計算測試數據的R平方有點棘手,因爲您必須記住您的基線是什麼。您的基線預測是您的培訓數據的平均值。

因此,延伸通過@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平方是對同一數據集,在該模型被訓練計算的假設,因爲它計算

yy <- y - mean(y) 

在這裏線184幕後:https://github.com/cran/miscTools/blob/master/R/utils.R