文章

自适应词汇量测试算法

自适应词汇量测试算法

1. 自适应测试的核心思想

传统的词汇量测试通常采用全量覆盖或固定抽样的方式。若要评估测试者的词汇量,最直接但效率最低的方法是测试大词表中的每一个单词。这种方法在实际工程中并不可行。

自适应测试(Computerized Adaptive Testing, CAT)的核心思想是:只向测试者呈现当前阶段最具有信息量的题目。

1.1 传统测试的局限性

若测试者的词汇水平较高(例如熟知 weaveunveilfragile 等词),则继续测试 appledogschool 等高频词的实际意义不大,因为这些题目无法提供关于其真实能力的区分信息。

反之,若测试者在基础词汇上已经出现较高的错误率,则直接测试 photosynthesisjurisdictionmetamorphosis 等极低频学术词汇,也难以获得有效的评估数据,因为其结果大概率只能证明测试者不会这些词。

1.2 信息量最大化原则

有效的测试应当动态调整难度,使其贴近测试者当前的实际水平。在心理测量学中,当题目的难度刚好对应测试者答对概率约为 50% 时,该题能提供最大的信息量。

通过引入这种动态反馈机制,测试系统可以在仅使用数十道经过精细筛选的题目后,较为准确地估计测试者的整体词汇量,从而避免了几千次的冗余测试。


2. 词频尺度与能力指标

在自适应词汇测试系统中,需要建立合理的度量衡来连接“词汇难度”、“测试者能力”与“词汇量大小”。

2.1 Zipf 词频尺度

Zipf 值是一种对数词频刻度,用于衡量一个词在语料库中的常见程度。其数学定义为:

\[\text{Zipf} = \log_{10}(\text{每十亿词中的出现次数})\]

Zipf 值每下降 1,意味着词频大约下降 10 倍。以下为常见的词频水平对照:

Zipf 值词频水平代表单词难度级别
6 左右极高频the, be, have极简单
5 左右高频decide, improve, describe常见
4 左右中频fragile, deceive, abstract中等
3 左右低频weave, unveil, forestry较难
2 以下极低频学术词、专业词、生僻词很难

2.2 测试能力值($\theta$)

能力值 $\theta$(Theta)是项目反应理论(IRT)中用于表示测试者潜在能力的数值。在词汇测试中,$\theta$ 越高,代表测试者的词汇能力越强,能够掌握更低频(Zipf 值更低)的词汇。

2.3 标准误(Standard Error, SE)

标准误 $\text{SE}$ 表示当前对测试者能力估计的不确定程度。随着答题数量的增加,系统收集到的信息量增多,$\text{SE}$ 会逐步减小,评估结果趋于稳定。

SE 范围评估结果解释
$\ge 0.8$极不稳定,无法用于参考
$0.5 \sim 0.8$粗略估计
$0.4 \sim 0.5$具有一定的参考价值,但波动风险仍存
$0.3 \sim 0.4$较为稳定
$< 0.3$非常稳定

2.4 词汇量估计(Vocab Size)

最终呈现给测试者的词汇量(如 11,700)并不是直接测得的,而是通过估计出的 $\theta$ 值映射至对应的 Zipf 阈值,并在一个按词频排序的大词表中统计出所有高于(或等于)该阈值的词汇数量得到的。


3. 项目反应理论与 Rasch 模型

3.1 什么是项目反应理论(IRT)?

项目反应理论(Item Response Theory, IRT)是现代心理测量学的核心理论,用以探索测试者的潜在特质能力($\theta$)与题目特征(难度、区分度等)对作答反应概率的影响。

在自适应词汇测试中:

  • 主体:测试者(能力值为 $\theta$)。
  • 客体:单词选择题(难度为 $b$)。
  • 目标:估计测试者答对某道题的条件概率。

3.2 经典 Rasch 模型

Rasch 模型是一参数逻辑模型(1PL),它只考虑一个题目特征参数——难度 $b$。该模型假设所有题目具有相同的区分度,且不存在猜测影响。

其数学公式为:

\[P(\text{correct} \mid \theta, b) = \frac{1}{1 + e^{-(\theta - b)}}\]

也可以简写为 Sigmoid 函数的形式:

\[P(\text{correct}) = \sigma(\theta - b)\]

其中:

\[\sigma(x) = \frac{1}{1 + e^{-x}}\]

3.3 Sigmoid 函数用于能力建模的性质

