[译]基于模型的机器学习 - 2.4 迁移到真实数据
既然我们已经在示例数据上充分试验过模型,现在就可以用一些真实数据来工作了。我们请了 22 位志愿者完成一份由 48 道题组成的测评测试,用以评估七种不同的开发技能。许多题目需要两项技能,因为它们既需要某个软件开发概念的知识(例如面向对象编程),又需要该题所用编程语言的知识(例如 C#)。
除了完成测试之外,我们还请每位志愿者说明他们认为自己具备哪些开发技能。这些自评技能将作为技能变量的真实标注(ground truth)——也就是说,我们把它们当作变量的真实取值。这类真实标注数据将用于评估我们的系统从志愿者答案中自动推断技能的准确性。真实标注数据应当相当可靠,因为志愿者没有夸大自己技能的动机:结果是匿名的,所报告的技能和答案无法与任何特定志愿者关联。然而,某些志愿者也有可能高估或低估自己的技能,我们在用这些数据评估准确性时需要牢记这一点。
我们收集到的原始数据如表 2.6 所示。
表 2.6:从志愿者完成一份真实测评测试所收集的原始数据。该数据包含自评技能(S1–S7)以及对每道题的答案(Q1–Q48)。数据的第一行给出每道题的正确答案。随后每一行给出其中一位参与者的数据。
在这个机器学习应用中,我们需要系统能够处理提供给它的任何测试,而不必为每份新测试收集新的真实标注数据。这意味着我们在模型中做推断时不能使用真实标注数据,因为在实践中我们不会有这类数据。不使用真实标注数据的学习称为无监督学习。不过,在开发系统时我们仍然需要真实标注数据,因为我们需要评估系统工作得如何。我们将在这份特定的测试上评估它,并假设它随后在新的、未见过的测试上会以相似的准确度工作。
可视化数据
在处理一份新数据集时,花时间通过各种方式对数据进行可视化观察是至关重要的(关于为什么这如此重要,见专栏 2.3)。那么,现在让我们来为测试答案制作一个可视化。
专栏 2.3:可视化的重要性
机器学习算法在代码出错时往往不会失败,而是悄无声息地继续运行、给出不准确的结果。对数据、推断过程以及结果进行可视化,提供了一种检测和理解这类错误的非常有效的方法。
可视化之所以重要,还因为:
- 它让你发现数据中的问题,例如数据录入错误、缺失数据、错误标注的数据、以错误格式保存的数据,或被错误加载的数据。
- 它让你看到数据中的模式,甚至在创建任何模型或进行任何推断计算之前。精心设计的可视化能够揭示有用的模式,就像精心设计的模型能揭示模式一样。
- 它让你把工作成果传达给他人,帮助说服他们相信你的系统运行良好,或者证明它正在从数据中提取有用的信息。
与其问“我需要可视化这些数据吗?”,不如换个更好的问题:“我承担得起不可视化这些数据的后果吗?”。任何时候,只要你选择不去可视化某些数据、推断过程的某个部分或某些结果,你就有(很高的)几率会遗漏某个重要的东西。一条好的经验法则是:至少值得花 20% 的时间来制作可视化。
照片(和饼干)由 Sarah Supp 提供,2018 年 12 月。在可视化数据时富有创意是件好事。
一个好的可视化的关键要素是:(i) 它忠实地表示了底层数据,(ii) 它把数据的至少一个方面表现得非常清楚,(iii) 它能独立成立(不需要任何解释性文字),以及 (iv) 在此之外它尽可能简单。关于这个主题有整本整本的书(例如 Tufte [1986]),也有一些有用的网站(它们一直在变——请用你的搜索引擎!)和商业可视化软件(例如 Tableau)。此外,大多数编程语言都有可用的可视化和图表库,尤其是那些专注于数据科学的语言,如 R、Python 和 Matlab。在本书中,我们希望通过示例——即阐释每个案例研究的各幅图——来说明什么样的可视化才是好的。例如,在表 2.4 中,除了数字之外还用条形来表示概率,这使得更容易看出哪些题答对了与推断出的技能概率之间的关系。
我们想要可视化的是:每个人对每道题答对还是答错,以及该题所需的技能(由出题人提供)。对于所需技能,我们可以用一个网格,其中白色方块表示需要该技能,黑色方块表示不需要(图 2.16a)。类似地,对于答案,我们可以用另一个网格,其中白色表示答对、黑色表示答错(图 2.16b)。为了更容易发现技能与答案之间的关系,我们可以把两个网格对齐,得到图 2.16 的可视化。
(a) 各题所需技能
(b) 答题情况
图 2.16:答题数据以及每道题所需技能的可视化。(a) 每一行对应一项技能,每一列对应一道题。白色方块显示每道题需要哪些技能。(b) 每一行对应一个人,每一列同样对应一道题。这里白色方块显示每个人答对了哪些题。
这个可视化已经告诉了我们许多关于数据的信息:它让我们看出哪些题容易(列几乎全白)、哪些题难(列几乎全黑)。类似地,它让我们识别出表现好或差的个体,并让我们对人与人之间的差异有一个直观感受。最有用的是,它向我们展示了人们常常成串地答错题。在我们的测试中,连续的题目通常需要相似的技能,因此一串答错的题可以用缺乏相应技能来解释。这些成串的错题令人安心,因为如果数据遵循我们模型的假设,这正是我们所期望看到的那种模式。
这个可视化的一个困难在于,我们必须在两个网格之间来回查看,才能发现某道题的答案与该题所需技能之间的关系。例如,要识别某个特定的人答错的那些题所需的技能集合,并不特别容易。为了解决这个问题,我们可以尝试创建一个同时包含两个网格信息的可视化。一种做法是为每项技能关联一种颜色,并相应地给答错的题着色,如图 2.17 所示:
图 2.17:与图 2.16 相同数据的可视化,但只用一个着色网格,以便更容易看出答错的题与技能之间的关联。
这个可视化使得更容易发现与同一技能相关的错题模式,而无需在两个网格之间不断切换视线。我们本也可以选择高亮答对的题,但在这个情形下聚焦于答错的题更有用,因为它们更罕见,因而更有意思。例如,我们可以看到,那些答错了一些橙色(面向对象编程)题目的人,往往也答错了许多其它橙色题目,因为橙色网格单元常常成块出现。这强烈暗示了缺乏某种底层技能,从而影响了所有这些题目的答案。相反,对于青色(桌面应用)题目,块状结构似乎较少,这表明在这种情况下,“存在一项技能影响所有这些题目”的假设更弱。
面向整份测试的因子图
在确信数据看起来合理之后,我们现在想在这份测评测试的因子图上运行推断。我们已经见过三题(图 2.5)和四题(图 2.14)的因子图,那时只建模了两项技能。但如果我们试图为全部 48 道题画一张因子图,它会非常庞大,也并不特别有用。为了避免这种过大的因子图,我们可以用一个板(plate)来表示图中重复的结构。下面是一个用板来表示五个技能变量先验的例子:
图 2.18:用板来表示因子图中的重复结构。
左边带板的因子图等价于右边不带板的因子图。板画成一个矩形,其重复次数标在右下角——在这个例子中是 5。包含在板内的变量节点和因子节点被视为被复制了 5 次。当一个变量在板内被复制时,它就变成一个长度为 5 的变量数组——所以在这个例子中,skill 是一个数组,其元素为 $skill[0]$、$skill[1]$、$skill[2]$、$skill[3]$ 和 $skill[4]$。注意,我们用下标 0 来指代数组的第一个元素。
图 2.19:面向整份测试的因子图,使用板和 Subarray 因子构建。
图 2.19 展示了我们如何用板为整份测试画出一张紧凑的因子图。图中有两个板,一个横跨技能,一个横跨题目。我们没有为重复次数填入实际数字,而是用了名为 skills 和 questions 的变量。这给了我们一张可针对任意数量技能和任意数量题目进行配置的因子图,因此可用于任何测试。对于我们这份特定的测试,我们将把 skills 设为 7,把 questions 设为 48。
图 2.19 还引入了 Subarray 因子,它连接了两个新变量 skillsNeeded 和 relevantSkills,二者都是 questions 板内的数组。skillsNeeded 数组必须被提供(由灰色阴影表示),它包含每道题需要哪些技能的信息。skillsNeeded 的每个元素本身是一个小的整数数组,指定了该题所需技能的下标——因此,对于一道需要第一项和第三项技能的题,它将是 $[0, 2]$。Subarray 因子利用这个信息,从 skill 数组中抽出相关的子数组,放入 relevantSkills 数组的对应元素中。继续我们的例子,这就意味着 relevantSkills 的那个元素将包含子数组 $[skill[0], skill[2]]$。从这一点往后,因子图就和之前一样了:hasSkills 是 relevantSkills 各元素的 AND,而 isCorrect 则是 hasSkills 的带噪版本。
我们的第一批结果
我们现在准备好在真实数据集上得到第一批结果了。走到这一步花了不少时间,因为我们花时间在小例子上试验了模型、并对数据做了可视化。但正是通过做这些工作,我们才能有信心,从一开始我们的推断结果就是有意义的。
我们可以对每个人分别把循环置信传播应用到图 2.19 的因子图上,把 isCorrect 设为该人的答案。对每项技能,这将给出这个人具备该技能的概率。对每个人重复这一过程,得到一个结果矩阵,展示在图 2.20 左侧的可视化中,其中行对应不同的人,列对应不同的技能。为便于比较,我们在图右侧包含了这些人的自评技能。
(a) 推断出的技能
(b) 自评技能
图 2.20:把我们的模型应用到真实测评数据的初步结果。(a) 计算出的每个人具备每项技能的概率,其中白色对应概率 1.0,黑色对应概率 0.0,灰色深浅表示介于中间的概率值。(b) 作为真实标注的自评技能,白色表示此人评估自己具备该技能,黑色表示不具备。不幸的是,推断出的技能与自评技能几乎没有相似之处。
这些推断结果显然有很大问题!推断出的技能与自评技能几乎没有相似之处。有少数几个人的推断技能看起来还算合理——比如第 3 行和第 6 行的人。然而,对于大多数人,系统推断出他们几乎具备所有技能,无论他们实际是否具备。在我们做了这么多细致的测试和准备之后,怎么会出现这种情况?
事实上,机器学习系统第一次被应用到真实数据上时,结果不如预期是非常常见的。真正的挑战在于找出哪里出了问题并把它修好。
本页引入概念回顾
真实标注(ground truth):一个数据集,其中包含我们想要预测或推断的变量的取值,用于评估模型的预测准确性,和/或用于训练模型。真实标注数据通常收集起来昂贵或困难,因此在大多数机器学习项目中是一种宝贵而稀缺的资源。
无监督学习(unsupervised learning):一种不使用带标注(真实标注)数据、而是旨在自动地、无需人工指导地从无标注数据中发现模式的学习。
可视化(visualisation):对某些数据或推断结果的图形化表示,它让模式或问题得以被检测、理解、传达和据以行动。可视化是机器学习中非常重要的一部分,正如专栏 2.3 所讨论的。
板(plate):因子图中的一个容器,它紧凑地表示所含节点和边的若干次重复。板画成一个矩形,在右下角标注重复次数。例如,见图 2.18。
变量数组(variable array):变量的有序集合,其中每个变量由其在该顺序中的位置(从零开始)来标识。例如,一个名为 skill、长度为 5 的变量数组将包含五个变量:$skill[0]$、$skill[1]$、$skill[2]$、$skill[3]$ 和 $skill[4]$。
自我评估 2.4
以下练习将帮助你巩固本节所学的概念。在做题时,回顾正文或上面的概念小结可能会有所帮助。
- 为表 2.6 的数据集创建一个替代的可视化,展示哪些人答对的题最多、哪些题被最多人答对。例如,你可以对图 2.16 或图 2.17 的行和列进行排序。你的新可视化展示了本节所用可视化中未能明显呈现的什么信息?注:可以用在线版本表格旁的按钮,以 Excel 或 CSV 形式下载该数据集。
- 用 Infer.NET [Minka et al., 2014] 实现图 2.19 中带板的因子图。你需要用到变量数组、ForEach 循环以及 Subarray 因子。把你的因子图应用到该数据集,并验证你得到图 2.20a 中所示的结果。
参考文献
[Tufte, 1986] Tufte, E. R. (1986). The Visual Display of Quantitative Information. Graphics Press, Cheshire, CT, USA.
[Minka et al., 2014] Minka, T., Winn, J., Guiver, J., Webster, S., Zaykov, Y., Yangel, B., Spengler, A., and Bronskill, J. (2014). Infer.NET 2.6. Microsoft Research Cambridge. http://research.microsoft.com/infernet.
下一节:诊断问题
- 本文作者:BeanHsiang
- 本文链接:https://beanhsiang.github.io/post/2026-06-26-mbml-learning-skills_moving_to_real_data/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. 进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。