【问题标题】:How to compare single paths of a decision tree?如何比较决策树的单个路径?
【发布时间】:2021-11-29 15:22:18
【问题描述】:

我想在 javascript 的一个函数中比较决策树的单个路径。

我只知道如何做到这一点,因为节点正在累加,但那只是比较节点。 相反,我想查看一条路径,然后查看下一条路径。

例如:下一个决定应该在 -3 的range 中。给出的是数字[9, 8, 6, 5, 3, 2, 0]。列表的总和是value。需要 length 为 6 且 biggest value 的路径。

                      2 - 0
                  3 <
               5<     0 
             /    2 - 0
           6 
          /  \    2 - 0
               3<
                  0
     8         2 - 0
       \    3<
   /    5 <    0
            2 - 0

9               2 - 0
            3 <
         5<     0 
   \   /    2 - 0
     6 
       \   2 - 0
        3<
           0

我想比较那些paths

[9,6,3,0],
[9,6,3,2,0],
[9,6,5,2,0],
[9,6,5,3,0],
[9,6,5,3,2,0],
[9,8,6,3,0],
[9,8,6,3,2,0],
[9,8,6,5,2,0],
[9,8,6,5,3,0],
[9,8,6,5,3,2,0],

而不是计算每个path 然后同时比较它们,我只想计算第一个path 然后将它与第二个path 进行比较,如下所示:

[9,6,3,0], //value 18
[9,6,3,2,0]//value 21

   || which one has the nearest length of 6 with the most Value?
   \/
[9,6,3,2,0]//value 21

[9,6,3,2,0],//value 21
[9,6,5,2,0] //value 23

   || which one has the nearest length of 6 with the most Value?
   \/ 
[9,6,5,2,0] //value 23

... and so on

如何一次只比较两条路径而不是每条路径?

编辑 1:

到目前为止我的代码: https://replit.com/@RubyKanima/BestSumwithlength#index.js

const numbers = [9, 8, 6, 5, 3, 2, 0];
const starting_node = Math.max(...numbers) + 3;

const path = (current_node, memo ={}) => {
  if (current_node in memo) return memo[current_node];
  if (current_node == 0) return [[]];
  let paths = [];
  let tmp_nodes = [];
  for (n of numbers) {
    if (n >= current_node - 3 && n < current_node) {
      tmp_nodes.push(n);
    }
  }
  for (let tmp of tmp_nodes) {
    const tmp_path = path(tmp);
    const tmp_paths = tmp_path.map(way => [tmp, ...way]);
    paths.push(...tmp_paths);
  }
  memo[current_node] = paths; 
  paths = paths.filter(x => x.length <= 6);
  return paths;
};

const bestPath = all_paths => {
  all_paths = all_paths.filter(x => (x.length = 6));
  let bestValue = 0;
  let bestPath = null;
  for (let path of all_paths) {
    let value = 0;
    for (node of path) value += node;
    if (value > bestValue) {
      bestValue = value;
      bestPath = path;
    }
  }
  return bestPath;
};
const path_array = path(starting_node);
console.log(bestPath(path_array));

它完成了这项工作,但如果我得到超过一千个数字,它就会出现堆栈溢出。 (在示例中我减少了一些数字以便于理解,实际上范围是 -360 而不是 -3)

最大的问题:数据过多

如何解决?:一次只比较 2 个 Path,然后计算下一个 Path。

我想知道的:如何只计算 2 条路径。

【问题讨论】:

  • 到目前为止你做了什么?添加一些代码你当前如何比较它们
  • @J_K 我编辑了我的问题并编辑了我的代码。它做了它应该做的,但它没有有效地做到这一点。我也有一个带有记忆功能的代码,但由于给出了 1500 个节点,它也会出现堆栈溢出,它的路径很大。问题之一是计算所有路线,而不仅仅是那些长度小于或等于 6 的路线。但最大的问题仍然是:一次计算所有路径而不是 2 条。
  • 我使用归并排序算法添加了一个答案。看看这是否对你有帮助@rubykanima

标签: javascript arrays dynamic


【解决方案1】:

所以我编写了一个合并排序算法,并为您的解决方案和合并排序解决方案添加了一些性能时间计算。在这种情况下,合并排序似乎表现更好。它同时比较两个数组,直到达到您需要的数组。在你的数据上试试这个,它应该更大,看看它是否效果更好。

const numbers = [9, 8, 6, 5, 3, 2, 0];
const starting_node = Math.max(...numbers) + 3;

const path = (current_node, memo ={}) => {
  if (current_node in memo) return memo[current_node];
  if (current_node == 0) return [[]];
  let paths = [];
  let tmp_nodes = [];
  for (n of numbers) {
    if (n >= current_node - 3 && n < current_node) {
      tmp_nodes.push(n);
    }
  }
  for (let tmp of tmp_nodes) {
    const tmp_path = path(tmp);
    const tmp_paths = tmp_path.map(way => [tmp, ...way]);
    paths.push(...tmp_paths);
  }
  memo[current_node] = paths; 
  paths = paths.filter(x => x.length <= 6);
  return paths;
};

const bestPath = all_paths => {
  all_paths = all_paths.filter(x => (x.length = 6));
  let bestValue = 0;
  let bestPath = null;
  for (let path of all_paths) {
    let value = 0;
    for (node of path) value += node;
    if (value > bestValue) {
      bestValue = value;
      bestPath = path;
    }
  }
  return bestPath;
};
//-----merge sort algorithm---------
const sumArr = arr => arr.reduce((acc, next)=> acc+next)
function merge(arr1, arr2){
    if (sumArr(arr1) > sumArr(arr2)) {
        return arr1
    } else if(sumArr(arr1) < sumArr(arr2)) {
        return arr2
    } else {return arr1}
}
function mergeSort(arr){
    if(arr.length <= 1) return arr[0];
    let mid = Math.floor(arr.length/2);
    let left = mergeSort(arr.slice(0,mid));
    let right = mergeSort(arr.slice(mid));
    return merge(left, right);
}
//-----end of merge sort algorithm------

const path_array = path(starting_node);
const start = performance.now()
console.log(bestPath(path_array));
const end = performance.now()
console.log("bestPath performance ", end-start)
const start2 = performance.now()
console.log(mergeSort(path_array))
const end2 = performance.now()
console.log("mergeSort performance ", end2-start2)

【讨论】:

  • 对我来说它只是说:ReferenceError: performance is not defined at /home/runner/match/index.js:60:15
  • 我只是仔细观察了一下,发现了一些缺陷。例如:第 41 到 43 行是变量“result”、“i”和“j”,它们从未使用过。我也可以通过查看它来判断,它不会产生任何影响,因为您仍然从 path_array 中获取变量 -> 问题出在 path() 中,因为它一次性计算所有路径。问题更多是代码本身而不是缺少代码。但我还是想出了一个主意,我稍后会尝试。仍然谢谢你,如果可能的话,我会尝试使用你的一些代码;D
  • 是的。我从我的代码库中获取代码并快速调整它。这些变量未使用,可以删除。我添加的部分代码是替换你拥有的性能低的 best_Path() 函数。那是比较路径的部分。
猜你喜欢
  • 2019-06-01
  • 1970-01-01
  • 2019-09-16
  • 2015-12-29
  • 1970-01-01
  • 2015-06-15
  • 2021-12-01
  • 2013-07-13
  • 2018-12-21
相关资源
最近更新 更多