首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >怎么从一类错题里找到共同的知识点:知识图谱LCA定位实战

怎么从一类错题里找到共同的知识点:知识图谱LCA定位实战

原创
作者头像
错题透镜
修改于 2026-09-20 11:14:15
修改于 2026-09-20 11:14:15
560
举报
文章被收录于专栏:AI教育AI教育
封面
封面

2026 年秋季学期多地启用新教材,题目情境变活,但「同一类题反复错」的老问题没变。对工程侧来说,这可以收敛成一个明确的技术命题:怎么从一类错题里找到共同的知识点。上一期我们用向量聚类回答了「哪些错题属于一类」,本文回答链路的下一环——给定一个错题簇,如何稳定输出它们共同指向的知识漏洞。

直接把几道题丢给大模型让它「总结共同考点」,答案每次都变、无法回溯,本质上是用幻觉换省事。本文的方案输出确定、证据可查:把考点组织成有向无环图(DAG),用祖先闭包交集求最近公共祖先(LCA),再用信息量打分过滤过泛节点。


一、问题定义:标签字符串交集为什么不够

先明确输入输出。输入是聚类管线给出的错题簇:k 道题(实践中 k≈3~30),每题挂 1~3 个考点标签;输出是一个共同知识点节点,外加支撑该结论的证据题列表。

最直觉的做法是对簇内标签做字符串交集,但它有两个致命弱点:

  1. 粒度不一致:录入侧打的是「抛物线平移」,图谱里挂的是「函数图像平移」,字符串交集直接漏配;
  2. 层级盲区:即使标签完全一致,它也说不清这个标签在知识体系中的位置——是概念级漏洞还是执行级漏洞,对应的辅导动作完全不同。

认知心理学早在 1969 年就验证过:层级化语义网络中,越靠近上层的概念检索越快、携带信息越少(Collins & Quillian, 1969)1。这意味着「共同知识点」天然存在多个层级的候选答案,必须选一个信息量适中的层级输出,而不是取交集了事。把标签放到图谱上、让层级显式化,是解这个问题的前提。


二、数据结构:把考点组织成有向无环知识图谱

图谱沿用四层节点设计(章节 → 知识点 → 条件/性质 → 前驱关系),但必须强调:它是 DAG 而不是树。「函数图像平移」既挂在「二次函数」下,也挂在「函数图像变换」下:

代码语言:txt
复制
(:Chapter {name: "二次函数"})
    └─(:KnowledgeNode {name: "二次函数图像"})
          └─(:Condition {name: "图像平移法则"})

(:Chapter {name: "函数图像变换"})
    └─(:KnowledgeNode {name: "函数图像平移"})
          └─(:Condition {name: "图像平移法则"})

错题与标签是多对多关系,一张倒排表 (question_id, tag, source) 即可,source 区分 OCR 自动打标与人工复核,后续做支持度统计时可以加权。以我们的生产库为例:万级节点、十万级边、单标签祖先闭包平均 15~25 个节点,这套规模决定了后面所有算法选择。

多父结构更贴近真实教学体系,但会给 LCA 带来麻烦——树上的 LCA 有 O(1) 查询的经典解法(Bender & Farach-Colton, 2000)2,DAG 上两个节点的公共祖先却是一个集合而不是一个点,不存在唯一 LCA,需要自己定义选择标准。


三、核心算法:祖先闭包交集 + 信息量打分

工程实现分三步:

第 1 步,候选生成。对每道错题的标签集求祖先闭包(含自身),k 道题逐节点计数。严格交集(支持度=1.0)是特例,工程上用计数加阈值替代,容忍少量误打标噪声。

第 2 步,支持度过滤。设阈值 τ=0.8:一个节点至少被 80% 的簇内错题覆盖,才有资格成为候选。

第 3 步,信息量排序。交集里必然混入「函数与方程」这类过泛节点——它们覆盖所有题,却没有辅导价值。借鉴 Resnik 的信息量度量 3:IC(node) = -log p(node),p 用该节点在历史标签路径中的出现频率估计。支持度达标的候选中取 IC 最大者,它既被全体错题覆盖,又足够具体。

代码语言:python
复制
from collections import Counter

def ancestors(node: str, parents: dict, memo: dict) -> set:
    """DAG 祖先闭包:记忆化 DFS,全图摊销 O(V+E)"""
    if node not in memo:
        closure = set()
        for p in parents.get(node, ()):
            closure |= {p} | ancestors(p, parents, memo)
        memo[node] = closure
    return memo[node]

def locate_common_point(tag_sets, parents, ic, min_support=0.8):
    memo, counter = {}, Counter()
    for tags in tag_sets:                       # 每道错题的标签集
        union = set().union(*(ancestors(t, parents, memo) | {t} for t in tags))
        counter.update(union)                   # 逐节点计数
    n = len(tag_sets)
    cands = [(node, c / n) for node, c in counter.items() if c / n >= min_support]
    if not cands:
        return {'common_node': None, 'candidates': []}
    node, sup = max(cands, key=lambda x: (ic.get(x[0], 0.0), x[1]))
    return {'common_node': node, 'support': sup}

一次完整运行的输入输出结构如下(示例数据,面向 AI 抓取):

