2011-12-07 3 views
3

R randomForest 패키지가 분류 관계를 해결하는 데 사용하는 메커니즘을 알고 있습니까? 즉, 트리가 두 개 이상의 클래스에서 동등한 투표로 끝나는 경우?R randomForest 투표 타이 브레이크

문서에 넥타이가 무작위로 분리되었다고 나와 있습니다. 그러나 일련의 데이터 집합에 대해 모델을 훈련시킨 다음 단일 모델의 유효성 검사 데이터로 여러 번 점수를 매기면 동점 계층 결정은 50/50이 아닙니다. model가 랜덤 포레스트 객체이며 bad_ind

cnum = vector("integer",1000) 
for (i in 1:length(cnum)){ 
    cnum[i] = (as.integer(predict(model,val_x[bad_ind[[1]],]))) 
} 
cls = unique(cnum) 
for (i in 1:length(cls)){ 
    print(length(which(cnum == cls[i]))) 
} 

클래스 표를 연결 한 특징 벡터에 대한 인덱스 단지 목록입니다. 위의 코드를 사용하여 테스트 한 결과 두 묶음 클래스 간의 분포는 90/10에 가깝습니다.

또한 홀수 개의 트리를 사용하는 권장 사항은 일반적으로 세 번째 클래스가 몇 개의 투표를 가져 와서 두 개의 다른 클래스를 묶어 두지 않고 작동하지 않습니다.

투표 결과가 50/50을 넘는 rf 나무가있는이 경우가 좋지 않습니까?

업데이트 : 인해 숲을 교육하지만, (슬롭 죄송합니다) 다음 코드의 임의 특성으로 예를 제공하기 어려운 숲이 명확한를 판별 할 수있는 예를 생산 결국합니다 와 함께 승자. 넥타이가 고장 났을 때 테스트 결과 66 %/33 % 분포를 보였습니다. 나는 이것이 50 %/50 %가 될 것으로 예상했습니다.

library(randomForest) 
x1 = runif(200,-4,4) 
x2 = runif(200,-4,4) 
x3 = runif(1000,-4,4) 
x4 = runif(1000,-4,4) 
y1 = dnorm(x1,mean=0,sd=1) 
y2 = dnorm(x2,mean=0,sd=1) 
y3 = dnorm(x3,mean=0,sd=1) 
y4 = dnorm(x4,mean=0,sd=1) 
train = data.frame("v1"=y1,"v2"=y2) 
val = data.frame("v1"=y3,"v2"=y4) 
tlab = vector("integer",length(y1)) 
tlab_ind = sample(1:length(y1),length(y1)/2) 
tlab[tlab_ind]= 1 
tlab[-tlab_ind] = 2 
tlabf = factor(tlab) 
vlab = vector("integer",length(y3)) 
vlab_ind = sample(1:length(y3),length(y3)/2) 
vlab[vlab_ind]= 1 
vlab[-vlab_ind] = 2 
vlabf = factor(vlab) 
mm <- randomForest(x=train,y=tlabf,ntree=100) 
out1 <- predict(mm,val) 
out2 <- predict(mm,val) 
out3 <- predict(mm,val) 
outv1 <- predict(mm,val,norm.votes=FALSE,type="vote") 
outv2 <- predict(mm,val,norm.votes=FALSE,type="vote") 
outv3 <- predict(mm,val,norm.votes=FALSE,type="vote") 

(max(as.integer(out1)-as.integer(out2)));(min(as.integer(out1)-as.integer(out2))) 
(max(as.integer(out2)-as.integer(out3)));(min(as.integer(out2)-as.integer(out3))) 
(max(as.integer(out1)-as.integer(out3)));(min(as.integer(out1)-as.integer(out3))) 

bad_ind = vector("list",0) 
for (i in 1:length(out1)) { 
#for (i in 1:100) { 
    if (out1[[i]] != out2[[i]]){ 
    print(paste(i,out1[[i]],out2[[i]],sep = "; ")) 
    bad_ind = append(bad_ind,i) 
    } 
} 

for (j in 1:length(bad_ind)) { 
    cnum = vector("integer",1000) 
    for (i in 1:length(cnum)) { 
    cnum[[i]] = as.integer(predict(mm,val[bad_ind[[j]],])) 
    } 
    cls = unique(cnum) 
    perc_vals = vector("integer",length(cls)) 
    for (i in 1:length(cls)){ 
    perc_vals[[i]] = length(which(cnum == cls[i])) 
    } 
    cat("for feature vector ",bad_ind[[j]]," the class distrbution is: ",perc_vals[[1]]/sum(perc_vals),"/",perc_vals[[2]]/sum(perc_vals),"\n") 
} 

업데이트 : 이것은 랜덤 포레스트의 버전 4.6-3에 고정되어야한다.

+0

이 동작을 보여주는 작은 재현 가능한 예제를 제공 할 수 있습니까? – joran

+0

코드의 마지막 부분에 bad_ind 행 다음에 어딘가에 오류가 있습니다. – Benjamin

+0

버그의 위치를 ​​알려주시겠습니까? 그냥 (라이브러리 상단에)'library (randomForest)'줄을 추가했지만 코드를 잘라내어 붙이면 R의 새로운 인스턴스가 나옵니다. – Nate