Sigmoid 函数的数学特性与实际答题表现高度契合:

  1. 有界性:输出值恒在 $(0, 1)$ 区间内,符合概率定义。
  2. 当能力远高于难度时($\theta \gg b$): \(\theta - b \to +\infty \implies P(\text{correct}) \to 1\) 表示题目对测试者过于简单,答对概率趋近于 1。
  3. 当能力远低于难度时($\theta \ll b$): \(\theta - b \to -\infty \implies P(\text{correct}) \to 0\) 表示题目对测试者过于困难,答对概率趋近于 0(在未引入猜测项的前提下)。
  4. 当能力等于难度时($\theta = b$): \(\theta - b = 0 \implies P(\text{correct}) = \sigma(0) = 0.5\) 表示测试者恰有 50% 的概率答对该题。

4. 最大似然估计与参数更新

在测试过程中,系统需要基于测试者已完成的 $n$ 道题的作答表现,逆向求解出最合理的 $\theta$ 值。

这一过程通常通过最大似然估计(Maximum Likelihood Estimation, MLE)结合牛顿-拉夫森迭代法(Newton-Raphson Method)来实现。

4.1 似然函数的构建

设测试者已回答 $n$ 道题。

  • 第 $i$ 道题的难度为 $b_i$。
  • 作答结果记为 $u_i$,其中 $u_i = 1$ 表示答对,$u_i = 0$ 表示答错。
  • 模型预测答对概率为 $p_i = \sigma(\theta - b_i)$。

对于单道题,观测到作答结果 $u_i$ 的概率(概率质量函数)可以统一写为:

\[P(U_i = u_i \mid \theta) = p_i^{u_i} (1 - p_i)^{1 - u_i}\]

假设各项作答之间在局部独立,则 $n$ 道题的联合概率即为似然函数 $L(\theta)$

\[L(\theta) = \prod_{i=1}^{n} p_i^{u_i} (1 - p_i)^{1 - u_i}\]

最大似然估计的目标,即是寻找一个 $\hat{\theta}$ 使得 $L(\theta)$ 最大化:

\[\hat{\theta} = \arg\max_{\theta} L(\theta)\]

4.2 对数似然函数

为了避免连乘计算带来的数值下溢问题,通常对似然函数取自然对数,得到对数似然函数 $\ell(\theta)$

\[\ell(\theta) = \ln L(\theta) = \sum_{i=1}^{n} \left[ u_i \ln(p_i) + (1 - u_i) \ln(1 - p_i) \right]\]

4.3 一阶导数(梯度)的推导

我们需要对 $\ell(\theta)$ 求关于 $\theta$ 的一阶偏导数。

首先,根据 Sigmoid 函数的导数性质:

\[\frac{d p_i}{d \theta} = p_i(1 - p_i)\]

将此性质代入对数似然函数求导:

\[\frac{d}{d \theta} [u_i \ln(p_i)] = \frac{u_i}{p_i} \cdot p_i(1 - p_i) = u_i(1 - p_i)\] \[\frac{d}{d \theta} [(1 - u_i) \ln(1 - p_i)] = \frac{1 - u_i}{1 - p_i} \cdot (-p_i(1 - p_i)) = -(1 - u_i)p_i\]

两项相加,得单项导数:

\[u_i(1 - p_i) - (1 - u_i)p_i = u_i - u_i p_i - p_i + u_i p_i = u_i - p_i\]

因此,对数似然函数的一阶导数(梯度 $g$)为:

\[g(\theta) = \frac{d\ell}{d\theta} = \sum_{i=1}^{n} (u_i - p_i)\]

梯度的直观物理意义

  • $\sum u_i$ 是测试者实际答对的题数。
  • $\sum p_i$ 是模型基于当前能力值预测的期望答对题数。
  • 若 $\sum u_i > \sum p_i$,说明测试者的实际表现优于模型预期,一阶导数为正,$\theta$ 应该往调大的方向更新。
  • 若 $\sum u_i < \sum p_i$,说明测试者实际表现逊于预期,一阶导数为负值,$\theta$ 应该往调小的方向更新。

4.4 二阶导数与 Fisher 信息量

对一阶导数继续关于 $\theta$ 求导:

\[\frac{d^2\ell}{d\theta^2} = \frac{d}{d\theta} \sum_{i=1}^{n} (u_i - p_i) = -\sum_{i=1}^{n} \frac{d p_i}{d \theta} = -\sum_{i=1}^{n} p_i(1 - p_i)\]

