randomForest
모델을 실행하면 모델을 기반으로 예측할 수 있습니다. 모델의 답이 얼마나 "확실"한지 알 수 있도록 각 예측의 예측 간격을 얻는 방법이 있습니까? 이것이 가능하다면 전체 모델에 대한 종속 변수의 변동성에 기초한 것일까 요? 아니면 특정 예측에 따른 특정 의사 결정 트리에 따라 더 넓고 좁은 간격을 가질 것입니까?
randomForest
모델을 실행하면 모델을 기반으로 예측할 수 있습니다. 모델의 답이 얼마나 "확실"한지 알 수 있도록 각 예측의 예측 간격을 얻는 방법이 있습니까? 이것이 가능하다면 전체 모델에 대한 종속 변수의 변동성에 기초한 것일까 요? 아니면 특정 예측에 따른 특정 의사 결정 트리에 따라 더 넓고 좁은 간격을 가질 것입니까?
답변:
이것은 부분적으로 @Sashikanth Dareddy에 대한 답변이며 (댓글에 맞지 않기 때문에) 원래 게시물에 대한 답변입니다.
예측 구간이 무엇인지 기억하십시오. 이는 미래 관측치가있을 것으로 예측하는 구간 또는 값 세트입니다. 일반적으로 예측 구간에는 너비를 결정하는 2 개의 주요 부분, 예측 평균에 대한 불확실성을 나타내는 부분 (또는 다른 매개 변수)이 있으며 이는 신뢰 구간 부분이며 해당 평균 주변의 개별 관측치의 변동성을 나타내는 부분입니다. 중앙 한계 정리로 인해 신뢰 구간이 상당히 강력하며 임의의 포리스트의 경우 부트 스트랩도 도움이됩니다. 그러나 예측 간격은 예측 변수, CLT 및 부트 스트래핑이 해당 부분에 영향을 미치지 않는 경우 데이터가 어떻게 분포되는지에 대한 가정에 전적으로 의존합니다.
해당 신뢰 구간도 더 넓을 경우 예측 구간은 더 넓어야합니다. 예측 구간의 너비에 영향을 미치는 다른 것은 등분 산에 대한 가정입니다. 이는 랜덤 포레스트 모델이 아니라 연구원의 지식에서 비롯된 것입니다.
예측 구간은 범주 결과에 적합하지 않습니다 (간격이 아닌 예측 세트를 수행 할 수 있지만 대부분 정보가 많지 않을 수 있습니다).
정확한 사실을 알고있는 데이터를 시뮬레이션하여 예측 구간과 관련된 문제를 확인할 수 있습니다. 다음 데이터를 고려하십시오.
set.seed(1)
x1 <- rep(0:1, each=500)
x2 <- rep(0:1, each=250, length=1000)
y <- 10 + 5*x1 + 10*x2 - 3*x1*x2 + rnorm(1000)
이 특정 데이터는 선형 회귀에 대한 가정을 따르며 임의의 포리스트에 적합합니다. "참"모델에서 두 예측 변수가 모두 0이고 평균이 10 인 경우 개별 점이 표준 편차가 1 인 정규 분포를 따른다는 것도 알고 있습니다. 이는 95 % 예측 구간이 이 점은 8에서 12 사이입니다 (실제로 8.04에서 11.96이지만 반올림하면 더 간단합니다). 예상되는 예측 간격은 이보다 넓어야하며 (완벽한 정보가 없으면 보상 할 너비가 추가됨)이 범위를 포함해야합니다.
회귀 간격을 살펴 보자.
fit1 <- lm(y ~ x1 * x2)
newdat <- expand.grid(x1=0:1, x2=0:1)
(pred.lm.ci <- predict(fit1, newdat, interval='confidence'))
# fit lwr upr
# 1 10.02217 9.893664 10.15067
# 2 14.90927 14.780765 15.03778
# 3 20.02312 19.894613 20.15162
# 4 21.99885 21.870343 22.12735
(pred.lm.pi <- predict(fit1, newdat, interval='prediction'))
# fit lwr upr
# 1 10.02217 7.98626 12.05808
# 2 14.90927 12.87336 16.94518
# 3 20.02312 17.98721 22.05903
# 4 21.99885 19.96294 24.03476
추정 된 평균 (신뢰 구간)에 약간의 불확실성이 있으며 8에서 12 범위의 넓은 (그러나 포함하는) 예측 구간을 제공합니다.
이제 개별 트리의 개별 예측을 기반으로 간격을 살펴 보겠습니다 (임의의 포리스트는 선형 회귀 분석의 가정 (이 데이터에 해당하는 것으로 알고 있음)에서 이익을 얻지 못하므로 더 넓을 것으로 예상합니다).
library(randomForest)
fit2 <- randomForest(y ~ x1 + x2, ntree=1001)
pred.rf <- predict(fit2, newdat, predict.all=TRUE)
pred.rf.int <- apply(pred.rf$individual, 1, function(x) {
c(mean(x) + c(-1, 1) * sd(x),
quantile(x, c(0.025, 0.975)))
})
t(pred.rf.int)
# 2.5% 97.5%
# 1 9.785533 13.88629 9.920507 15.28662
# 2 13.017484 17.22297 12.330821 18.65796
# 3 16.764298 21.40525 14.749296 21.09071
# 4 19.494116 22.33632 18.245580 22.09904
구간은 회귀 예측 구간보다 넓지 만 전체 범위를 포함하지는 않습니다. 여기에는 실제 값이 포함되므로 신뢰 구간으로 합법적 일 수 있지만 평균 (예측 된 값)이 어디에 있는지 만 예측하고 해당 평균 주위의 분포에 대한 추가 된 부분은 없습니다. x1과 x2가 모두 0 인 첫 번째 경우 구간이 9.7 아래로 떨어지지 않습니다. 이는 8로 내려가는 실제 예측 구간과는 매우 다릅니다. 새로운 데이터 포인트를 생성하면 여러 포인트가 생깁니다. 실제 및 회귀 구간에 있지만 임의의 포리스트 구간에 속하지는 않습니다.
예측 구간을 생성하려면 예측 된 평균 주변의 개별 점 분포에 대한 강력한 가정을 수행 한 다음 개별 트리 (부트 스트랩 신뢰 구간)에서 예측을 취한 다음 가정에서 임의의 값을 생성 할 수 있습니다 그 센터와의 배포. 생성 된 조각의 Quantile은 예측 간격을 형성 할 수 있습니다 (그러나 여전히 테스트 할 것이므로 프로세스를 여러 번 반복하고 결합해야 할 수도 있습니다).
다음은 해당 트리에서 추정 된 MSE를 기반으로 표준 편차를 사용하여 예측에 법선 (원래 데이터에 법선이 사용 된 것을 알고 있음) 편차를 추가하여이를 수행하는 예입니다.
pred.rf.int2 <- sapply(1:4, function(i) {
tmp <- pred.rf$individual[i, ] + rnorm(1001, 0, sqrt(fit2$mse))
quantile(tmp, c(0.025, 0.975))
})
t(pred.rf.int2)
# 2.5% 97.5%
# [1,] 7.351609 17.31065
# [2,] 10.386273 20.23700
# [3,] 13.004428 23.55154
# [4,] 16.344504 24.35970
이 간격에는 완벽한 지식을 기반으로하는 간격이 포함되므로 합리적으로 보입니다. 그러나 그들은 가정에 크게 의존 할 것입니다 (우리는 데이터가 어떻게 시뮬레이션되었는지에 대한 지식을 사용했기 때문에 가정이 유효하며 실제 데이터의 경우에는 유효하지 않을 수 있습니다). 이 방법을 완전히 신뢰하기 전에 실제 데이터와 비슷하지만 (진실을 알기 위해 시뮬레이션 된) 데이터와 비슷한 데이터에 대해 시뮬레이션을 여러 번 반복합니다.
나는 이것이 오래된 게시물이라는 것을 알고 있지만 이것에 대한 시뮬레이션을 실행했으며 결과를 공유 할 것이라고 생각했습니다.
@GregSnow 코드를 변경하면 다음과 같은 결과가 나타납니다.
set.seed(1)
x1 <- rep( 0:1, each=500 )
x2 <- rep( 0:1, each=250, length=1000 )
y <- 10 + 5*x1 + 10*x2 - 3*x1*x2 + rnorm(1000)
library(randomForest)
fit2 <- randomForest(y~x1+x2)
pred.rf <- predict(fit2, newdat, predict.all=TRUE)
pred.rf.int <- t(apply( pred.rf$individual, 1, function(x){
c( mean(x) + c(-1.96,1.96)*sd(x), quantile(x, c(0.025,0.975)) )}))
pred.rf.int
2.5% 97.5%
1 7.826896 16.05521 9.915482 15.31431
2 11.010662 19.35793 12.298995 18.64296
3 14.296697 23.61657 14.749248 21.11239
4 18.000229 23.73539 18.237448 22.10331
이제 @GregSnow와 같이 MSE가 제안한 것처럼 표준 편차가있는 예측에 법선 편차를 예측에 추가하여 생성 된 구간과이를 비교합니다.
pred.rf.int2 <- sapply(1:4, function(i) {
tmp <- pred.rf$individual[i,] + rnorm(1000, 0, sqrt(fit2$mse))
quantile(tmp, c(0.025, 0.975))
})
t(pred.rf.int2)
2.5% 97.5%
[1,] 7.486895 17.21144
[2,] 10.551811 20.50633
[3,] 12.959318 23.46027
[4,] 16.444967 24.57601
이 두 가지 접근 방식의 간격은 이제 매우 가깝습니다. 이 경우 오차 분포에 대한 세 가지 접근 방식의 예측 간격을 플로팅하면 다음과 같습니다.
이제 시뮬레이션을 다시 실행 해 봅시다. 이번에는 오차항의 분산이 증가합니다. 예측 구간 계산이 좋으면 위에서 얻은 것보다 더 넓은 구간으로 끝나야합니다.
set.seed(1)
x1 <- rep( 0:1, each=500 )
x2 <- rep( 0:1, each=250, length=1000 )
y <- 10 + 5*x1 + 10*x2 - 3*x1*x2 + rnorm(1000,mean=0,sd=5)
fit1 <- lm(y~x1+x2)
newdat <- expand.grid(x1=0:1,x2=0:1)
predict(fit1,newdata=newdat,interval = "prediction")
fit lwr upr
1 10.75006 0.503170 20.99695
2 13.90714 3.660248 24.15403
3 19.47638 9.229490 29.72327
4 22.63346 12.386568 32.88035
set.seed(1)
fit2 <- randomForest(y~x1+x2,localImp=T)
pred.rf.int <- t(apply( pred.rf$individual, 1, function(x){
c( mean(x) + c(-1.96,1.96)*sd(x), quantile(x, c(0.025,0.975)) )}))
pred.rf.int
2.5% 97.5%
1 7.889934 15.53642 9.564565 15.47893
2 10.616744 18.78837 11.965325 18.51922
3 15.024598 23.67563 14.724964 21.43195
4 17.967246 23.88760 17.858866 22.54337
pred.rf.int2 <- sapply(1:4, function(i) {
tmp <- pred.rf$individual[i,] + rnorm(1000, 0, sqrt(fit2$mse))
quantile(tmp, c(0.025, 0.975))
})
t(pred.rf.int2)
2.5% 97.5%
[1,] 1.291450 22.89231
[2,] 4.193414 25.93963
[3,] 7.428309 30.07291
[4,] 9.938158 31.63777
이제 두 번째 방법으로 예측 간격을 계산하는 것이 훨씬 더 정확하고 선형 회귀 분석에서 예측 간격과 매우 가까운 결과를 얻을 수 있음을 알 수 있습니다.
mean.rf <- pred.rf$aggregate
sd.rf <- mean(sqrt(fit2$mse))
pred.rf.int3 <- cbind(mean.rf - 1.96*sd.rf, mean.rf + 1.96*sd.rf)
pred.rf.int3
1 1.332711 22.09364
2 4.322090 25.08302
3 8.969650 29.73058
4 10.546957 31.30789
이것은 선형 모델 간격과 @GregSnow가 제안한 접근 방식과 매우 잘 맞습니다. 그러나 우리가 논의한 모든 방법의 기본 가정은 오류가 정규 분포를 따른다는 것입니다.
당신은 R을 사용하는 경우 당신은 쉽게 임의 숲 회귀의 예측에 대한 예측 간격을 생성 할 수 있습니다 : 그냥 패키지 사용 quantregForest
(이용 가능한 크랑을 ) 및 읽기 N. Meinshausen에 의해 종이 분위수 회귀 숲과 방법으로 추정 할 수있는 방법을 조건부 분위수에를 그들이 예측 구간을 구축하는 데 사용할 수 있습니다. R로 작업하지 않아도 매우 유익합니다!
randomForest로 쉽게 해결할 수 있습니다.
먼저 회귀 작업을 처리하겠습니다 (숲에 1000 그루의 나무가 있다고 가정). 이 predict
기능에는 개별 트리의 결과를 반환하는 옵션이 있습니다. 이것은 1000 개의 열 출력을 수신한다는 것을 의미합니다. 각 행에 대해 평균 1000 개의 열을 사용할 수 있습니다. 이것은 일반 출력 RF가 어떤 식 으로든 생성했을 것입니다. 이제 예측 구간을 얻기 위해 +/- 2 표준을 말합니다. 각 행마다 1000 값에서 +/- 2 std를 계산하기 만하면됩니다. 편차를 예측하고이를 상한 및 하한으로 만듭니다.
둘째, 분류의 경우 각 트리가 기본적으로 1 또는 0을 출력하고 1000으로 나눈 모든 1000 개의 나무에 대한 합계가 클래스 확률 (2 진 분류의 경우)을 제공한다는 것을 기억하십시오. 확률에 예측 간격을 두려면 최소값을 수정해야합니다. nodesize 옵션 (해당 옵션의 정확한 이름은 randomForest 문서화 참조) 값을 >> 1로 설정하면 개별 트리가 1과 0 사이의 숫자를 출력합니다. 이제부터 위에서 설명한 것과 동일한 프로세스를 반복 할 수 있습니다. 회귀 작업.
나는 그것이 의미가 있기를 바랍니다.
몇 가지 옵션을 시도했습니다 (이 모든 WIP).
실제로 종속 변수를 단일 값 대신 범위의 결과로 분류 문제로 만들었습니다. 내가 얻은 결과는 평범한 가치를 사용하는 것과 비교하여 열악했습니다. 나는이 접근법을 포기했다.
그런 다음 여러 분류 문제로 변환하여 각 범위의 하한 (모델의 결과가 하한을 넘을 지 여부)을 계산 한 다음 모든 모델을 실행했습니다 (~ 20). 결과를 결합하여 최종 답변을 범위로 얻습니다. 이것은 위의 1보다 잘 작동하지만 필요한만큼 좋지 않습니다. 나는 여전히이 접근법을 개선하기 위해 노력하고 있습니다.
나는 OOB와 일대일 추정치를 사용하여 모델의 상태를 결정합니다.
랜덤 포레스트 예측을위한 예측 구간을 구성하는 문제는 다음 백서에서 해결되었습니다.
Zhang, Haozhe, Joshua Zimmerman, Dan Nettleton 및 Daniel J. Nordman. "임의의 산림 예측 간격." 미국 통계 학자, 2019.
R 패키지 "rfinterval"은 CRAN에서 사용 가능한 구현입니다.
R 패키지 rfinterval 을 설치하려면 다음을 수행하십시오 .
#install.packages("devtools")
#devtools::install_github(repo="haozhestat/rfinterval")
install.packages("rfinterval")
library(rfinterval)
?rfinterval
빠른 시작:
train_data <- sim_data(n = 1000, p = 10)
test_data <- sim_data(n = 1000, p = 10)
output <- rfinterval(y~., train_data = train_data, test_data = test_data,
method = c("oob", "split-conformal", "quantreg"),
symmetry = TRUE,alpha = 0.1)
### print the marginal coverage of OOB prediction interval
mean(output$oob_interval$lo < test_data$y & output$oob_interval$up > test_data$y)
### print the marginal coverage of Split-conformal prediction interval
mean(output$sc_interval$lo < test_data$y & output$sc_interval$up > test_data$y)
### print the marginal coverage of Quantile regression forest prediction interval
mean(output$quantreg_interval$lo < test_data$y & output$quantreg_interval$up > test_data$y)
데이터 예 :
oob_interval <- rfinterval(pm2.5 ~ .,
train_data = BeijingPM25[1:1000, ],
test_data = BeijingPM25[1001:2000, ],
method = "oob",
symmetry = TRUE,
alpha = 0.1)
str(oob_interval)
score
성능을 평가하는 기능이 있습니다. 출력은 포리스트에있는 나무의 과반수 투표를 기준으로하므로 분류의 경우 투표 분포에 따라이 결과가 사실 일 가능성이 있습니다. 그래도 회귀에 대해 잘 모르겠습니다 .... 어떤 라이브러리를 사용하십니까?