获取 DecisionTreeRegressor 中终端(叶)节点的所有值
Get all values of a terminal (leaf) node in a DecisionTreeRegressor
决策树会分裂节点,直到出现某些破坏条件,并使用任何节点中值的平均值作为预测。
我想获取此类节点中的所有值,而不仅仅是平均值,然后执行更复杂的操作。我正在使用sklearn。我没有找到任何答案,只是一种使用 DecisionTreeRegressor.tree_.value
.
获取所有节点平均值的方法
如何操作?
据我所知,没有任何 API 方法,但您当然可以通过编程方式获取它们。
让我们先制作一些虚拟数据并构建回归树来演示这一点:
import numpy as np
from sklearn.tree import DecisionTreeRegressor, export_graphviz
# dummy data
rng = np.random.RandomState(1) # for reproducibility
X = np.sort(5 * rng.rand(80, 1), axis=0)
y = np.sin(X).ravel()
y[::5] += 3 * (0.5 - rng.rand(16))
estimator = DecisionTreeRegressor(max_depth=3)
estimator.fit(X, y)
import graphviz
dot_data = export_graphviz(estimator, out_file=None)
graph = graphviz.Source(dot_data)
graph
这是我们的决策树图:
从中可以明显看出我们有 8 个叶子,其中描述了样本数量和每个样本的平均值。
这里的关键命令是apply
:
on_leaf = estimator.apply(X)
on_leaf
# result:
array([ 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14])
on_leaf
的长度等于我们的数据 X
和结果 y
;它给出了每个样本结束的节点的索引(on_leaf
中的所有节点都是终端节点,即叶子)。它的唯一值的个数等于我们叶子的个数,这里是8:
len(np.unique(on_leaf))
# 8
和on_leaf[k]
给出y[k]
结束的节点数。
现在我们可以得到 8 片叶子中每一片的实际 y
值:
leaves = []
for i in np.unique(on_leaf):
leaves.append(y[np.argwhere(on_leaf==i)])
len(leaves)
# 8
让我们验证一下,根据我们的情节,第一片叶子只有一个样本值为-1.149
(因为它是一片single-sample叶子,样本的值等于均值):
leaves[0]
# array([[-1.1493464]])
看起来不错。那么第二片叶子呢,有 10 个样本,平均值为 -0.173
?
leaves[1]
# result:
array([[ 0.09131401],
[ 0.09668352],
[ 0.13651039],
[ 0.19403525],
[-0.12383814],
[ 0.26365828],
[ 0.41252216],
[ 0.44546446],
[ 0.47215529],
[-0.26319138]])
len(leaves[1])
# 10
leaves[1].mean()
# 0.17253138570808904
等等——对最后一片叶子 (#7) 的最终检查,有 4 个样本,平均值为 -0.99
:
leaves[7]
# result:
array([[-0.99994398],
[-0.99703245],
[-0.99170146],
[-0.9732277 ]])
leaves[7].mean()
# -0.9904763973694366
总结一下:
您需要的数据 X
、结果 y
和决策树回归器 estimator
是:
on_leaf = estimator.apply(X)
leaves = []
for i in np.unique(on_leaf):
leaves.append(y[np.argwhere(on_leaf==i)])
感谢@desertnaut,我们得到了一个非常好的答案。对于想要 pandas-based 解决方案的人,我建议使用以下代码:
import numpy as np
from sklearn.tree import DecisionTreeRegressor
import pandas as pd
## Dummy data code provided by desertnaut
rng = np.random.RandomState(1) # for reproducibility
X = np.sort(5 * rng.rand(80, 1), axis=0)
y = np.sin(X).ravel()
y[::5] += 3 * (0.5 - rng.rand(16))
## Assuming X and y to be pd.DataFrame
X, y = pd.DataFrame(X, columns=['input']), pd.DataFrame(y, columns=['output'])
## Train a regression tree
estimator = DecisionTreeRegressor(max_depth=3)
estimator.fit(X, y)
leaf_index = pd.DataFrame(estimator.apply(X), columns=['leaf_index'], index=y.index)
leaf_df = pd.concat([leaf_index, y], axis=1).groupby('leaf_index')\
.apply(lambda x: x['output'].unique())\
.to_frame('leaf_values').reset_index()
leaf_df['leaf_size'] = leaf_df.leaf_values.apply(len)
Jupyter 显示了以下数据框,如您所见,我们得到了与 desertnaut 相同的结果。
之后,得到对应于给定观察值x的叶子样本就非常简单了。
leaf_df.loc[leaf_index == estimator.apply(x), 'leaf_values']
决策树会分裂节点,直到出现某些破坏条件,并使用任何节点中值的平均值作为预测。
我想获取此类节点中的所有值,而不仅仅是平均值,然后执行更复杂的操作。我正在使用sklearn。我没有找到任何答案,只是一种使用 DecisionTreeRegressor.tree_.value
.
如何操作?
据我所知,没有任何 API 方法,但您当然可以通过编程方式获取它们。
让我们先制作一些虚拟数据并构建回归树来演示这一点:
import numpy as np
from sklearn.tree import DecisionTreeRegressor, export_graphviz
# dummy data
rng = np.random.RandomState(1) # for reproducibility
X = np.sort(5 * rng.rand(80, 1), axis=0)
y = np.sin(X).ravel()
y[::5] += 3 * (0.5 - rng.rand(16))
estimator = DecisionTreeRegressor(max_depth=3)
estimator.fit(X, y)
import graphviz
dot_data = export_graphviz(estimator, out_file=None)
graph = graphviz.Source(dot_data)
graph
这是我们的决策树图:
从中可以明显看出我们有 8 个叶子,其中描述了样本数量和每个样本的平均值。
这里的关键命令是apply
:
on_leaf = estimator.apply(X)
on_leaf
# result:
array([ 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14])
on_leaf
的长度等于我们的数据 X
和结果 y
;它给出了每个样本结束的节点的索引(on_leaf
中的所有节点都是终端节点,即叶子)。它的唯一值的个数等于我们叶子的个数,这里是8:
len(np.unique(on_leaf))
# 8
和on_leaf[k]
给出y[k]
结束的节点数。
现在我们可以得到 8 片叶子中每一片的实际 y
值:
leaves = []
for i in np.unique(on_leaf):
leaves.append(y[np.argwhere(on_leaf==i)])
len(leaves)
# 8
让我们验证一下,根据我们的情节,第一片叶子只有一个样本值为-1.149
(因为它是一片single-sample叶子,样本的值等于均值):
leaves[0]
# array([[-1.1493464]])
看起来不错。那么第二片叶子呢,有 10 个样本,平均值为 -0.173
?
leaves[1]
# result:
array([[ 0.09131401],
[ 0.09668352],
[ 0.13651039],
[ 0.19403525],
[-0.12383814],
[ 0.26365828],
[ 0.41252216],
[ 0.44546446],
[ 0.47215529],
[-0.26319138]])
len(leaves[1])
# 10
leaves[1].mean()
# 0.17253138570808904
等等——对最后一片叶子 (#7) 的最终检查,有 4 个样本,平均值为 -0.99
:
leaves[7]
# result:
array([[-0.99994398],
[-0.99703245],
[-0.99170146],
[-0.9732277 ]])
leaves[7].mean()
# -0.9904763973694366
总结一下:
您需要的数据 X
、结果 y
和决策树回归器 estimator
是:
on_leaf = estimator.apply(X)
leaves = []
for i in np.unique(on_leaf):
leaves.append(y[np.argwhere(on_leaf==i)])
感谢@desertnaut,我们得到了一个非常好的答案。对于想要 pandas-based 解决方案的人,我建议使用以下代码:
import numpy as np
from sklearn.tree import DecisionTreeRegressor
import pandas as pd
## Dummy data code provided by desertnaut
rng = np.random.RandomState(1) # for reproducibility
X = np.sort(5 * rng.rand(80, 1), axis=0)
y = np.sin(X).ravel()
y[::5] += 3 * (0.5 - rng.rand(16))
## Assuming X and y to be pd.DataFrame
X, y = pd.DataFrame(X, columns=['input']), pd.DataFrame(y, columns=['output'])
## Train a regression tree
estimator = DecisionTreeRegressor(max_depth=3)
estimator.fit(X, y)
leaf_index = pd.DataFrame(estimator.apply(X), columns=['leaf_index'], index=y.index)
leaf_df = pd.concat([leaf_index, y], axis=1).groupby('leaf_index')\
.apply(lambda x: x['output'].unique())\
.to_frame('leaf_values').reset_index()
leaf_df['leaf_size'] = leaf_df.leaf_values.apply(len)
Jupyter 显示了以下数据框,如您所见,我们得到了与 desertnaut 相同的结果。
之后,得到对应于给定观察值x的叶子样本就非常简单了。
leaf_df.loc[leaf_index == estimator.apply(x), 'leaf_values']