由于 $p_i \in (0,1)$,二阶导数恒为负值,说明对数似然函数是严格凹函数,存在全局最大值。

在心理测量学中,Fisher 信息量 $I(\theta)$ 定义为对数似然函数二阶导数负值的期望。在此处,其形式为:

\[I(\theta) = \sum_{i=1}^{n} p_i(1 - p_i)\]

4.5 标准误(SE)的计算

估计的渐近标准误(Standard Error)可通过 Fisher 信息量直接计算:

\[\text{SE}(\theta) = \frac{1}{\sqrt{I(\theta)}} = \frac{1}{\sqrt{\sum_{i=1}^{n} p_i(1 - p_i)}}\]

信息量与不确定性的直观联系

单道题目的信息量为 $I_i(\theta) = p_i(1 - p_i)$。

  • 当 $p_i = 0.5$(测试者刚好有半数把握答对该题)时,单题信息量达到最大值 $0.5 \times 0.5 = 0.25$。
  • 当 $p_i \to 1$ 或 $p_i \to 0$ 时,单题信息量趋近于 $0$。

这从数学上证明了:难度与测试者当前能力匹配度极高的题目,能提供最高的信息量,从而使标准误最快下降。


5. 算法:自适应选题、更新与换算

自适应词汇测试在运行期间是一个闭环控制系统:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
                    [ 1. 抽选具有最大信息量的题目 ]
                                   │
                                   ▼
                    [ 2. 呈现题目并接收作答反应 ]
                                   │
                                   ▼
                    [ 3. 采用牛顿迭代法更新能力值 ]
                                   │
                                   ▼
                    [ 4. 判定是否满足终止测试条件 ]
                        /                 \
                     (否)                 (是)
                      /                     \
                     ▼                       ▼
            [ 返回步骤 1 ]            [ 进行词汇量换算 ]

5.1 选题策略:最大信息量选题

当估计出当前能力值为 $\theta$ 后,系统需要从未作答的候选题库中选择下一道题。对于每一道候选题目 $j$,计算其在当前 $\theta$ 处的 Fisher 信息量:

\[\text{nextItem} = \arg\max_{j \in \text{Candidates}} p_j(1 - p_j)\]

在 Rasch 模型中,因为 $p_j = \sigma(\theta - b_j)$,其最大信息量直接对应于题目难度 $b_j$ 与当前能力值 $\theta$ 的接近程度。因此,选题逻辑可退化为:选择难度 $b$ 与当前 $\theta$ 差值绝对值最小的题目。

5.2 能力估计更新:牛顿迭代法

每增加一个新的作答反应,系统通过牛顿-拉夫森法进行迭代更新。更新公式如下:

\[\theta^{(k+1)} = \theta^{(k)} - \frac{g(\theta^{(k)})}{H(\theta^{(k)})} = \theta^{(k)} + \frac{\sum (u_i - p_i)}{\sum p_i(1 - p_i)}\]

为了保证工程上的数值鲁棒性,通常会对单步的更新量(步长)进行阶段性截断(例如单步调整幅度限制在 $[-1.0, 1.0]$ 区间内),以防止在测试初期因作答数据较少而导致估计值剧烈震荡。

5.3 终止条件设计

为了平衡测试精度与用户体验,系统通常结合多个条件来决定何时结束测试:

  1. 极值约束:已答题数达到设定的上限值(如 $60$ 题)。
  2. 基本信息收集:已答题数达到了设定的下限值(如 $20$ 题)。
  3. 精度约束:当前估计的标准误 $\text{SE}$ 降至目标阈值(如 $0.35$)以下。
  4. 收敛约束:最近数道题更新带来的 $\theta$ 变化量或词汇量估计变动幅度已经极小(如近 $5$ 题变化量小于 $5\%$)。

5.4 能力值向词汇量的映射路径

心理测量学输出的 $\theta$ 值(通常分布在 $[-4.0, 4.0]$ 之间)对最终用户而言不够直观,需要将其转换为词汇量指标。

步骤一:能力值 $\theta$ 到 Zipf 阈值的映射

由于能力值越高,可识别的低频词(Zipf 值较小的词)越多,因此 $\theta$ 与 Zipf 阈值呈负相关。通常可以通过对真实样本测试数据的统计标定,拟合出一条线性对应关系:

\[\text{zipf_threshold} = A - B \times \theta\]

