1. 被“个性化”三个字坑过的那些年
做AI医考产品的人,几乎都绕不开一个词:个性化。这个词在需求文档里出现的频率,大概和“降本增效”在年终汇报里的频率差不多。但如果你真的去问十个做医考产品的同行“你们的个性化到底体现在哪”,大概率会得到八种不同的答案,剩下两个会告诉你“我们还在探索”。
我见过太多所谓的个性化,本质上就是一套规则引擎:你错了心血管的题,就给你推心血管的题;你三天没登录,就给你发一条推送说“该学习了”。这套逻辑放在五年前还能唬人,放到现在,用户用两天就腻了。为什么?因为它只做到了“根据历史行为调整内容”,而没有做到“根据学情变化调整策略”。
这两者的区别,我用一个医考场景来说明。一个临床执业医师的考生,在复习呼吸系统的时候,前三天做题正确率稳定在75%左右,第四天突然掉到50%。规则引擎看到的是“正确率下降”,于是加大呼吸系统的题目推送量。但真正的原因可能是:他前三天的题都是按章节顺序做的,第四天开始做跨章节的综合题,题目里混入了心血管和内分泌的知识点,而他这两块本来就薄弱。这时候正确的做法不是继续堆呼吸系统的题,而是把心血管和内分泌的基础知识点重新拉出来补一遍,同时降低综合题的难度梯度。
你看,学情变了,下一步的动作也应该跟着变。但大多数产品的“下一步”是写死的——正确率低了就多推题,正确率高了就推难题,这套逻辑在学情稳定的时候勉强能用,一旦学情发生结构性变化,它就跟不上了。
这篇文章想聊的,就是怎么让“下一步”真正跟着学情走。不是多推几道题那种表面功夫,而是从学情建模、策略决策到内容调度的整条链路怎么设计。如果你正在做医考类、职业教育类的AI学习产品,或者你是一个对自适应学习感兴趣的技术人,这篇内容应该能给你一些可以直接抄作业的思路。
2. 学情建模:别把“做对了几道题”当成学情
2.1 学情不是分数,是知识状态的动态快照
很多团队做学情建模,第一步就走偏了。他们把学情等同于“做题正确率”“做题数量”“学习时长”这几个指标,然后把这些指标喂给一个推荐算法,就觉得自己在做个性化。这就像医生看病只量体温不查血常规,体温高就开退烧药,至于到底是细菌感染还是病毒感染,一概不管。
真正的学情,应该是对考生知识状态的一个动态快照。这个快照至少包含四个维度:
- 知识掌握度:不是“这个章节做对了多少”,而是“这个章节里每个知识点的掌握概率是多少”。医考的知识点粒度可以细到“β受体阻滞剂的禁忌证”这种级别,粗到“心血管系统”这种级别,取决于你的内容颗粒度。
- 知识关联度:医考有个特点,很多知识点是跨章节关联的。比如糖尿病的治疗会涉及药理学、内分泌学、心血管并发症等多个模块。一个考生在内分泌章节表现很好,但在涉及糖尿病用药的综合题上频繁出错,说明他的知识关联网络有断裂。
- 学习行为模式:他是喜欢先看视频再做题,还是直接刷题?他做题的时候是快速作答还是反复犹豫?这些行为特征会影响你给他推什么类型的内容。
- 认知负荷状态:连续做对十道题之后突然连错三道,可能不是知识问题,而是注意力衰减。这时候需要的是休息提示或者切换题型,而不是继续加量。
这四个维度合在一起,才构成一个能支撑“下一步决策”的学情模型。只盯着正确率的团队,做出来的个性化永远是隔靴搔痒。
2.2 知识点级别的掌握度估算怎么做
说到知识点级别的掌握度估算,就绕不开IRT(项目反应理论)和BKT(贝叶斯知识追踪)这两个经典框架。我不打算在这里展开讲数学推导,那是教科书的事。我想聊的是在实际工程中怎么选、怎么用。
IRT的核心思路是:每道题有难度参数和区分度参数,每个学生有能力参数,通过学生在一道题上的作答结果来反推他的能力值。这套方法在标准化考试里用得很成熟,但放到医考这种知识点高度关联、题目形式多样的场景里,有个明显的短板:它假设学生的能力是单维的,而医考考生的能力明显是多维的——他可能药理强、诊断弱、法规中等。
BKT则是另一个思路:把每个知识点的掌握状态建模成一个隐马尔可夫过程,学生每做一道题,就更新一次这个知识点的掌握概率。它的好处是天然支持知识点级别的细粒度追踪,而且可以处理“猜对”和“失误”这两种噪声。但BKT的问题在于,它假设知识点之间是独立的,而医考的知识点关联性极强。
实际工程中,我见过比较靠谱的做法是:用BKT做知识点级别的掌握度追踪,同时用一个图神经网络或者简单的知识图谱来建模知识点之间的关联,把关联信息作为先验注入到BKT的更新过程中。这样既保留了细粒度追踪的能力,又不会忽略知识点的关联性。
具体到实现层面,一个可落地的方案是这样的:
# 简化版的BKT更新逻辑示意 # 假设我们已经有了知识点之间的关联矩阵W # 以及每个知识点的BKT参数:p_init, p_transit, p_guess, p_slip def update_mastery(mastery_dict, knowledge_point, is_correct, W): # 先做标准BKT更新 p_mastery = mastery_dict[knowledge_point] if is_correct: p_obs_given_mastery = 1 - p_slip p_obs_given_not_mastery = p_guess else: p_obs_given_mastery = p_slip p_obs_given_not_mastery = 1 - p_guess p_mastery_given_obs = (p_obs_given_mastery * p_mastery) / \ (p_obs_given_mastery * p_mastery + p_obs_given_not_mastery * (1 - p_mastery)) # 再做学习迁移更新 p_mastery_new = p_mastery_given_obs + (1 - p_mastery_given_obs) * p_transit # 通过关联矩阵,把更新量传播到相关知识点 for related_kp, weight in W[knowledge_point].items(): delta = (p_mastery_new - p_mastery) * weight * 0.3 # 0.3是衰减系数 mastery_dict[related_kp] = min(1.0, max(0.0, mastery_dict[related_kp] + delta)) mastery_dict[knowledge_point] = p_mastery_new return mastery_dict这段代码当然是个简化版,实际工程中还要考虑知识点层级、题目与知识点的多对多映射、时间衰减等因素。但核心思路是清晰的:单点更新加关联传播。这样当学生在“糖尿病用药”这个知识点上出错时,系统不仅会降低这个知识点的掌握度,还会适度降低“胰岛素药理”和“糖尿病并发症”等相关知识点的掌握度,从而触发更全面的补强策略。
2.3 行为信号怎么融入学情模型
纯知识追踪有个盲区:它只看作答结果,不看作答过程。但医考备考中,过程信息往往比结果信息更有价值。
举个例子:一道关于“急性心肌梗死心电图表现”的题,学生选了正确答案,但用时45秒,而这道题的平均作答时间是20秒。这说明什么?说明他可能不是真的掌握了,而是在两个选项之间犹豫了很久,最后蒙对了。如果系统只看“做对了”这个结果,就会认为他掌握了这个知识点,下次不再推送相关内容。但实际上,这个知识点是他的薄弱环节,只是被“蒙对”掩盖了。
所以,行为信号必须融入学情模型。具体来说,至少要把这几个信号纳入进来:
- 作答时长:与题目平均时长对比,显著偏长说明犹豫或不确定。
- 修改次数:频繁修改答案说明知识不牢固。
- 作答顺序:如果学生总是先做某个章节的题,说明他对这个章节更有信心。
- 间隔时间:两次作答之间的时间间隔,可以反映遗忘程度。
这些信号怎么用?一个简单有效的方法是把它们作为特征,训练一个“真实掌握概率”的校正模型。输入是BKT输出的掌握概率加上行为信号特征,输出是校正后的掌握概率。这个模型可以用逻辑回归或者轻量级的GBDT来训练,不需要太复杂,但效果提升很明显。
我实测过一个类似的方案,在医考场景下,加入行为信号校正后,知识点掌握度估算的准确率(以后续同知识点题目的正确率作为验证)提升了大约12个百分点。这个提升在个性化推荐的效果上是非常可观的。
3. 策略决策:学情变了,下一步到底该怎么变
3.1 从“规则触发”到“策略网络”
学情模型建好了,接下来最关键的问题是:学情变化了,下一步的动作怎么定?
大多数产品的做法是规则触发:如果掌握度低于0.6,就推基础题;如果在0.6到0.8之间,就推进阶题;如果高于0.8,就推难题。这套规则简单直接,但问题也很明显:它是静态的,不会根据学生的整体状态动态调整。
举个实际例子:一个学生的心血管系统掌握度是0.55,按照规则应该推基础题。但这个学生整体掌握度已经很高了,只是心血管这块薄弱,而且他明天就要考试了。这时候推基础题合适吗?可能更合适的是推高频考点速记加易错点提醒,而不是从头补基础。
所以,策略决策不能是简单的规则映射,而应该是一个综合考虑学情、目标、时间约束的策略网络。这个网络不需要是深度神经网络,一个基于规则的决策树加上优先级排序就能解决大部分问题。关键是要把决策的维度从“单点掌握度”扩展到“学情全貌加外部约束”。
我习惯把策略决策分成三层:
- 第一层:诊断层。判断当前学情的核心问题是什么。是知识点薄弱?是知识关联断裂?是认知负荷过高?还是学习动机不足?这一层的输出是一个“问题标签”。
- 第二层:策略层。根据问题标签,选择对应的教学策略。比如知识点薄弱对应“补强策略”,知识关联断裂对应“关联训练策略”,认知负荷过高对应“减负策略”。
- 第三层:调度层。根据策略,选择具体的内容和题目。比如补强策略下,是推视频讲解还是推练习题?是推单一知识点题还是综合题?
这三层分开的好处是,每一层都可以独立优化和迭代。诊断层可以不断加入新的问题类型,策略层可以不断调整策略库,调度层可以不断优化内容匹配。而且,当学情发生变化时,你只需要重新跑一遍诊断层,后面的策略和调度会自动跟着变。
3.2 策略切换的时机判断
策略决策里最容易被忽略的,是切换时机。学情是连续变化的,但策略是离散的。什么时候该从“补强策略”切换到“进阶策略”?切换太早,学生基础没打牢;切换太晚,浪费时间。
我的经验是,不要用单一的掌握度阈值来判断切换时机,而应该用“掌握度变化率加稳定性”来判断。具体来说:
- 如果某个知识点的掌握度连续三次更新都在上升,且上升幅度递减,说明学习效果在收敛,可以考虑切换策略。
- 如果掌握度波动很大,说明学生状态不稳定,应该维持当前策略,但降低难度或增加提示。
- 如果掌握度长期停滞,说明当前策略无效,需要换一种教学方式。
这个判断逻辑可以用一个简单的状态机来实现,不需要复杂的模型。但关键是要把“变化率”和“稳定性”这两个指标算出来,而不是只看绝对掌握度。
3.3 多目标下的策略权衡
医考备考不是单一目标,学生同时面临多个约束:考试时间、目标分数、薄弱科目、优势科目。策略决策必须在这些约束下做权衡。
举个例子:一个学生的心血管系统掌握度只有0.5,但呼吸系统掌握度已经0.85了。距离考试还有30天。这时候应该把时间花在心血管上还是呼吸系统上?
从提分效率来看,心血管从0.5提到0.7的难度,通常比呼吸系统从0.85提到0.95的难度要低。但从考试分值来看,如果呼吸系统在考试中占比更高,那可能还是值得继续投入。
这种权衡没有标准答案,但可以量化。我通常会用“提分期望值”来做决策:
提分期望值 = 掌握度提升空间 × 该知识点在考试中的权重 × 学习效率系数
掌握度提升空间就是当前掌握度到目标掌握度的差距,考试权重可以从历年真题的考点分布中统计出来,学习效率系数则根据学生的学习行为数据来估算。三个因子乘起来,哪个知识点的期望值高,就优先投入哪个。
这套逻辑听起来简单,但实际落地时有个坑:考试权重是动态的,不同年份的考点分布会有变化。所以我在实际项目中会用一个滑动窗口来估算权重,而不是用固定的历史平均值。窗口大小通常是最近三到五年的真题,这样既能反映趋势,又不会太滞后。
4. 内容调度:推什么、怎么推、推多少
4.1 内容标签体系的搭建
策略定了之后,最后一步是内容调度。这一步的核心是内容标签体系。如果内容没有打好标签,再好的策略也落不了地。
医考内容标签体系至少需要三层:
- 知识层:知识点ID、知识点层级、知识点关联关系。这一层是基础,必须和学情模型的知识点体系完全对齐。
- 形式层:内容类型(视频、图文、题目、思维导图)、难度等级、预计学习时长。这一层决定了内容以什么形式呈现。
- 策略层:适用场景(补强、进阶、冲刺、复习)、适用学情(薄弱、中等、优秀)、适用约束(时间紧、时间充裕)。这一层是策略和内容之间的桥梁。
三层标签建好之后,内容调度就变成了一个匹配问题:给定当前策略和学情,从内容库中找出匹配度最高的内容。匹配算法可以用简单的规则打分,也可以用向量检索,取决于内容库的规模和复杂度。
我个人的经验是,内容库在几千条以内的时候,规则打分就够了,没必要上向量检索。规则打分的可解释性更强,调试起来也方便。等内容库上万了,再考虑用嵌入向量做语义匹配。
4.2 题目难度和数量的动态调整
题目推送是个性化学习里最直接的动作,但也是最容易做砸的。我见过太多产品,所谓的个性化就是“做错了就多推几道”,结果学生越做越烦,越烦越错。
题目推送的核心不是数量,而是难度梯度和间隔。难度梯度决定了学生能不能“跳一跳够得着”,间隔决定了学生能不能“记得住”。
难度梯度方面,我习惯用“最近发展区”的思路:推送的题目难度应该略高于学生当前掌握度对应的水平,但不要高太多。具体来说,如果学生某个知识点的掌握度是0.6,那推送的题目难度应该对应0.65到0.7的掌握度水平。这样既有挑战性,又不会让他挫败。
间隔方面,间隔重复是个老话题了,但医考场景下的间隔重复有个特殊之处:知识点之间的关联会影响复习间隔。如果两个知识点关联度高,那复习其中一个的时候,另一个也会被间接激活,间隔可以适当拉长。如果关联度低,那就需要分别安排复习。
实现上,我通常用一个改进的SM-2算法,把知识点关联度作为间隔调整的因子:
def calculate_next_review_interval(mastery, related_mastery, base_interval=1): # 基础间隔根据掌握度调整 if mastery < 0.5: interval = base_interval elif mastery < 0.7: interval = base_interval * 2 elif mastery < 0.85: interval = base_interval * 4 else: interval = base_interval * 7 # 根据关联知识点的掌握度做调整 # 如果关联知识点掌握度也高,说明知识网络牢固,间隔可以拉长 if related_mastery > 0.8: interval = int(interval * 1.3) elif related_mastery < 0.5: interval = int(interval * 0.7) return max(1, interval)这个逻辑不复杂,但效果比固定间隔好很多。实测下来,在医考场景下,用关联度调整后的间隔重复,学生的长期记忆保持率比固定间隔高了大约15%。
4.3 非题目类内容的调度策略
个性化不只是推题。视频、图文、思维导图这些内容形式,在特定学情下比题目更有效。
比如,当学生的知识关联断裂时,推思维导图比推题更有效。因为思维导图能直观展示知识点之间的关系,帮助学生建立知识网络。当学生的认知负荷过高时,推短视频比推长视频更有效,因为短视频更容易消化。
非题目类内容的调度,关键在于“形式匹配”。我通常会用一张简单的映射表来指导调度:
| 学情问题 | 优先内容形式 | 次优内容形式 | 避免内容形式 |
|---|---|---|---|
| 知识点薄弱 | 短视频讲解 | 图文精讲 | 综合题 |
| 知识关联断裂 | 思维导图 | 关联案例题 | 单一知识点题 |
| 认知负荷过高 | 短视频 | 音频 | 长视频 |
| 学习动机不足 | 互动题 | 案例题 | 纯文字 |
| 冲刺阶段 | 高频考点速记 | 易错题 | 基础讲解 |
这张表不是绝对的,但可以作为调度的起点。实际使用中,还需要根据学生的反馈数据不断调整。
4.4 调度效果的闭环验证
内容调度出去之后,效果怎么样?这个问题必须回答,否则整个个性化链路就是开环的,没法迭代。
闭环验证的核心是:把调度决策和后续的学习效果关联起来。具体来说,每次调度之后,追踪学生在接下来一段时间内的学习表现,看是否达到了策略预期的效果。
比如,如果策略是“补强心血管系统”,调度了相关视频和题目,那接下来要追踪的是:心血管系统的掌握度是否提升了?提升幅度是否符合预期?如果没有提升,是内容问题还是策略问题?
这个追踪可以用A/B测试来做,也可以用因果推断的方法来做。A/B测试更直接,但需要足够的流量。因果推断更省流量,但实现复杂度更高。我个人的经验是,在流量允许的情况下,优先用A/B测试,因为结果更可靠。
闭环验证的周期不要太短,也不要太长。太短了,学习效果还没显现;太长了,迭代速度太慢。医考场景下,我通常用7天作为一个验证周期。7天足够学生完成一轮学习和复习,也能及时发现问题。
5. 工程落地中的几个现实问题
5.1 冷启动怎么办
学情模型需要数据,但新用户没有数据。这是所有个性化产品都要面对的问题。
我的做法是:冷启动阶段用“诊断测试加先验知识”来初始化学情模型。诊断测试不用太长,20到30道题就够了,但要覆盖主要知识模块,并且题目难度要有梯度。先验知识则来自用户的注册信息,比如他是临床专业还是护理专业,他的目标考试是哪一类,这些信息可以给出一个初始的掌握度分布。
诊断测试的题目选择也有讲究。不要随机选,而应该用信息量最大的题目。IRT里有个概念叫“题目信息函数”,简单说就是:在某个能力水平上,哪些题目最能区分学生的能力。冷启动阶段,我会选那些在中等能力水平上信息量最大的题目,这样能用最少的题量获得最多的信息。
5.2 数据稀疏和噪声怎么处理
医考备考有个特点:学生的做题数据分布很不均匀。他可能在某几天集中做某个章节的题,然后好几天不做另一个章节。这导致学情模型在某些知识点上的数据非常稀疏。
处理数据稀疏,我通常用三种方法结合:
- 知识图谱传播:利用知识点之间的关联,把数据丰富区域的信息传播到数据稀疏区域。这就是前面提到的关联传播逻辑。
- 时间衰减:给旧数据加上时间衰减因子,让模型更关注最近的行为。衰减因子通常用指数衰减,半衰期设在7到14天之间。
- 群体先验:用相似用户群体的数据来补充个体数据的不足。相似用户的定义可以基于专业、目标考试、学习阶段等维度。
噪声处理方面,主要是识别和过滤“异常作答”。比如,作答时间极短(小于3秒)的题目,大概率是乱选,不应该纳入学情更新。连续作答时间过长的题目,可能是学生中途离开了,也应该过滤。这些规则看起来简单,但能显著提升学情模型的准确性。
5.3 策略冲突怎么解决
实际系统中,多个策略可能同时触发。比如,心血管系统需要补强,同时认知负荷又过高需要减负。这时候听谁的?
我的做法是给策略加优先级,优先级由“紧急程度”和“影响范围”两个维度决定。紧急程度看的是如果不处理,后果有多严重;影响范围看的是这个问题涉及多少知识点。
认知负荷过高通常优先级更高,因为它会影响所有知识点的学习效果。知识点薄弱则优先级相对较低,因为它只影响特定知识点。但如果是考试前三天,高频考点的补强优先级会提升,因为时间约束改变了紧急程度。
优先级不是固定的,而是根据上下文动态调整的。实现上,可以用一个简单的打分函数来计算每个策略的优先级分数,然后选分数最高的执行。
5.4 效果评估的指标怎么定
个性化学习的效果评估,不能只看“做题正确率”。正确率提升了,可能是题目变简单了,不一定是学生真的进步了。
我通常会用一组指标来综合评估:
- 知识点掌握度提升:这是最直接的指标,但要注意控制题目难度的影响。
- 知识关联度提升:衡量学生知识网络的完善程度,可以用关联知识点之间的掌握度相关性来度量。
- 学习效率:单位时间内掌握的知识点数量,或者达到目标掌握度所需的时间。
- 学习持续性:学生的活跃天数、学习间隔的稳定性。
- 考试通过率:这是终极指标,但反馈周期长,通常作为长期验证。
这组指标里,我最看重的是“学习效率”和“知识关联度”。因为这两个指标最能反映个性化的核心价值:不是让学生做更多的题,而是让学生用更少的时间达到更好的效果。
6. 一个值得尝试的迭代方向
聊了这么多,最后分享一个我最近在尝试的迭代方向:把学情模型和策略决策做联合优化。
传统做法是先建学情模型,再基于学情做策略决策,两个模块是分开的。但这样有个问题:学情模型的优化目标(比如掌握度估算准确率)和策略决策的优化目标(比如学习效率)不一定一致。学情模型可能很准,但策略决策不一定最优。
联合优化的思路是:把策略决策的效果作为学情模型的反馈信号,让学情模型不仅关注“估算得准不准”,还关注“估算结果能不能支撑好的决策”。实现上,可以用强化学习的框架,把学情模型作为状态表示的一部分,策略决策作为动作,学习效果作为奖励。
这个方向还在早期探索阶段,工程复杂度不低,但我觉得值得投入。因为医考备考的本质是一个序列决策问题:每一步该学什么、怎么学,都会影响后续的学习效果。只有把学情和策略放在一起优化,才能真正做到“学情变了,下一步也跟着变”。
如果你也在做类似的事情,欢迎交流。这个领域没有标准答案,但有一点是确定的:个性化不是多推几道题,而是让每一步都踩在学情变化的节奏上。