7

我有一个二叉决策树。它将输入作为浮点数组,每个分支节点根据输入索引和值拆分,最终将我带到叶子。

我正在这棵树上执行大量查找(根据性能分析,大约占执行时间的 17%(编辑:优化了其他区域,现在几乎是 40%)),我想知道我是否可以/应该使用不同的数据结构以提高查找速度。

不能使用某种哈希表,因为输入不直接映射到叶节点,但我想知道是否有人对我可以用来代替树的方法和数据结构有任何建议(或者也as?) 以提高查找速度。

内存是一个问题,但比速度更重要。

代码目前是用 C# 编写的,但显然可以应用任何方法。

编辑:要发布的代码太多了,但我会提供有关树的更多详细信息。

树是使用信息增益计算生成的,它并不总是 50/50 分割,分割值可以是任何浮点值。单个输入也可以多次拆分,以增加该输入的分辨率。

我在这里发布了一个关于迭代器性能的问题:

在 C# 中迭代​​树的微优化

但我认为我可能需要查看数据结构本身以进一步提高性能。

我的目标是尽可能提高性能。我正在研究一种新的机器学习方法,树使用反馈循环自行生长。对于我正在处理的过程,我估计它会运行几个月,所以这里节省了几个%,而且是巨大的。最终目标是在不使用太多内存的情况下提高速度。

4

2 回答 2

2

如果我理解正确,您的浮点范围必须映射到决策。像这样的东西:

       x <= 0.0      : Decision A
 0.0 < x <= 0.5      : Decision B
 0.5 < x <= 0.6      : Decision C
 0.6 < x             : Decision D

二叉树是一种很好的处理方法。只要树平衡良好并且输入值在范围内均匀分布,您就可以预期 O(log 2 n) 比较,其中 n 是可能决策的数量。

如果树不平衡,那么您可能会进行不必要的比较。在最坏的情况下:O(n)。所以我会看看树,看看它们有多深。如果一次又一次地使用同一棵树,那么重新平衡一次所花费的成本可能会在多次查找中分摊。

如果输入值不是均匀分布的(并且您提前知道),那么您可能需要对比较的顺序进行特殊处理,以便尽早检测到最常见的情况。您可以通过操作树或在实际检查树之前在代码中添加特殊情况来做到这一点。

如果您已经用尽了算法改进并且仍然需要优化,那么您可能会研究一种比一般二叉树具有更好局部性的数据结构。例如,您可以将分区边界放入一个连续数组并对其执行二进制搜索。(而且,如果数组不太长,您甚至可以尝试对数组进行线性搜索,因为它可能对缓存和分支预测更友好。)

最后,我会考虑建立一个粗略的索引,让我们在树(或数组)中占得先机。例如,使用输入值的一些最高有效位作为索引,看看这是否可以切断树的前几层。这可能比您想象的更有帮助,因为跳过的比较可能很少有机会获得正确的分支预测。

于 2013-05-14T16:25:10.523 回答
1

假设决策有 50/50 的机会:

想象一下,您有两个二元决策;可能的路径是 00、01、10、11

想象一下,你有一个包含四个结果的数组,而不是树;您可以将浮点数组转换为二进制数,该二进制数将被索引到该数组中。

于 2013-05-14T09:32:58.760 回答