基于双列表构建决策树遇异常:仅生成首个节点求排查方案
我看了你的代码,发现核心问题出在buildtree函数的递归逻辑上,导致无法生成完整的多层决策树,具体问题和修复方案如下:
问题分析
终止条件逻辑完全错误
当record为空时,你返回了一个以symptoms[0]为数据的节点,但这时候应该是到达了决策树的叶子节点,应该返回records中的疾病节点,而不是继续用症状作为节点。另外,当symptoms遍历完之后,symptoms[0]还会引发索引越界错误。递归方向彻底颠倒
你错误地将record[0]添加到symptoms列表中继续递归,这搞反了决策树的核心逻辑:决策树应该是逐层使用symptoms中的症状作为决策节点,最终到达records中的叶子(疾病)节点,而不是把疾病加到症状列表里。缺少分支过滤逻辑
原代码没有根据症状是否存在来过滤对应的records子集,导致每个分支无法对应不同的疾病集合,自然无法生成有意义的决策路径。
修复后的完整代码
class Node: def __init__(self, data="", pos=None, neg=None): self.data = data self.positive_child = pos self.negative_child = neg def buildtree(symptoms, records): # 终止条件1:没有剩余症状,到达叶子节点 if not symptoms: return Node(records[0]) if records else Node() # 终止条件2:只剩一种疾病,直接返回叶子节点 if len(records) == 1: return Node(records[0]) current_symptom = symptoms[0] # 这里替换为真实的症状-疾病对应过滤逻辑 # 示例:临时按列表拆分模拟过滤(实际使用时根据疾病的症状标签划分) mid = len(records) // 2 records_with_symptom = records[:mid] records_without_symptom = records[mid:] # 递归构建正负分支:使用剩余症状+过滤后的疾病集合 positive_branch = buildtree(symptoms[1:], records_with_symptom) negative_branch = buildtree(symptoms[1:], records_without_symptom) # 返回当前决策节点 return Node(current_symptom, positive_branch, negative_branch) def get_leafs_from_records(records): optimal_illness = {} list_of_illnesses = [] illness_in_records=[] for record in records: if diagnoser.diagnose(record.symptoms) == record.illness: list_of_illnesses.append(record.illness) for illness in list_of_illnesses: if illness in optimal_illness: optimal_illness[illness] += 1 else: optimal_illness[illness] = 1 for illness in optimal_illness: illness_in_records.append(illness) return illness_in_records def build_tree(records, symptoms): records = get_leafs_from_records(records) return buildtree(symptoms, records)
关键修改说明
修正终止条件
- 当
symptoms为空时,说明已经遍历完所有决策层,直接返回records中的疾病作为叶子节点。 - 当
records只剩一种疾病时,直接返回该叶子节点,避免无意义的递归。
- 当
调整递归逻辑
每次取当前第一个症状作为决策节点,递归构建正负分支时使用剩余的症状列表,确保逐层向下构建完整的决策树结构。添加分支过滤逻辑(模拟)
原代码没有根据症状过滤疾病集合,这里加入了模拟的拆分逻辑。你需要将这部分替换为真实的业务逻辑:比如根据每个疾病是否包含当前症状,将records划分为两个子集,分别对应"有该症状"和"无该症状"的分支。
测试示例
调用build_tree(['dead','healthy','cold','influenza'], ['cough','sneezing','fever'])会生成一个三层决策树:
- 第一层:
cough节点,正分支对应['dead','healthy'],负分支对应['cold','influenza'] - 第二层:
sneezing节点,各自分支再拆分对应子集 - 第三层:
fever节点,最终分支到单个疾病叶子节点
内容的提问来源于stack exchange,提问作者Oday Haj Yehia

