我正在使用sklearn的决策树来取代业务规则的混乱和不可持续的实现,作为一个长if-elif-else链 . 我使用数千个测试用例对所有标签验证树,但有时我用作训练数据的规则表有错误,有些测试随机失败 .
我需要一种方法来验证树,超出结果的测试用例 . 假设所有叶节点的gini = 0.0,使用不同的随机种子生成的树的分类中没有随机变化,这是正确的吗?如果我需要在我的应用程序上强制执行该操作,在更新培训数据时检查是否合理?
请注意,我的情况不是典型的分类问题,因为我已经在代码中实现了决策树,并且我想使用算法从精心定制的数据生成等效树,而不是真实世界的数据样本,因为在我的情况是使用业务规则维护数据集比维护代码更容易 .
因此,在我的数据集中,功能将理想地涵盖所有可能的值范围,并为此提供一个明确的标签 . 例如,虽然现实世界的训练集可能是这样的:
features = [[1], [1.1], [2], [2.3]]
labels = ['sativa', 'sativa', 'indica', 'indica']
一个算法可以随机出现一个tree1,如:
if feature < 1.75:
return 'sativa'
else:
return 'indica'
和树2一样:
if feature < 1.55:
return 'sativa'
else:
return 'indica'
但是,我的训练集不会出现随机性发生的差距 . 这将是:
features = [[1], [1.9], [2], [2.3]]
labels = ['sativa', 'sativa', 'indica', 'indica']
因此,无论初始随机状态如何,树总是(显然,忽略低于0.1的差异):
if feature < 1.95:
return 'sativa'
else:
return 'indica'
我的问题正是我需要验证训练集是否有错误,并且存在可能发生随机变化的值的间隙,或者是否将相同的特征集分配给不同的标签 . 修复随机状态并不能解决这个问题,它只能保证相同的数据始终会生成相同的树 .
那么,有没有办法确定这是否发生在树上,除了在生成树之前验证这些问题的数据,或者进行多次大规模的综合测试以排除随机变化?
1 回答
由于您有标签规则,并且知道可能的功能范围,因此您可以实现目标 .
让我们用例子来看这个
基尼指数
基尼指数的含义是什么?它试图使您刚刚制作的树中的训练集合适合,并告诉他们的项目被标记的错误 . 因此,在Tree1和Tree2中,您有gini = 0,因为训练集中的每个示例都将被正确标记 .
Tree1和Tree2具有相同的训练集,并且gini = 0.0 . 但是,如果我们试图标记x = [1.7],我们将得到不同的结果 .
解决方案
由于您已了解将特征集与其相应标签绑定的规则,因此可以确保给定一个训练集,它将始终生成一个树,输出正确的结果,对于任何可能的特征,如果:
连续值的要素在范围内,例如 . [2,30]
您可以有一个精度阈值,例如 . 上面的例子至少以0.1步变化
您可以为每种可能的组合生成示例
你的树有gini = 0.0
(基本上,我们告诉你,因为gini = 0.0,那么如果你给出一个在训练集中的输入,它将被正确标记 . 这里没有巨大的跳跃结论) .
因此,如果:
和:
然后你可以肯定:
这样,随机初始化的随机树将具有相同的输出 . 它们可能仅在训练集范围之外的示例中有所不同,或者具有值不符合阈值规则的值的示例 .
猜猜你已经这样做了,但是使用测试覆盖率工具创建训练集是个好主意,以确保创建所有可能的示例 .
关于在连续值中使用所有可能值的必要性
当我说你需要拥有连续值的所有可能值时,我一直非常小心,如[1.0,1.1,1.2,...... 1.9,2.0] . 如果该功能仅在一个节点中使用,则只能使用边界值(示例中为1.9和2.0) . 但是,如果你的if-elses更复杂,我们可能会有一些不可预测的复杂场景 . 在评估特征f1的节点之后,我们可以稍后在左边生成的节点上有一个条件,如(如果f2> 5),和右边节点中的a(如果f2 <3),或类似的东西 . 你可能会得到错误的结果 .
如果您的组合太大,那么将功能二值化可能是个好主意 . 如果你有一个连续的功能,如:
使用DictVectorizer对象将其转换为(1 0)和(0 1) .
虽然您正在增加维度,但您的决策树只会为这两个功能创建一个节点 . 如果它只检查第一个是否为真,那么第二个是多余的,因为它们是相互排斥的 .
如果您没有数据边界,这也是一种解决方案 . 如果你有没有范围的ax特征,你可以像(x <0,0 <= x <5,5 <= x)二进制化,将连续值转换为(1 0 0),(0 1 0)或(0 0 1),允许您评估所有可能的组合 .
通过这种方式,您可以从根本上减少组合集的大小 .
希望如此 . 干杯!