例如经验参数设为 $A = 4.5, B = 0.725$: 若当前 $\theta = 1.806$,则:

\[\text{zipf_threshold} = 4.5 - 0.725 \times 1.806 \approx 3.19\]

步骤二:Zipf 阈值到词汇量的映射

获得 Zipf 阈值后,系统将检索后台的大词表,统计符合以下条件的单词个数:

\[\text{vocab_size} = \text{Count}(\text{words where } \text{Zipf} \ge \text{zipf\_threshold})\]

若大词表中 $\text{Zipf} \ge 3.19$ 的词共有 $11,700$ 个,则最终输出给用户的词汇量估计即为 $11,700$ 词。


6. 模型演进:引入猜测参数与多维考量

虽然经典的 Rasch 模型简洁稳定,但在实际的多选题词汇测试中,测试者即使完全不会也有可能通过随机猜测答对题目。为此,我们需要更复杂的模型设计。

6.1 三参数逻辑斯蒂模型(3PL IRT)

在多选题场景下,更精准的模型是三参数逻辑斯蒂模型(Three-Parameter Logistic Model, 3PL):

\[P(U_i = 1 \mid \theta) = c_i + \frac{1 - c_i}{1 + e^{-a_i(\theta - b_i)}}\]

模型参数定义及其工程现实意义如下:

1. $b_i$:难度参数(Difficulty)

代表题目在能力轴上的位置。在无猜测($c_i = 0$)且区分度 $a_i = 1$ 的情况下,当测试者能力 $\theta = b_i$ 时,其答对概率为 0.5。

2. $a_i$:区分度参数(Discrimination)

代表概率曲线在 $\theta = b_i$ 处的斜率。

  • 高区分度:说明该词能够显著区分出能力在其难度线上下的人。
  • 低区分度:曲线较平缓,说明能力高和能力低的人答对该题的概率差异不大(可能由于题干释义模糊或选项设计不合理导致)。

3. $c_i$:猜测参数(Guessing)

代表极低能力个体随机猜测时答对该题的渐近概率。

  • 对于三选一单选题,理论猜测概率为 $0.33$。
  • 在实际中,由于干扰项的迷惑程度不同或测试者具备部分排除能力,猜测参数通常由实际数据标定,并不一定恰好等于 $1/\text{选项数}$。

7. 工程实践:浏览器端自适应词汇测试系统实现

前文已经从理论层面说明了自适应测试、Rasch 模型、最大似然估计、Fisher 信息量与标准误的关系。本章进一步结合一个可运行的浏览器端原型,说明这些数学概念如何被转化为实际代码。

该系统使用 HTML、CSS 与原生 JavaScript 实现,不依赖后端服务即可完成题目展示、作答记录、能力值更新、标准误计算、词汇量估计和可视化报告生成。它适合作为自适应词汇测试算法的最小可行原型。

7.1 系统整体结构

从工程角度看,整个系统可以拆分为四个核心部分:

  1. 题库数据层 题库以数组 itemBank 的形式存储,每个题目包含英文单词、正确释义、干扰项、Zipf 词频值与难度参数。

  2. 测量算法层 该层负责根据 Rasch 模型计算答对概率、题目信息量、能力值更新与标准误。

  3. 测试流程控制层 该层负责控制开始测试、进入下一题、记录答案、判断是否终止测试以及生成最终报告。

  4. 用户界面层 该层负责展示当前能力值、标准误、Zipf 阈值、估计词汇量、答题进度和能力收敛曲线。

其运行流程可以概括为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
初始化能力值 θ
      ↓
从题库中选择信息量最大的题目
      ↓
展示题目与选项
      ↓
用户作答
      ↓
记录反应并更新 θ
      ↓
计算 SE 与词汇量估计
      ↓
判断是否达到终止条件
      ↓
输出评测报告

7.2 题库设计:从词频到难度参数

在代码中,每个词条采用如下结构:

1
2
3
4
5
6
7
{
  word: "alleviate",
  correct: "减轻",
  options: ["减轻", "加重", "创造", "毁坏"],
  zipf: 3.2,
  difficulty: 1.1
}

其中:

  • word 是测试词。
  • correct 是正确中文释义。
  • options 是四个候选选项。
  • zipf 表示该词的大致词频水平。
  • difficulty 是 Rasch 模型中的题目难度参数 (b)。

需要注意的是,当前代码中的 difficulty 并不是通过真实大规模作答数据标定得到的统计参数,而是根据词频、常识难度和考试等级进行的人工近似。因此它更适合用于算法演示和原型验证,而不是直接作为高精度测评系统的正式标定题库。

