【问题标题】:Could I use a faster data structure than a tree for this?我可以为此使用比树更快的数据结构吗?
【发布时间】:2013-05-14 09:28:21
【问题描述】:

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

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

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

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

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

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

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

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

Micro optimisations iterating through a tree in C#

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

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

【问题讨论】:

  • 可以是地图的排序字典
  • 你说你有一棵二叉树,每个节点的输入是一个浮点数 - 你选择的子节点是基于input < 0.5 还是有更复杂的事情发生?你能发布一些代码吗?另外:17% 的执行时间与上下文无关——这可能非常快!您是否有一个目标,或者您可以分享更多关于分析的详细信息?
  • 感谢 Dan,我添加了有关树和目标的更多详细信息。
  • 它有固定的深度吗?
  • 浮点数需要什么精度?例如,在 0 和 1 之间只有 256 个刻度就足够了吗?

标签: performance data-structures


【解决方案1】:

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

       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(log2 n) 次比较,其中 n 是可能决策的数量。

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

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

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

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

【讨论】:

  • 感谢您的回答。我的下一个计划是将树放入一个数组中,看看我可以从缓存位置获得什么样的改进。我喜欢使用最高有效位进行索引的声音。我将不得不考虑实现它的最佳方式。将树塞进一个数组的问题是 1. 它正在增长 2. 最终的大小将是许多千兆字节。
  • @Will Calderwood:如果树的数量级为千兆字节,那么我怀疑缓存位置会为您带来很多好处。确保树是平衡的可能是最大的胜利。您还可以考虑在多核机器上并行查找(假设树是静态的)。
【解决方案2】:

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

假设您有两个二元决策;可能的路径是 00, 01, 10, 11

想象一下,你有一个包含四个结果的数组,而不是树;你可以把你的浮点数数组变成一个二进制数,这个二进制数会被索引到这个数组中。

【讨论】:

  • 有趣的想法。如果我理解正确,我仍然需要迭代树以生成二进制数以获取数组中的索引。我看不出如何在不迭代树的情况下生成数字。
  • @WillCalderwood 是的,我假设有 50/50 的机会,这意味着您无需访问节点即可知道拆分。您现在已经扩展了问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-07
相关资源
最近更新 更多