资讯动态

DINA认知诊断模型:从总分到知识点画像的题诊断研究

发布时间:2026/10/16 9:42:46 来源:尧图企业网站定制
简介这是一篇发表于《中国考试》2013年第1期的认知诊断DINA模型研究综述作者为南京师范大学张潇、沙如雪适合心理测量学、教育统计与个性化教学研究者阅读。资源以PDF格式提供包含期刊原文共1个文件压缩包约1.31MB内容系统梳理DINA模型的原理、Q矩阵、失误与猜测参数并重点介绍HO-DINA、P-DINA、G-DINA等改进方向还结合分数减法认知属性示例说明模型应用方式。已有517人学习适合作为认知诊断模型入门与论文写作参考可帮助读者快速把握DINA模型从基础定义到前沿进展的整体脉络并为后续开展相关实证研究提供文献线索。1. 认知诊断DINA模型从「总分90分」到「知识点画像」的题诊断研究期末考试结束了某班一名学生总分90分应用题全对「一元二次方程判别式」相关的四道选择题却全部做错。传统测验只报告一个总分这个问题被完全掩盖。认知诊断DINA模型要解决的不是把分数算得更准而是把一次测验拆解成可解释的知识状态——每位被试到底掌握了哪几个属性缺了哪几个。这类模型在过去十几年里成为教育测量与智能题库研究中最活跃的方向之一而DINA是其中最经典、最适合当落地起点的那个结构简单、参数可解释、R语言生态成熟。适合读这篇笔记的人有三类做学业诊断研究的量化研究者、题库系统或自适应学习产品的算法工程师、以及正在为「怎么给学生出诊断报告」发愁的教研团队。前提是你手上有二值计分的作答数据和一份大致靠谱的题目-知识图谱。2. DINA模型机制拆解Q矩阵、与门规则与两个噪声参数的由来2.1 题目的知识画像Q矩阵与理想作答向量DINA全称是 Deterministic Input, Noisy AND gate中文常译作「确定性输入、噪声与门模型」。名字里的每一个词都对应一个具体设计Deterministic Input 指的是在理想情况下不考虑猜测和失误被试能不能答对某道题是完全确定的由他是否掌握题目涉及的全部属性决定Noisy AND gate 则说明这个确定性规则被两个噪声参数污染模型在「全或无」的理想作答外允许犯错。整个模型的第一个地基是 Q 矩阵。Q 是一个 J×K 的 0/1 矩阵J 是题目数K 是属性数也就是知识点数或认知属性数。第 j 行第 k 列取 1表示题目 j 测查了属性 k取 0 表示没测。比如一份 4 题、3 个属性的 Q 矩阵题目A1概念理解A2公式记忆A3计算执行I1100I2011I3110I4111这个矩阵决定了两个关键东西一是每道题需要哪些属性的组合二是被试的属性向量 α_i 如何映射到理想作答。属性向量是每位被试的 K 维 0/1 向量α_ik 1 表示被试 i 掌握了属性 k。理想作答 η 的计算规则是「与门」只有被试掌握了题目 j 所要求的全部属性η_ij 才等于 1否则为 0。公式写作$$\eta_{ij} \prod_{k1}^{K} \alpha_{ik}^{q_{jk}}$$这个连乘看起来抽象实际就是「缺一不可」。题目 I4 同时要求三个属性那么只掌握其中两个的被试理想作答就是 0。这是 DINA 与后面要提的 DINO 最本质的区别也是它名字里 AND gate 的来源。建模之前先问自己一句我设计的题目是不是真的满足「缺一不可」如果某道题掌握了任意一个属性都有较大概率做出来那它就不适合用 DINA 描述。2.2 两个噪声参数如何刻画「会而不对、不会而蒙」有了理想作答 η模型还远没有结束因为真实作答和理想作答之间总有偏差。有人掌握了全部属性但粗心算错有人一个属性都没掌握但蒙对了选项。DINA 用两个题目参数分别刻画这两种情况失误参数 s_j被试掌握了题目要求的所有属性却答错的概率猜测参数 g_j被试没有掌握全部要求属性却答对的概率。于是被试 i 在题目 j 上答对的概率可以写成很对称的形式$$P(X_{ij}1 \mid \alpha_i) (1 - s_j)^{\eta_{ij}} , g_j^{,1 - \eta_{ij}}$$当 η1 时答对概率是 1 - s_j当 η0 时答对概率是 g_j。这两个参数合在一起构成了 DINA 的完整似然。每条题目只有两个参数所以 DINA 是认知诊断模型族里参数最节俭的一类样本量要求相对友好。落地时有个经验判据值得记下来g_j s_j 越接近 1这道题提供的信息越少当 g s 超过 0.5 时被试答对与否和是否掌握属性几乎没关系了。我自己做估计时第一步永远是看 item 参数表里有没有 g 和 s 相加接近甚至超过 0.5 的题这种题要么是题目表述有问题要么是 Q 矩阵标定错了。2.3 从DINA到DINO、G-DINA模型族怎么选DINA 只是认知诊断模型族中的一员。理解它为什么被称作「研究进展的起点」需要把它和邻近模型放在一起看。DINODeterministic Input, Noisy OR gate把「与门」换成「或门」只要掌握了题目要求的任意一个属性理想作答就是 1。对应到现实场景就是「会其中一个方法就能解题」的题目比如一道题既可以用代入法也可以用排除法两种知识技能任一掌握都能做出来。DINO 的参数结构同样是每道题两个参数但理想作答的计算完全不同用错模型会导致参数估计整体偏移而不是某个值错了。再往上走是 G-DINAGeneralized DINA它不再预设「与门」或「或门」而是把每个属性及其交互项都放进线性展开里让数据自己说话。G-DINA 里 DINA 只是其中一个特殊情形——只保留形如 α_1α_2...α_K 的最高阶交互相其余项系数不参与。实际选型时我的习惯是样本量在 500 以上且不确定题目机制就用 G-DINA 作为基准再看简化成 DINA 后拟合是否明显变差样本量只有两三百优先 DINA因为它的参数少估计稳定性明显更高。下面用一张表总结这几个模型的差异模型理想作答规则适用题目特征每题目参数个数DINA与门缺一不可综合性强的题目技能不可替代2DINO或门任一即可解题方法可替换2ACDM属性线性可加各属性独立贡献答对概率K1G-DINA完全展开含交互机制不确定时优先尝试最多 2^K研究进展的脉络也很清晰先有 DINA 这类简洁模型然后被推广到 G-DINA 这样的统一框架再往高阶扩展出带高阶潜变量的模型、允许属性连续掌握的部分掌握模型、以及处理多次测评的动态认知诊断模型。对新入门的人来说直接追最新的模型等于跳过了地基建议从 DINA 跑通全流程再把同样的 Q 矩阵丢给 G-DINA 做对比至少能在一天内看到「更复杂的模型是否值得」。3. 搭好数据底座作答矩阵、Q矩阵编码与模拟数据生成3.1 最小可运行的数据形态dat 与 q.matrix 的组织规范R 里所有认知诊断包无论 CDM 还是 GDINA对数据的要求都大同小异最少需要两个对象作答矩阵和 Q 矩阵。作答矩阵习惯命名为 dat行是被试列是题目取值只有 0 和 11 表示答对Q 矩阵行是题目列是属性1 表示该题测查该属性。这个方向不能搞反否则一切计算都是错的。我第一次上手时就是把 Q 矩阵转置之后直接传进去结果模型跑了很久不收敛后来才发现是行列方向反了。两个矩阵之间还有一个硬性约定dat 的列名必须和 Q 矩阵的行名完全一致。换句话说作答矩阵里第一列的题目 ID必须能在 Q 矩阵的行名里找到对应条目。这个约定看上去简单实际很容易翻车尤其是从 Excel 或 CSV 读入数据时表格的行名可能被悄悄改成了数字。读取后第一件事就是做一致性检查我一般直接在代码里写一个 stopifnot 断言dat - read.csv(answer.csv, row.names 1) # 行是被试ID Q - read.csv(qmatrix.csv, row.names 1) # 行是题目ID # 检查题目一致且顺序一致 stopifnot(identical(colnames(dat), rownames(Q))) # 检查Q矩阵不能有全零行不允许出现不测任何属性的题目 stopifnot(all(rowSums(Q) 0))这段代码的逻辑是先用 row.names 1 保证读进来的行名是 ID 而不是默认的数字序号然后用 identical 比对两个矩阵的行列名。注意这里用的是 identical要求完全一致且顺序一致而不是用 %in% 只判断「都存在」。因为认知诊断模型假设 Q 矩阵第 j 行就是数据第 j 列对应题目的属性编码顺序错位不会报错但估计结果全错属于最典型的「静默翻车」。3.2 属性层级怎么标线性、收敛、发散三种结构的矩阵写法Q 矩阵只描述了「题目测了什么」但属性之间往往不是互相独立的。比如「计算执行」以「公式记忆」为前提那一个被试被估计为「掌握计算执行但没掌握公式记忆」就不符合认知逻辑。这种先决关系叫属性层级在建模时不该被忽略。常见的层级结构有三种线性型、收敛型、发散型。线性型意味着属性一条链式递进A1 是 A2 的前提A2 是 A3 的前提合法的属性模式只有 4 种而不是 8 种少了所有「跳级」的组合。收敛型是多个前提属性汇聚到一个高层属性发散型则是一个公共前提分别通向多个后继。无论哪种结构处理方式都是在拟合时传入一个合法模式集合把不合逻辑的属性模式排除掉。# 以3个属性、线性层级 A1 - A2 - A3 为例 legal_patterns - matrix( c(0,0,0, 1,0,0, 1,1,0, 1,1,1), ncol 3, byrow TRUE, dimnames list(NULL, c(A1, A2, A3)) ) # 在 din() 中通过 skillclasses 参数约束合法模式空间 res - CDM::din(dat dat, q.matrix Q, skillclasses legal_patterns)这里 skillclasses 参数接受一个 2^K 的合法模式子集每一行是一个允许出现的属性模式。加上约束之后估计结果里不会出现「跳级」的画像这也让输出更符合教学常识。不过有一点要提醒层级结构如果标错等价于给模型加了错误的约束比不加约束更糟。稳妥做法是先跑一个不加约束的模型看估计出的属性模式里有多少比例落在合法集合外如果比例很低说明数据本身支持层级假设再正式加入约束。3.3 先用模拟数据验证估计器一套可复现的生成代码在拿真实数据拟合之前强烈建议先用模拟数据跑通一遍流程给定真实的 Q 矩阵、真实的属性分布和真实的 g/s 参数按 DINA 机制生成作答数据再去拟合看估计值能否回到真实值附近。这个过程能同时验证你的数据格式是否正确、代码链路是否通畅、对输出字段的理解是否准确。下面是一套可以直接复制运行的模拟代码set.seed(20240601) # 固定随机种子结果可复现 K - 4 # 属性个数 J - 12 # 题目个数 N - 500 # 被试人数 # 1) 生成属性向量每个属性独立地以0.5概率被掌握 alpha - matrix(rbinom(N * K, size 1, prob 0.5), nrow N, ncol K) colnames(alpha) - paste0(A, 1:K) # 2) 设计Q矩阵单属性、双属性、三属性、四属性题混合 Q - matrix(0, nrow J, ncol K, dimnames list(paste0(I, 1:J), paste0(A, 1:K))) Q[1, 1] - 1 # 单属性题 Q[2, 2] - 1 Q[3, 3] - 1 Q[4, 4] - 1 Q[5, c(1, 2)] - 1 # 双属性题 Q[6, c(2, 3)] - 1 Q[7, c(3, 4)] - 1 Q[8, c(1, 4)] - 1 Q[9, c(1, 2, 3)] - 1 # 三属性题 Q[10, c(1, 3, 4)] - 1 Q[11, c(2, 3, 4)] - 1 Q[12, c(1, 2, 3, 4)] - 1 # 四属性题 # 3) 设置每题真实参数范围控制在0.05~0.15之间 s - runif(J, 0.05, 0.15) # 失误参数 g - runif(J, 0.05, 0.15) # 猜测参数 # 4) 计算理想作答与门规则 eta - matrix(0, nrow N, ncol J) for (j in 1:J) { req - which(Q[j, ] 1) # 第j题考察哪些属性 eta[, j] - as.numeric( rowSums(alpha[, req, drop FALSE]) length(req) ) } # 5) 按题目参数生成作答 Y - matrix(0, nrow N, ncol J, dimnames list(paste0(stu, 1:N), paste0(I, 1:J))) for (j in 1:J) { p - ifelse(eta[, j] 1, 1 - s[j], g[j]) Y[, j] - rbinom(N, size 1, prob p) }这段代码的关键在第 4 步对每道题先找出它要求的属性列再逐个被试检查这些列上是否全部为 1全部为 1 才记录理想作答为 1。drop FALSE 是为了防止 Q 矩阵某行只有一个 1 时取出的子矩阵退化成向量导致 rowSums 报错。第 5 步里 ifelse 是对向量化的熟练运用——eta 为 1 的被试按失误概率答错eta 为 0 的按猜测概率答对。生成完数据后你可以把真实 g/s 存下来后面拟合完对比看看差了多少这是验证整个流程是否走通的黄金标准。4. 跑通DINA估计CDM包的完整命令链与参数解读4.1 首跑命令din()最小调用与关键输出字段R 里拟合 DINA 最常用的是 CDM 包它同时支持 DINA、DINO、G-DINA 等多个模型接口统一。最小调用只需要把作答矩阵和 Q 矩阵传进去library(CDM) res - CDM::din(dat Y, q.matrix Q, maxit 500) summary(res)din() 的核心参数就三个dat 传入二值作答矩阵q.matrix 传入 Q 矩阵maxit 控制 EM 算法最大迭代次数。运行结束后summary(res) 会显示模型的对数似然、题目参数估计值和属性掌握比例。初次跑通后先别急着看别的直接看 res$item 这个字段它是题目参数的估计结果表。# 查看每题估计的猜测与失误参数 round(res$item, 3)res$item 是一个 J 行、多列的矩阵核心列包含 guessg 的估计值、slips 的估计值以及它们的标准误。把这几列和模拟时设置的真实值对比如果偏差在 0.03 以内说明估计链路正常如果 g/s 明显偏离真实值甚至跑到 0.5 以上就要回去检查 Q 矩阵和数据的列名匹配了。我在模拟验证时习惯把真实 g/s 用 cbind 和估计值放同一张表里一眼就能看出哪些题目估计得不准。4.2 把结果变成画像MAP属性模式与后验概率的用法DINA 估计完成后模型给出的不仅是几个参数每个被试还会得到一个属性模式。输出对象中的 attribute 字段直接给出了每一位被试最可能的 0/1 属性画像这是后端出报告最直接的输入# 取出每位被试的MAP属性模式 profile - res$attribute head(profile, 10) # 统计每种属性画像的人数分布 apply(profile, 1, paste, collapse ) | table() | sort(decreasing TRUE)attribute 字段的行对应被试列对应属性取值 0 或 1。第二段代码把每一行的画像拼成 A1A2A3A4 这样的字符串再计数能快速看到样本里最多的掌握类型是哪些。比如结果里「1111」占了 320 人「0000」只有 15 人说明这批被试整体掌握情况较好。不过要注意MAP 只是按后验概率取最大值它不告诉你这个最大值有多可靠。一个被试在两个属性模式上的后验概率分别是 0.49 和 0.48MAP 会硬把他分到前者但实际他对自己的状态几乎不确定。更稳妥的做法是同时看 posterior 字段里「第二大概率」有多大。如果最大和第二大的差距小于 0.1这类被试的画像就属于边界个案出诊断报告时应降低结论强度或者在报告中标注「状态存疑」。4.3 参数调整迭代上限、随机种子、合法模式约束第一次跑完如果结果看起来不对劲最常见的原因是 EM 算法没有收敛或者收敛到了局部极值。这时要检查的首先是 maxit 是否足够。默认值在某些版本里偏保守数据复杂时容易提前停止。我一般把 maxit 设为 500并且把 progress 参数打开观察每一轮的对数似然是否还在明显下降res - CDM::din(dat Y, q.matrix Q, maxit 500, progress TRUE)progress TRUE 会在控制台实时打印迭代过程的似然值。如果最后一轮似然相比前一轮的变化还超过 conv.crit 的数量级说明迭代不够把 maxit 往上加到 1000 再跑。另一个隐蔽问题是随机种子。EM 算法如果初始化方式带随机性不同种子可能给出略微不同的结果。但 CDM 包本身默认初始化较稳定真正需要关心的是你自己在模拟数据环节的种子设置保证复现一致。参数调整里还有一个容易被忽略的入口前一章提到的 skillclasses 合法模式约束。真实数据中属性之间存在先决关系时把合法模式集合传进去模型的自由参数会减少小样本下估计更稳健。需要提醒的是加约束后不能直接和未加约束的模型比对数似然因为两个模型的复杂度不同要比较信息准则或做似然比检验而不是看谁似然更大。5. DINA落地排查清单本地复现最容易翻车的五个环节5.1 报错「列名不匹配」dat 与 Q 矩阵的行列名核对现象运行 din() 时报错提示找不到某个题目 ID或者提示数据列名与 Q 矩阵行名不一致。原因几乎都是同一类读入 CSV 时没有指定 row.names或者原始表里题目 ID 列被当作普通数据列读进来了。这种情况下 dat 的列名可能是 X1、X2 这类自动生成的编号而 Q 矩阵的行名是 I1、I2两者对不上。解决方法是回到读取步骤统一 IDdat - read.csv(answer.csv, row.names 1, check.names FALSE) Q - read.csv(qmatrix.csv, row.names 1, check.names FALSE) # 命名不一致时先统一顺序 common_id - intersect(colnames(dat), rownames(Q)) dat - dat[, common_id] Q - Q[common_id, , drop FALSE]check.names FALSE 的作用是防止 R 把 I1 这类列名自动改成带前缀的合法变量名。统一顺序那两行是为了兼容「数据列更多」或「Q 矩阵行更多」的情况保证两组题目完全对齐。5.2 Q矩阵标定依赖主观判断同一道题不同人标出不同结果现象同一个数据集换个标定者重新写一份 Q 矩阵估计出的被试掌握比例差很多。原因在于 Q 矩阵本来就是专家判断的结果同一道题到底是「只测 A1」还是「测 A1 和 A3」不同教研人员经常有分歧而 DINA 对 Q 矩阵错误非常敏感一个属性标错会连带影响所有涉及该属性的题目和被试。这也是认知诊断领域把 Q 矩阵修正单独做成一个研究方向的原因。解决思路是把 Q 矩阵当作可迭代的对象而不是一次性定稿。常见做法是让两位教研人员独立标定对不一致的题目逐个讨论对于拿不准的题目分别用两版 Q 矩阵跑模型比较 AIC/BIC再看估计出的 g/s 是否合理。如果某道题在某一版 Q 矩阵下 g 或 s 特别大往往说明这版标定有问题。这步虽然费时间但值得做因为 Q 矩阵错了后面的报告再精美都是错的。5.3 小样本下参数漂移规律与缓解策略现象被试人数只有 100 左右时估计出的 g/s 忽高忽低换一组被试结果差异很大属性画像也不稳定。原因很直接DINA 虽然参数少但每个被试贡献的信息量有限尤其是那些只有单属性题覆盖的属性样本量不足时后验分布尖锐不起来。这属于模型信息量问题不是代码 bug。缓解策略按优先级排序首先增加样本量N 低于 200 的 DINA 结果只能当探索性参考其次考虑减少属性数量把标定过细的属性合并比如「公式记忆」和「概念理解」如果高度相关合并成一个属性能显著降低模型复杂度最后可以改用带先验的贝叶斯估计思路给 g/s 加 Beta 先验把参数拉回合理区间。实际项目中我见过不少团队用 Q 矩阵 300 个被试的数据强行跑 DINA 出了报告里面的画像可信度很低。遇到样本量不足宁可用规则法直接按题目得分率给用户做粗粒度提示也比给一个看似精确实则漂移的画像好。5.4 把DINA当万能模型AND门假设的适用边界现象模型拟合指标还行但部分被试的画像明显不符合常理——比如一个学生被标成「未掌握 A2 公式记忆」可是他在只考 A2 的题目上全部答对。这时候往往不是估计错了而是模型假设和题目机制不一致如果那道题实际上只要会一点 A2 就能做或者可以用 A3 的方法替代DINA 的「缺一不可」就不成立。这类问题的根子不在统计而在题目设计。DINA 的 AND 门假设意味着每道题的所有属性缺一不可且属性内部没有部分掌握。如果实际题目中存在「方法替代」「部分给分」「渐进式推理」那用 DINO 或 G-DINA 更合理。判断方法也很简单把每道题的 g 和 s 估计出来如果某题 g 特别高可能意味着「没有掌握全部属性也能做对一部分」也就是 AND 门被违反了。解决路径是重新审视题目或者换模型族而不是硬调参数。5.5 版本差异与换包风险CDM 与 GDINA 对象结构不同现象网上两份教程一份用 CDM 包一份用 GDINA 包代码看着差不多混着用就报错比如取不到某个字段或者 anova 方法失效。原因在于这两个包虽然都做认知诊断但输出对象的类结构完全不同CDM 的 din() 返回对象和 GDINA 包的 GDINA() 返回对象不是同一套接口。GDINA 包功能更新快支持更多变体模型但对 DINA 的输出字段命名方式与 CDM 不一致。我的习惯是一个项目只选一个包不要混合调用。做标准 DINA 且需要 G-DINA 对比时首选 CDM 包因为它用一套函数覆盖多个模型需要用到 GDINA 包独有的自定义模型或更新算法时就全程用 GDINA。切换包时先运行 names() 或 str() 查看对象结构再写提取字段的代码。两个包导出的同名函数存在冲突时显式用 包名::函数名 的方式调用避免后加载的包屏蔽前一个包。6. 模型验证不要只看拟合指标DINA结果可靠性的三条实用检查6.1 一把尺子gs 越接近 0.3 越要警惕题目质量模型估计完成后我做的第一件事不是看被试画像而是拿一张纸列出每道题的 g 和 s算它们的和。这是一个非常有信息量的单一指标g s 接近 0.5意味着答对概率几乎与是否掌握无关题目严重失效g s 在 0.3 附近这道题基本可以判定有问题。用法很简单直接在 R 里算item - res$item item$gs - item$guess item$slip print(item[order(item$gs, decreasing TRUE), ])如果发现某题 gs 超过 0.4优先检查这道题的 Q 矩阵标定是否合理其次考虑题目本身是否存在歧义。这个步骤不需要任何额外工具却能把「模型整体拟合不错」背后的单题问题挖出来。6.2 一边看拟合一边看实际效标可落地的验证流程模型选择上可以把 DINA 和 G-DINA 同时拟合用 anova 做似然比检验DINA 是 G-DINA 的约束版本嵌套关系成立res_dina - CDM::din(dat Y, q.matrix Q) res_gdina - CDM::gdina(dat Y, q.matrix Q) anova(res_dina, res_gdina)输出结果里 p 值显著说明 G-DINA 更贴合数据p 值不显著说明简化成 DINA 不损失太多解释力优先用 DINA。拟合指标之外必须做实际效标验证把模型输出的画像与任课教师对学生的判断做对比选一批边界个案交给教研组复核。如果模型说某个学生「未掌握 A2」但多位教师一致认为他掌握得不错那大概率不是模型的问题而是 Q 矩阵对这个属性的定义和教师认知不一致。6.3 下一步的两个方向CD-CAT与动态诊断如果 DINA 全家桶已经跑通下一步值得投入的方向一是 CD-CAT认知诊断自适应测验根据已估计的属性状态动态选题只测还不确定的属性能在更短题量下得到同等精度的画像二是动态认知诊断把多次测评串起来用马尔可夫结构建模知识状态的转移回答「学生从 A 状态进步到 B 状态的概率是多少」这类时序问题。两个方向都建立在 DINA 这套基础认知上学过的 Q 矩阵、参数估计和后验推断全用得上。做这类模型这几年我最大的教训是模型跑出数字只是开始数字背后那道题的 Q 矩阵标定、样本量和题目机制才是决定结果可信度的根本因素。先怀疑数据再怀疑模型最后才是调参数磨刀永远比砍柴重要。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