2014-09-05 17 views
6

ich ein lineares Regressionsmodell auf 75% meiner Datensatz passen, die ~ 11000 Beobachtungen und 143 Variablen enthalten:R-Quadrat auf Testdaten

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

, und ich bekam einen R^2 von 0,43 . Ich habe dann versucht, auf meine Testdaten Vorhersage der Rest der Daten mit:

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

Ich möchte nun den R^2-Wert auf meine Testdaten berechnen. Gibt es einen einfachen Weg, das zu berechnen?

Danke

+0

See [diese ähnliche Frage] (http://stats.stackexchange.com/questions/863 14/höher-r-Quadrat-Wert-auf-Test-Daten-als-Training-Daten) auf CrossValidated. – nrussell

+0

@nrussell Danke; Ich habe die Formel in der erwähnten Frage verwendet und eine negative Zahl (-0,59) als meinen R^2-Wert erhalten. Ich habe Zweifel an meinem LM-Modell, sollte ich einen Schnittpunkt hinzufügen (ich nehme an, R tut es automatisch)? Warum bekomme ich dann negative R^2? –

+0

Haben Sie die Formel in der Frage oder die Formel im Kommentar unterhalb der Frage verwendet? Weil die Formel in der Frage falsch ist - siehe @ Panos 'Kommentar zu dieser Frage. – nrussell

Antwort

16

Es gibt ein paar Probleme hier. Erstens ist dies kein guter Weg, lm(...) zu verwenden. lm(...) ist für die Verwendung mit einem Datenrahmen vorgesehen, wobei die Formelausdrücke auf Spalten im df verweisen. So ist Ihre Daten unter der Annahme, in zwei Vektoren x und 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,]) 

Jetzt fit hat das Modell basierend auf dem Trainingssatz. Mit lm(...) können Sie auf diese Weise beispielsweise Vorhersagen ohne die gesamte Matrixmultiplikation erzeugen.

Das zweite Problem ist die Definition von R-Quadrat. Die conventional definition ist:

1 - SS.residuals/SS.total

für den Trainingssatz, und der Trainingssatz NUR,

SS.total = SS. + Regressions SS.residual

so

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

und deshalb

R.sq = SS.regression/SS.total

so R. sq ist der Bruchteil der Variabilität in dem Datensatz, der durch das Modell erklärt wird, und wird immer zwischen 0 und 1 liegen.

Sie können th sehen ist unterhalb.

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 

Aber diese nicht Arbeit mit dem Test-Set (zum Beispiel, wenn Sie die Prognosen von einem Modell machen).

In diesem erfundenen Beispiel gibt es nicht viel Unterschied, aber es ist sehr möglich, ein R-sq zu haben. Wert kleiner als 0 (wenn auf diese Weise definiert).

Wenn das Modell zum Beispiel ein sehr schlechter Prädiktor für den Testsatz ist, können die Residuen tatsächlich größer sein als die Gesamtvariation im Testset. Dies ist gleichbedeutend mit der Aussage, dass der Testsatz mit seinem Mittelwert besser modelliert wird als mit dem aus dem Trainingssatz abgeleiteten Modell.

Ich habe festgestellt, dass Sie die ersten drei Viertel Ihrer Daten als Trainingssatz verwenden, anstatt eine Stichprobe zu nehmen (wie in diesem Beispiel). Wenn die Abhängigkeit von y auf x nichtlinear ist und die x 's in Ordnung sind, dann könnten Sie ein negatives R-sq mit dem Testset erhalten.

In Bezug auf den Kommentar von OP unten ist eine Möglichkeit, das Modell mit einem Testset zu bewerten, der Vergleich des Modells mit dem mittleren quadratischen Fehler (MSE) außerhalb des Modells.

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

Wenn wir davon ausgehen, dass die Trainings- und Testsatzes sind beide normalerweise mit gleicher Varianz verteilt und mit Mitteln, die das gleiche Modell Formel folgen, dann sollte das Verhältnis haben eine F-Verteilung mit (n.train-2) und (n. Test-2) Freiheitsgrade. Wenn sich die MSEs auf der Grundlage eines F-Tests signifikant unterscheiden, passt das Modell die Testdaten gut an.

Haben Sie Ihre test.y und pred.y vs x ?? Dies allein wird dir viel erzählen.

+0

Vielen Dank für dieses aufwendige Beispiel. Was ist der beste Weg für mich, mein Modell auf dem Testdatensatz zu bewerten? –

+0

Ich habe gerade die Antwort bearbeitet, um sie in Übereinstimmung mit der konventionelleren Definition von R-sq zu bringen, aber die wichtigsten Schlussfolgerungen sind unverändert. Bezüglich deiner Frage, siehe meine Kommentare am Ende. – jlhoward

+0

Ausgezeichnete Antwort, wie immer. Ich habe meinen Zug/mein Test-Set gewechselt, als Sie vorgeschlagen haben, die Punkte zufällig zu sammeln. Ich bekomme für meinen Test kein negatives R-Quadrat mehr (vorausgesetzt, es hat eine Bedeutung). Ich habe auch das Training berechnet und MSEs getestet: 0,00056 für Training, 0,00036 für Test, Verhältnis ~ 0,65. Vergleichend mit diesem: 'qf (0,95, Länge (Zug) -2, Länge (Test) -2) = 1.036603 ', macht das Modell etwas. Bitte korrigieren Sie mich, wenn ich einen Fehler mache. –

2

Wenn Sie eine Funktion wünschen, die miscTools Paket eine rSquared Funktion hat.

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

Ich konnte dieses Paket nicht finden: Installation des Pakets in 'C: /Users/Haidar/Documents/R/win-library/3.1' (als 'lib' ist nicht spezifiziert) Warnung in den Installationspaketen: Paket 'micsTools 'ist nicht verfügbar (für R-Version 3.1.1) –

+0

@H_A, Tippfehler meinerseits, tut mir leid. Es ist 'miscTools'. – cdeterman

+0

Danke, es hat geklappt, ich bekomme immer noch einen negativen Wert für mein R^2, ich vermute, dass etwas mit meinem Regressions-/Vorhersageverfahren nicht stimmt. –

1

Die Berechnung von R-Quadrat auf den Testdaten ist ein wenig schwierig, da Sie sich daran erinnern müssen, was Ihre Grundlinie ist. Ihre Basisprojektion ist ein Mittelwert Ihrer Training Daten.

Daher Verlängerung des durch @jlhoward vorgesehen obiges Beispiel:

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 

Update: miscTools::rSquared() Funktion macht eine Annahme, die R-Quadrat auf dem gleichen Datensatz berechnet wird, auf das das Modell trainiert wird, wie es berechnet

yy <- y - mean(y) 

hinter den Kulissen in Linie 184 hier: https://github.com/cran/miscTools/blob/master/R/utils.R

Verwandte Themen