为什么用 python 编写的决策树代码预测结果与用 R 编写的代码不同?
Why Decision Tree code written in python predicts differently than the code written in R?
我在 python 和 R 中使用来自 sklearn 的 load_iris 数据集(它在 R 中称为 iris)。
我使用 "gini" 索引以两种语言构建了模型,并且当测试数据直接从 iris 数据集中获取时,我能够以两种语言正确测试模型。
然而,如果我给出一个新的数据集作为测试输入,对于相同的 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
请帮忙。谢谢。
决策树涉及的参数很多(最小/最大叶子尺寸、树的深度、何时分裂等),不同的包可能有不同的默认设置。如果你想得到相同的结果,你需要确保隐含的默认值是相似的。例如,尝试 运行 以下内容:
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=0
和 maxdepth = 30
以与 sklearn
选项相同,参见 here。 maxdepth = 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
输出非常相似。
不用说,当您的预测(在训练集上)看起来 "unreasonably good" 时要小心,因为您可能会过度拟合数据。例如,查看 model.predict_proba(...)
,它为您提供 sklearn
的概率(而不是预测的 类)。您应该看到,使用当前的 Python 代码/设置,您几乎肯定会过度拟合。
除了@coffeeinjunky的回答,你还需要注意参数random_state
(这是Python参数,不知道在R中叫什么)。树本身的生成是伪随机的,因此需要指定两者的模型具有相同的种子值。否则,您将 fit/predict 使用相同的模型并在每个 运行 得到不同的结果,因为每个模型使用的树都不同。
查看 Mueller & Guido 中关于决策树的部分 -- 'Python for Machine Learning.' 它很好地直观地解释了不同的参数,如果你只是尝试 Google 搜索。使用决策树和集成学习方法,您指定的参数将对预测产生有意义的影响。
我在 python 和 R 中使用来自 sklearn 的 load_iris 数据集(它在 R 中称为 iris)。
我使用 "gini" 索引以两种语言构建了模型,并且当测试数据直接从 iris 数据集中获取时,我能够以两种语言正确测试模型。
然而,如果我给出一个新的数据集作为测试输入,对于相同的 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
请帮忙。谢谢。
决策树涉及的参数很多(最小/最大叶子尺寸、树的深度、何时分裂等),不同的包可能有不同的默认设置。如果你想得到相同的结果,你需要确保隐含的默认值是相似的。例如,尝试 运行 以下内容:
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=0
和 maxdepth = 30
以与 sklearn
选项相同,参见 here。 maxdepth = 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
输出非常相似。
不用说,当您的预测(在训练集上)看起来 "unreasonably good" 时要小心,因为您可能会过度拟合数据。例如,查看 model.predict_proba(...)
,它为您提供 sklearn
的概率(而不是预测的 类)。您应该看到,使用当前的 Python 代码/设置,您几乎肯定会过度拟合。
除了@coffeeinjunky的回答,你还需要注意参数random_state
(这是Python参数,不知道在R中叫什么)。树本身的生成是伪随机的,因此需要指定两者的模型具有相同的种子值。否则,您将 fit/predict 使用相同的模型并在每个 运行 得到不同的结果,因为每个模型使用的树都不同。
查看 Mueller & Guido 中关于决策树的部分 -- 'Python for Machine Learning.' 它很好地直观地解释了不同的参数,如果你只是尝试 Google 搜索。使用决策树和集成学习方法,您指定的参数将对预测产生有意义的影响。