4

R randomForest パッケージが分類の同点を解決するために使用するメカニズムを知っている人はいますか?

ドキュメントによると、同点はランダムに壊れています。ただし、一連のデータでモデルをトレーニングし、そのモデルを 1 つの検証データ セットで何度もスコアリングする場合、同点のクラスの決定は 50/50 ではありません。

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])))
}

ここmodelで、 は randomForest オブジェクトであり、同数bad_indのクラス投票を持つ特徴ベクトルの単なるインデックスのリストです。上記のコードを使用した私のテスト ケースでは、同順位の 2 つのクラス間の分布は 90/10 に近づきました。

また、奇数のツリーを使用するという推奨事項は、通常、3 番目のクラスがいくつかの票を集め、他の 2 つのクラスが引き分けになった場合には機能しません。

投票で結ばれた rf ツリーを持つこれらのケースは、最終的に 50/50 になるべきではありませんか?

更新: フォレストのトレーニングのランダムな性質のため、例を提供することは困難ですが、次のコード (スロップで申し訳ありません) は、フォレストが明確な勝者を決定できない例を生成することになります。私のテストの実行では、同点が解消されたときに 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")
}

更新: これは、randomForest のバージョン 4.6-3 で修正される必要があります。

4

3 に答える 3

1

完全な例がなければ、これが唯一の問題であるかどうかを判断するのは困難ですが、上記のコードの明らかな問題の 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
于 2011-12-07T23:40:41.763 に答える
1

結びつきの数が非常に少ないため、これが起こっていると思います。コインを 10 回投げるのと同じ問題で、表が 5 回裏が 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

おっしゃる通り、クラス 1 の 2 倍の頻度でクラス 2 を支持して同点を破っています。

于 2011-12-08T01:36:08.353 に答える
1

これは、randomForest のバージョン 4.6-3 で修正される必要があります。

于 2011-12-30T23:35:18.320 に答える