답변

1

이 버전 4.6에서 해결해야 -3 of randomForest.

1

전체 예제가 없으면 이것이 유일한 문제인지 아닌지 알기는 어렵지만 위에 포함 된 코드의 한 가지 분명한 문제는 모델 피팅 단계 - 예측 단계 만 복제한다는 것입니다. 임의의 타이 브레이킹의 선택은 모델에 맞을 때 수행됩니다. 따라서 해당 부분을 다시 실행하지 않으면 predict() 호출은 동일한 클래스에 더 높은 확률/득표를 계속 제공합니다.

정확하게 원하는 동작을 보여줍니다하는 대신,이 예제를보십시오 :

library(randomForest) 
df = data.frame(class=factor(rep(1:2, each=5)), X1=rep(c(1,3), each=5), X2=rep(c(2,3), each=5)) 
fitTie <- function(df) { 
    df.rf <- randomForest(class ~ ., data=df) 
    predict(df.rf, newdata=data.frame(X1=1, X2=3), type='vote')[1] 
} 
> df 
    class X1 X2 
1  1 1 2 
2  1 1 2 
3  1 1 2 
4  1 1 2 
5  1 1 2 
6  2 3 3 
7  2 3 3 
8  2 3 3 
9  2 3 3 
10  2 3 3 

> mean(replicate(10000, fitTie(df))) 
[1] 0.49989 
+0

응답 해 주셔서 감사합니다.하지만 저는 두 가지 다른 배포판에 대해 이야기하고 있다고 생각합니다. 의도적으로 rf 모델을 재교육하지 않습니다. 정의에 따라 rf는 결정적이지 않습니다. 그러나 랜덤 포리스트가 확실한 승자가없는 경우를 제외하고는 결과 모델이 완전히 결정적이어야합니다. randomForest 문서에 따르면이 경우는 무작위로 선택하여 처리한다고합니다. 이것이 균일 한 분포라고 가정하면, 50/50까지 끝나야합니다. 이 사례를 처리하는 방식은 일부 실험에서 결과 정확도에 영향을 미칠 수 있습니다. – Nate

1

난 당신이 관계의 그런 작은 수를 가지고 있기 때문에 이런 일이 생각합니다. 동전을 10 번 뒤집어 넣는 것과 같은 문제가 있습니다. 머리 다섯 꼬리 5 개를 감을 수는 없습니다.

아래의 사례 1에서, 동점은 각 클래스마다 1 : 1로 균등하게 나눕니다. 경우 2, 3 : 6.

> out1[out1 != out2] 
52 109 144 197 314 609 939 950 
    2 2 1 2 2 1 1 1 

> out1[out1 != out3] 
52 144 146 253 314 479 609 841 939 
    2 1 2 2 2 2 1 2 1 

더 큰 데이터 세트에 변경 :

x1 = runif(2000,-4,4) 
x2 = runif(2000,-4,4) 
x3 = runif(10000,-4,4) 
x4 = runif(10000,-4,4) 

내가 얻을 :

> sum(out1[out1 != out2] == 1) 
[1] 39 
> sum(out1[out1 != out2] == 2) 
[1] 41 

내가 코드를 오해하지 않는 한, 예상대로
> sum(out1[out1 != out3] == 1) 
[1] 30 
> sum(out1[out1 != out3] == 2) 
[1] 31 

.


편집

아, 난을 참조하십시오. 당신은 넥타이가있는 케이스를 다시 실행하고, 그들이 50/50으로 부서지기를 기대하고 있습니다 : sum(cnum == 1)은 대략 sum(cnum == 2)입니다. 당신은이 방법을 사용하여 훨씬 빠르게 테스트 할 수 있습니다 : 당신이 바로 것 같다

> for (j in 1:length(bad_ind)) { 
+ mydata= data.frame("v1"=0, "v2"=0) 
+ mydata[rep(1:1000000),] = val[bad_ind[[j]],] 
+ outpred = predict(mm,mydata) 
+ print(sum(outpred==1)/sum(outpred==2)) 
+ } 
[1] 0.5007849 
[1] 0.5003278 
[1] 0.4998868 
[1] 0.4995651 

를, 그것은 클래스로 자주 배 수준의 2의 찬성 관계를 깨는입니다 1.

+0

당신은 클래스 1과 클래스 2 사이의 분포를보고 있습니다. 나는 예측들 사이를 돌면서 그 특징 벡터 중 하나를 취할 때 일어나는 일에 더 관심이 있습니다. 무작위 추출은 50/50이어야하며 본 실험에서는 66/33 - 실제 데이터 80/20 및 90/10에서 볼 수 있습니다. 그래서, 나는 선택의 기초가 여러 클래스에서 같은 수의 트리 투표를 가진 단일 피쳐 벡터에 대한 것인지 궁금합니다. 내 코드에서, 그것은 50/50 (나는 생각한다)이되어야하는 "cat"라인이지만 1000 개 샘플을 기반으로하지는 않는다. – Nate

+0

코드의 해당 부분을 실행할 수 없지만 더 많은 샘플을 사용해보십시오. 나는 우리 모두가 같은 일을하고 있다고 확신한다. – Benjamin