7.3 答对概率计算:Rasch 模型的代码化

系统使用如下函数计算 Sigmoid:

1
2
3
4
5
function sigmoid(x) {
  return x >= 0
    ? 1 / (1 + Math.exp(-x))
    : Math.exp(x) / (1 + Math.exp(x));
}

这里采用了分段写法,是为了避免当 (x) 绝对值很大时出现指数溢出。随后,系统通过:

1
2
3
function probabilityCorrect(theta, item) {
  return sigmoid(theta - item.difficulty);
}

实现 Rasch 模型:

\[P(\text{correct} \mid \theta, b) = \frac{1}{1 + e^{-(\theta - b)}}\]

其中:

  • 当 $\theta > b$ 时,测试者能力高于题目难度,答对概率较高。
  • 当 $\theta < b$ 时,测试者能力低于题目难度,答对概率较低。
  • 当 $\theta = b$ 时,答对概率约为 $0.5$,该题最能区分测试者能力。

这一函数是整个系统的概率核心。后续的选题、能力更新和标准误计算都依赖它。

7.4 自适应选题:最大信息量原则

系统通过以下函数选择下一道题:

1
2
3
4
function itemInformation(theta, item) {
  const p = probabilityCorrect(theta, item);
  return p * (1 - p);
}

单题信息量为:

\[I_i(\theta) = p_i(1 - p_i)\]

当 $p_i = 0.5$ 时,信息量达到最大值 $0.25$。这意味着最有价值的题目不是最简单或最难的题目,而是难度最接近当前能力估计值的题目。

选题函数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function selectNextItem() {
  const unused = itemBank.filter(
    (item) => !state.usedWords.has(item.word),
  );
  if (unused.length === 0) return null;

  return unused.reduce((best, item) => {
    const infoCurrent = itemInformation(state.theta, item);
    const infoBest = itemInformation(state.theta, best);

    if (Math.abs(infoCurrent - infoBest) < 0.02)
      return Math.random() > 0.5 ? item : best;

    return infoCurrent > infoBest ? item : best;
  }, unused[0]);
}

该实现有三个关键点:

  1. 只从未作答题目中选题 系统通过 usedWords 避免重复出现同一个单词。

  2. 选择当前信息量最大的题目 对所有候选题计算 (p(1-p)),选择信息量最高者。

  3. 加入微小随机扰动 当多个题目信息量接近时,系统不会机械地选择题库中最靠前的题目,而是加入一定随机性。这可以减少测试路径的僵化,使不同测试者或多次测试之间的题目序列更加自然。


7.5 能力值更新:最大似然估计的工程实现

每次用户作答后,系统都会把当前题目、作答结果和选项状态写入测试状态:

1
state.responses.push({ item, correct, chosen });

随后调用:

1
updateTheta();

能力值更新函数的核心逻辑如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
for (let iter = 0; iter < 10; iter++) {
  let gradient = 0,
      information = 0;

  for (const resp of state.responses) {
    const p = probabilityCorrect(thetaTemp, resp.item);
    gradient += resp.correct - p;
    information += p * (1 - p);
  }

  if (information < 1e-5) break;

  let step = gradient / information;
  step = Math.max(Math.min(step, 1), -1);
  thetaTemp += step;

  if (Math.abs(step) < 1e-4) break;
}

它对应前文推导的牛顿迭代更新式。

代码中还加入了三个重要的工程保护:

第一,极端作答保护

当测试者目前为全对或全错时,传统 MLE 容易出现估计发散。代码中对此进行了单独处理:

1
2
3
4
5
if (score === 0) {
  state.theta = Math.max(-4, state.theta - 0.5);
} else if (score === state.responses.length) {
  state.theta = Math.min(4, state.theta + 0.5);
}

这样做可以避免在测试初期因为样本太少而导致 $\theta$ 一次性跳到极端位置。

第二,步长截断

代码将单次更新步长限制在 $[-1, 1]$:

1
step = Math.max(Math.min(step, 1), -1);

这可以降低数值震荡风险,使能力轨迹更加平滑。

第三,能力边界限制

最终能力值被限制在 $[-4, 4]$:

1
state.theta = Math.max(Math.min(thetaTemp, 4), -4);

这相当于给测量尺度设置了合理边界,防止极少量异常作答把能力估计推向不现实的范围。


