Tôi thú nhận là một thông dịch viên mã c tầm thường và mã cũ này không thân thiện với người dùng. Điều đó nói rằng tôi đã xem qua mã nguồn và thực hiện những quan sát này khiến tôi khá chắc chắn để nói: "rpart theo nghĩa đen chọn cột biến đầu tiên và tốt nhất". Vì cột 1 và 2 tạo ra các phân tách kém hơn, petal.length sẽ là biến phân tách đầu tiên vì cột này nằm trước petal. Thong trong data.frame / matrix. Cuối cùng, tôi chỉ ra điều này bằng cách đảo ngược thứ tự cột sao cho petal.with sẽ là biến phân tách đầu tiên.
Trong tệp nguồn c "bsplit.c" trong mã nguồn cho rpart tôi trích dẫn từ dòng 38:
* test out the variables 1 at at time
me->primary = (pSplit) NULL;
for (i = 0; i < rp.nvar; i++) {
... do đó lặp đi lặp lại trong một vòng lặp for bắt đầu từ i = 1 đến rp.nvar, một hàm mất sẽ được gọi để quét tất cả các phân tách bởi một biến, bên trong gini.c cho dòng "phân chia không phân loại" 230 phân tách được tìm thấy tốt nhất là cập nhật nếu một phân chia mới là tốt hơn. (Đây cũng có thể là chức năng mất do người dùng xác định)
if (temp < best) {
best = temp;
where = i;
direction = lmean < rmean ? LEFT : RIGHT;
}
và dòng cuối cùng 323, sự cải thiện để phân chia tốt nhất bởi một biến được tính toán ...
*improve = total_ss - best
... Quay lại bsplit.c, cải tiến được kiểm tra nếu lớn hơn những gì đã thấy trước đó và chỉ được cập nhật nếu lớn hơn.
if (improve > rp.iscale)
rp.iscale = improve; /* largest seen so far */
Ấn tượng của tôi về điều này là đầu tiên và tốt nhất (trong số các mối quan hệ có thể sẽ được chọn), bởi vì chỉ khi điểm dừng mới có điểm tốt hơn thì nó mới được lưu. Điều này liên quan đến cả điểm phá vỡ tốt nhất đầu tiên được tìm thấy và biến tốt nhất đầu tiên được tìm thấy. Điểm phá vỡ dường như không được quét đơn giản từ trái sang phải trong gini.c, vì vậy điểm phá vỡ buộc đầu tiên được tìm thấy có thể khó dự đoán. Nhưng các biến được quét rất dễ đoán từ cột đầu tiên đến cột cuối cùng.
Hành vi này khác với triển khai RandomForest trong đó trong classTree.c giải pháp sau được sử dụng:
/* Break ties at random: */
if (crit == critmax) {
if (unif_rand() < 1.0 / ntie) {
*bestSplit = j;
critmax = crit;
*splitVar = mvar;
}
ntie++;
}
cuối cùng tôi xác nhận hành vi này bằng cách lật các cột của mống mắt, sao cho petal. thong được chọn trước
library(rpart)
data(iris)
iris = iris[,5:1] #flip/flop", invert order of columns columns
obj = rpart(Species~.,data=iris)
print(obj) #now petal width is first split
1) root 150 100 setosa (0.33333333 0.33333333 0.33333333)
2) Petal.Width< 0.8 50 0 setosa (1.00000000 0.00000000 0.00000000) *
3) Petal.Width>=0.8 100 50 versicolor (0.00000000 0.50000000 0.50000000)
6) Petal.Width< 1.75 54 5 versicolor (0.00000000 0.90740741 0.09259259) *
7) Petal.Width>=1.75 46 1 virginica (0.00000000 0.02173913 0.97826087) *
... và lật lại lần nữa
iris = iris[,5:1] #flop/flip", revert order of columns columns
obj = rpart(Species~.,data=iris)
print(obj) #now petal length is first split
1) root 150 100 setosa (0.33333333 0.33333333 0.33333333)
2) Petal.Length< 2.45 50 0 setosa (1.00000000 0.00000000 0.00000000) *
3) Petal.Length>=2.45 100 50 versicolor (0.00000000 0.50000000 0.50000000)
6) Petal.Width< 1.75 54 5 versicolor (0.00000000 0.90740741 0.09259259) *
7) Petal.Width>=1.75 46 1 virginica (0.00000000 0.02173913 0.97826087) *