【问题标题】:Why does DecisionTreeClassifier (0.23.1 sklearn) give different results based on the column order of the inputs?为什么 DecisionTreeClassifier (0.23.1 sklearn) 根据输入的列顺序给出不同的结果?
【发布时间】:2020-09-12 17:34:04
【问题描述】:

当更改 sklearn DecisionTreeClassifier 的输入列的顺序时,准确性似乎发生了变化。这不应该是这样的。我做错了什么?

from sklearn.datasets import load_iris
import numpy as np

iris = load_iris()

X = iris['data']
y = iris['target']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.90, random_state=0)


clf = DecisionTreeClassifier(random_state=0)
clf.fit(X_train, y_train)
print(clf.score(X_test, y_test))

clf = DecisionTreeClassifier(random_state=0)
clf.fit(np.hstack((X_train[:,1:], X_train[:,:1])), y_train)
print(clf.score(X_test, y_test))

clf = DecisionTreeClassifier(random_state=0)
clf.fit(np.hstack((X_train[:,2:], X_train[:,:2])), y_train)
print(clf.score(X_test, y_test))

clf = DecisionTreeClassifier(random_state=0)
clf.fit(np.hstack((X_train[:,3:], X_train[:,:3])), y_train)
print(clf.score(X_test, y_test))

运行此代码会产生以下输出

0.9407407407407408
0.22962962962962963
0.34074074074074073
0.3333333333333333

这已在 3 年前提出,但由于未提供代码,被质疑者被否决了。 Does feature order impact Decision tree algorithm in sklearn?


编辑

在上面的代码中,我忘记将列重新排序应用于测试数据。

我发现在将重新排序应用到整个数据集时也会持续存在不同的结果。

首先我导入数据并将其转换为 pandas 数据框。

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
import numpy as np

iris = load_iris()
y = iris['target']
iris_features = iris['feature_names']
iris = pd.DataFrame(iris['data'], columns=iris['feature_names'])

然后我通过原始有序特征名称选择所有数据。我训练和评估模型。

X = iris[iris_features].values
print(X.shape[1], iris_features)
# 4 ['petal length (cm)', 'petal width (cm)', 'sepal length (cm)', 'sepal width (cm)']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.95, random_state=0)

clf = DecisionTreeClassifier(random_state=0)
clf.fit(X_train, y_train)
pred = clf.predict(X_test)

print(np.mean(y_test == pred))
# 0.7062937062937062

为什么我仍然得到不同的结果? 然后我选择相同列的不同顺序来训练和评估模型。

X = iris[iris_features[2:]+iris_features[:2]].values
print(X.shape[1], iris_features[2:]+iris_features[:2])
# 4 ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.95, random_state=0)

clf = DecisionTreeClassifier(random_state=0)
clf.fit(X_train, y_train)
pred = clf.predict(X_test)

print(np.mean(y_test == pred))
# 0.8881118881118881

【问题讨论】:

    标签: python pandas scikit-learn


    【解决方案1】:

    您错过了在测试数据中应用列排序 (X_test)。当您对测试数据执行相同操作时,您将获得相同的分数。

    from sklearn.datasets import load_iris
    from sklearn.tree import DecisionTreeClassifier
    from sklearn.model_selection import train_test_split
    import numpy as np
    
    iris = load_iris()
    
    X = iris['data']
    y = iris['target']
    
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.90, random_state=0)
    
    
    def shuffle_data(data, n):
        return np.hstack((data[:,n:], data[:,:n]))
    
    clf = DecisionTreeClassifier(random_state=0)
    clf.fit(X_train, y_train)
    print(clf.score(X_test, y_test))
    # 0.9407407407407408
    
    clf = DecisionTreeClassifier(random_state=0)
    clf.fit(shuffle_data(X_train,1), y_train)
    print(clf.score(shuffle_data(X_test,1), y_test))
    # 0.9407407407407408
    
    clf = DecisionTreeClassifier(random_state=0)
    clf.fit(shuffle_data(X_train,2), y_train)
    print(clf.score(shuffle_data(X_test,2), y_test))
    # 0.9407407407407408
    
    clf = DecisionTreeClassifier(random_state=0)
    clf.fit(shuffle_data(X_train,3), y_train)
    print(clf.score(shuffle_data(X_test,3), y_test))
    # 0.9407407407407408
    

    更新:

    在您的第二个示例中,您将 test_size 设置为 0.95,这使您只剩下 7 个数据点,它们的类是 array([0, 0, 0, 2, 1, 2, 0])

    如果在这两种情况下测量决策树的训练分数,则为1.0。这告诉我们模型在两种情况下都找到了最佳分离。

    简单的答案是肯定的,当列顺序发生变化时,结果会有所不同,当不同的规则组合(不同的拆分条件)可能导致数据点的完美分离(100% 准确度)。

    使用plot_tree 我们可以可视化树。这里我们需要了解DecisionTree的实现。 This 回答引用了文档中的重点:

    在最优性的几个方面,甚至对于简单的概念,学习最优决策树的问题都是 NP 完全的。因此,实际的决策树学习算法基于启发式算法,例如贪心算法,其中在每个节点处做出局部最优决策。此类算法不能保证返回全局最优决策树。这可以通过在集成学习器中训练多棵树来缓解,其中特征和样本是随机抽样替换的。

    我们需要在这里集中精力的一点是 practical decision-tree learning algorithms are based on heuristic algorithms such as the greedy algorithm where locally optimal decisions are made at each node 采用贪心算法时,列顺序的变化会影响其结果。

    同样,当您的数据集中有更多数据点时(当您的示例中没有时),当您更改列的顺序时不太可能得到不同的结果。

    即使在这个例子中,当设置test_size=0.90 时,我们也可以获得与0.9407407407407408 相同的分数。

    【讨论】:

    • 我调整了我的问题,以更好地反映我在原始代码中面临的问题。我最初提出的问题并没有反映我所面临的问题。
    • 一般后续新问题建议作为新问题提出。无论如何,我会尽力回答你的新更新
    • 如果 Venkatachalam 发现了您的问题,您应该接受他的回答并为您的其他问题创建另一个帖子。
    • 感谢您的解释。
    猜你喜欢
    • 2020-10-19
    • 1970-01-01
    • 2013-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-14
    • 2010-10-29
    相关资源
    最近更新 更多