7.6 标准误与终止条件

系统通过如下函数计算当前标准误:

1
2
3
4
5
6
7
8
9
10
11
12
function standardError() {
  let information = 0;

  for (const resp of state.responses) {
    const p = probabilityCorrect(state.theta, resp.item);
    information += p * (1 - p);
  }

  return information <= 1e-5
    ? Infinity
    : 1 / Math.sqrt(information);
}

其数学形式为:

$ SE(\theta) = \frac{1} {\sqrt{\sum_i p_i(1-p_i)}} $

随着测试进行,信息量逐步累积,标准误通常会下降。系统的终止条件由 isDone() 控制:

1
2
3
4
5
6
7
8
9
10
11
function isDone() {
  const answered = state.responses.length;
  const se = standardError();

  if (answered >= config.maxQuestions) return true;

  if (answered >= config.minQuestions && se <= config.targetSe)
    return true;

  return false;
}

当前配置为:

1
2
3
4
5
6
const config = {
  minQuestions: 20,
  maxQuestions: 50,
  targetSe: 0.38,
  totalLexiconSize: 50000,
};

因此,测试至少完成 20 题;若 20 题后标准误已经低于 0.38,则可以结束;若一直未达到精度要求,则最多完成 50 题。

这种设计体现了自适应测试中的典型权衡:既不能为了追求精度让测试无限延长,也不能在信息不足时过早输出结果。


7.7 从能力值到词汇量估计

当前系统先将 (\theta) 映射为 Zipf 阈值:

1
2
3
function thetaToZipfThreshold(theta = state.theta) {
  return 4.5 - 0.725 * theta;
}

对应公式为:

$ \text{Zipf Threshold} = 4.5 - 0.725 \theta $

能力越高,(\theta) 越大,对应的 Zipf 阈值越低,表示测试者可以识别更低频的词。

随后,系统使用指数函数估算词汇量:

1
2
3
4
5
6
7
8
9
10
function estimateVocabSize(theta = state.theta) {
  if (theta <= -4) return 500;

  const baseVocab = 6000;
  const growthFactor = 0.366;

  let vocab = baseVocab * Math.exp(growthFactor * theta);

  return Math.round(vocab / 50) * 50;
}

这意味着:

$ \text{Vocab} = 6000 \times e^{0.366\theta} $

在该映射下:

  • $\theta = 0$ 时,估计词汇量约为 6000。
  • $\theta = 2$ 时,估计词汇量约为 12500。
  • $\theta = 4$ 时,估计词汇量约为 26000。

这种映射方式比直接用小题库中 Zipf 阈值以上的题目比例进行外推更平滑,也更适合前端演示。但它本质上仍是经验换算公式,并非真实大词表统计结果。若要用于正式测评,应使用完整词表和真实语料频率进行重新标定。


7.8 结果报告与可视化反馈

测试结束后,系统调用 showReport() 生成报告:

1
2
3
const vocab = estimateVocabSize();
const lowTheta = Math.max(state.theta - 1.96 * se, -4);
const highTheta = Math.min(state.theta + 1.96 * se, 4);

报告不仅输出点估计词汇量,还根据标准误计算 95% 置信区间

此外,系统还使用 Canvas 绘制能力值收敛轨迹:

1
state.history.push(state.theta);

每一次能力值更新都会被记录到 history 中,并绘制为折线图。该图可以直观展示测试初期的快速波动以及后期逐渐收敛的过程。

从用户体验角度看,这种设计有两个好处:

  1. 测试者可以实时看到系统如何根据作答表现调整难度。
  2. 最终报告不只是给出一个孤立数值,而是展示能力估计的稳定程度。

7.9 原型系统的工程价值

该浏览器端实现虽然简化,但已经覆盖了自适应词汇测试的关键闭环:

  • 使用 Rasch 模型计算答对概率。
  • 使用 Fisher 信息量选择题目。
  • 使用最大似然估计更新能力值。
  • 使用标准误判断结果稳定性。
  • 使用经验映射输出词汇量。
  • 使用图表展示能力收敛轨迹。
  • 使用置信区间呈现测量不确定性。

因此,它不仅是一个可交互网页工具,也可以被视为一个自适应测试算法的教学型实现。后续若要演进为正式系统,主要工作不在于重写算法框架,而在于补充真实题库标定、完整词表映射、用户数据存储、反作弊机制和多维能力建模。

warning

本文由作者按照 CC BY 4.0 进行授权