2017-06-18 27 views
3

我正在使用python和R中的sklearn设置load_iris数据集(它只是在R中称为“虹膜”)。为什么用python编写的决策树代码与用R编写的代码不同?

我使用“gini”索引在两种语言中构建模型,并且在两种语言中,我都能够在从虹膜数据集直接获取测试数据时正确测试模型。

但是,如果我给一个新的数据集作为测试输入,对于相同的Python和R把它放到不同的类别。

我不确定我在这里错过什么或做错了什么,所以任何指导将非常感激。

代码提到如下: 的Python 2.7:

from sklearn.datasets import load_iris 
from sklearn import tree 
iris = load_iris() 
model = tree.DecisionTreeClassifier(criterion='gini') 
model.fit(iris.data, iris.target) 
model.score(iris.data, iris.target) 
print iris.data[49],model.predict([iris.data[49]]) 
print iris.data[99],model.predict([iris.data[99]]) 
print iris.data[100],model.predict([iris.data[100]]) 
print iris.data[149],model.predict([iris.data[149]]) 
print [6.3,2.8,6,1.3],model.predict([[6.3,2.8,6,1.3]]) 

R-Rstudio运行3.3.2 32位:

library(rpart) 
iris<- iris 
x_train = iris[c('Sepal.Length','Sepal.Width','Petal.Length','Petal.Width')] 
y_train = as.matrix(cbind(iris['Species'])) 
x <- cbind(x_train,y_train) 
fit <- rpart(y_train ~ ., data = x_train,method="class",parms = list(split = "gini")) 
summary(fit) 
x_test = x[149,] 
x_test[,1]=6.3 
x_test[,2]=2.8 
x_test[,3]=6 
x_test[,4]=1.3 
predicted1= predict(fit,x[49,]) # same as python result 
predicted2= predict(fit,x[100,]) # same as python result 
predicted3= predict(fit,x[101,]) # same as python result 
predicted4= predict(fit,x[149,]) # same as python result 
predicted5= predict(fit,x_test) ## this value does not match with pythons result 

我的Python输出是:

[ 5. 3.3 1.4 0.2] [0] 
[ 5.7 2.8 4.1 1.3] [1] 
[ 6.3 3.3 6. 2.5] [2] 
[ 5.9 3. 5.1 1.8] [2] 
[6.3, 2.8, 6, 1.3] [2] -----> this means it's putting the test data into virginica bucket 

和R输出为:

> predicted1 
    setosa versicolor virginica 
49  1   0   0 
> predicted2 
    setosa versicolor virginica 
100  0 0.9074074 0.09259259 
> predicted3 
    setosa versicolor virginica 
101  0 0.02173913 0.9782609 
> predicted4 
    setosa versicolor virginica 
149  0 0.02173913 0.9782609 
> predicted5 
    setosa versicolor virginica 
149  0 0.9074074 0.09259259 --> this means it's putting the test data into versicolor bucket 

请帮忙。谢谢。

+0

你可以发布您的R树的树参数和值? – CPak

回答

5

决策树涉及相当多的参数(最小/最大离开大小,树的深度,何时拆分等),不同的包可能有不同的默认设置。如果你想得到相同的结果,你需要确保隐含的默认值是相似的。例如,尝试运行以下:

fit <- rpart(y_train ~ ., data = x_train,method="class", 
      parms = list(split = "gini"), 
      control = rpart.control(minsplit = 2, minbucket = 1, xval=0, maxdepth = 30)) 

(predicted5= predict(fit,x_test)) 
    setosa versicolor virginica 
149  0 0.3333333 0.6666667 

这里,minsplit = 2, minbucket = 1, xval=0maxdepth = 30被选择成是相同的sklearn -options选项,看到heremaxdepth = 30是最大的值rpart会让你有; sklearn在这里没有绑定)。如果你想要的概率等是相同的,你可能想要玩弄cp参数。

同样,

model = tree.DecisionTreeClassifier(criterion='gini', 
            min_samples_split=20, 
            min_samples_leaf=round(20.0/3.0), max_depth=30) 
model.fit(iris.data, iris.target) 

我得到

print model.predict([iris.data[49]]) 
print model.predict([iris.data[99]]) 
print model.predict([iris.data[100]]) 
print model.predict([iris.data[149]]) 
print model.predict([[6.3,2.8,6,1.3]]) 

[0] 
[1] 
[2] 
[2] 
[1] 

这看起来很相似,你的初始R输出。不用说,当你的预测(在训练集上)看起来“不合理地好”时要小心,因为你可能会过度使用数据。例如,看看model.predict_proba(...),它给出了sklearn(而不是预测的类)中的概率。你应该看到,你现在的Python代码/设置,你几乎肯定是过度配合。

+0

@coffeinjunkey非常具有描述性和翔实的答案。谢谢。 我只是想补充一点:'min_samples_leaf = ROUND(20.0/3.0)'扔了'ValueError异常:min_samples_leaf必须至少1或在(0,0.5],得到7.0'和解决,我缠绕。这个函数使用了一个int()函数,所有的工作都很好,所以我的最终代码格式如下:Python应该有: 'model = tree.DecisionTreeClassifier(criterion ='gini', min_samples_split = 20 , min_samples_leaf = INT(圆形(20.0/3.0)),MAX_DEPTH = 30)' – S4nd33p

2

除了@ coffeeinjunky的答案,你需要注意的参数random_state(这是Python的参数,不知道这是R中调用)。树本身的生成是随机的,所以你需要指定两个模型都有相同的种子值。否则,您将使用相同的模型进行拟合/预测,并在每次运行中获得不同的结果,因为每个使用的树都不相同。

查核在穆勒&圭多决策树的部分 - “Python的机器学习。”它在视觉上解释不同的参数方面做得很好,如果你只是尝试谷歌搜索,pdf就会在互联网上浮动。通过决策树和集成学习方法,您指定的参数将对预测产生有意义的影响。