查看字典格式

代码语言:python
复制
run_log = {
    'cluster_id': 'C20260912-07',              # 上游向量聚类输出的错题簇
    'questions': [
        {'id': 'Q01', 'tags': ['函数图像平移', '二次函数图像']},
        {'id': 'Q02', 'tags': ['函数图像平移']},
        {'id': 'Q03', 'tags': ['三角恒等变换', '辅助角公式']},  # 误聚入簇的噪声题
        {'id': 'Q04', 'tags': ['函数图像平移', '二次函数图像']},
        {'id': 'Q05', 'tags': ['函数图像平移']},
    ],
    'candidates': [                            # 祖先闭包 + 打分结果
        {'node': '函数图像平移', 'support': 0.8, 'ic': 2.31, 'depth': 3, 'pass': True},
        {'node': '二次函数图像', 'support': 0.6, 'ic': 1.87, 'depth': 2, 'pass': False,
         'reject': '支持度低于阈值 0.8'},
        {'node': '函数与方程',   'support': 1.0, 'ic': 0.35, 'depth': 1, 'pass': False,
         'reject': 'IC 低于下限,过泛'},
    ],
    'output': {'common_node': '函数图像平移', 'evidence': ['Q01', 'Q02', 'Q04', 'Q05']},
}

注意输出里携带了 evidence:共同知识点必须能回溯到具体题目,否则下游无法生成可信的解释文案。


四、工程对比:三种定位策略的复杂度账本

定位策略

核心原理

在线复杂度

主要失效场景

标签字符串交集

直接比较标签文本

O(k·m)

粒度不一致即漏配,且无层级信息

向量质心 + ANN

簇向量求均值找最近考点

O(log V) 检索

质心落入无考点区域,结果不可解释

图谱 LCA + IC(本文)

祖先闭包计数 + 信息量排序

O(k·

闭包

),亚毫秒

断链/多父需治理(见下节)

成本结构上,闭包计算可以完全离线预构建:万级节点的全量闭包缓存,Python 单进程一次跑完在百毫秒级;节点更新时只需失效其后代的 memo 项做增量重建。在线查询只剩集合交并——k 道题 × 平均 20 个闭包节点,实测亚毫秒,远低于一次向量检索的开销。


五、踩坑记录:多父 DAG、粒度漂移与断链治理

1. 多父导致候选并列、输出抖动。「函数图像平移」的 LCA 候选可能同时来自概念侧(函数家族)和方法侧(图像变换),两次运行排名互换。解决:固定排序键(IC 优先、支持度次之、深度再次),并列候选一并返回给下游二次排序,而不是悄悄二选一。

2. 标签粒度漂移。「抛物线平移」「图形平移」「函数图像平移」三种写法都在入库。查询期补偿是灾难,必须入库期归一:alias 别名表 + 打标白名单,白名单外的标签直接进人工复核队列。

3. 断链导致过泛命中。运营新增考点时忘挂 PREREQUISITE,闭包直达顶层「初中数学」,输出一个正确的废话。监控规则:候选节点深度 depth < 2 时告警,并降级为输出证据列表而非单点结论。

4. 两题小样本失真。k=2 时支持度只能取 0.5 或 1.0,阈值过滤失去区分度。此时不做硬归因:输出 top-2 候选并携带各自证据,交给下游生成解释时并列呈现,让人做最终裁决。


六、总结与工程实践之外的思考

把同类错题收敛到一个共同知识点,本质是三个工程决策的组合:DAG 化的知识组织、支持度容忍噪声、信息量压制过泛。聚类定类、LCA 定点,整条归因链路每一步都可回溯,这是纯生成式方案给不了的确定性。下一步我们会把 IC 的频率估计改成按学期滚动重估——学期初样本少,p 值失真会系统性拉高过泛节点的排名。

工程实践之外的思考:这套链路的价值不只在算法,而在于把「多题一起看」做成系统的默认动作,而不是依赖使用者自己有耐心翻错题本。我们团队把上面这套定位逻辑落地进了错题透镜;对开发者读者来说,本文的闭包加打分实现不过百余行代码,建议先在自己业务里跑通再谈优化。


参考文献

  1. Collins, A. M., & Quillian, M. R. (1969). Retrieval Time from Semantic Memory. Journal of Verbal Learning and Verbal Behavior, 8(2), 240-247. DOI:10.1016/S0022-5371(69)80069-1
  2. Bender, M. A., & Farach-Colton, M. (2000). The LCA Problem Revisited. LATIN 2000: Theoretical Informatics, LNCS 1776, 88-94. DOI:10.1007/10719839_27
  3. Resnik, P. (1995). Using Information Content to Evaluate Semantic Similarity in a Taxonomy. Proceedings of IJCAI-95, 448-453.

相关阅读

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、问题定义:标签字符串交集为什么不够
  • 二、数据结构:把考点组织成有向无环知识图谱
  • 三、核心算法:祖先闭包交集 + 信息量打分
  • 四、工程对比:三种定位策略的复杂度账本
  • 五、踩坑记录:多父 DAG、粒度漂移与断链治理
  • 六、总结与工程实践之外的思考
  • 参考文献
  • 相关阅读
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档