[译]基于模型的机器学习 - 4.6 随邮件到达而学习
到目前为止,我们能够一次性在大量邮件上训练我们的模型。但对我们的应用而言,我们需要能够在用户回复一封新邮件时、或在明确用户不会回复它时,立即从这封邮件中学习。我们不能等到收到大量邮件后,再一次性在它们上面训练、然后永远使用训练好的模型。相反,我们必须随着新邮件的到来持续训练模型,并始终使用最新训练好的模型来做预测。
正如我们在上一章第 3.3 节中看到的,我们可以使用在线学习在收到新训练数据时持续更新我们的模型。在我们的模型中,在线学习很直接:对每一批自上次训练以来到达的邮件,我们把之前对 weight 和 threshold 的后验分布用作训练的先验。一旦对这一批的训练完成,对 weight 和 threshold 的新后验分布就可以用来做预测。之后当训练下一批邮件时,这些后验分布将充当新的先验。我们可以通过把训练数据分成若干批、并在每一批到来时运行在线学习,来检查这个过程工作得如何。然后我们可以把这种方法与离线训练相比较,离线训练一次性呈现到该时间点为止见过的所有训练数据。图 4.20 显示了使用离线训练、或使用不同批量大小的在线训练时,在全部 10 个用户上平均的 AUC 和 AP。
(a) 曲线下面积
(b) 平均精确率
图 4.20:随着越来越多训练邮件变得可用时的预测准确性,在全部 10 个用户上平均。对每个指标,离线曲线显示如果我们在到该时间点为止收到的所有邮件上从头重新训练模型的准确性。另外四条曲线显示如果我们改为在每 1、5、10 或 50 封邮件后做在线训练以增量更新模型的准确性。
这些结果表明,在线学习给出的准确性与离线训练相似,但略低,较大的批量大小通常给出更好的准确性。这些图还显示,随着收到更多邮件,准确性的差异会减小。因此,一旦收到足够的邮件,在线学习似乎可以是一个合适的解法。但这把我们带到另一个问题:大约需要 400 到 500 封邮件,平均精确率才能接近一个稳定值。在达到那个数量之前的一段时间内,特别是当训练过的邮件相对较少时,分类器的准确性很低。这意味着新用户的体验会很差。当然,我们可以等到用户已收到并处理了足够多的邮件,但对某些用户来说这可能需要数周或数月。如果我们能立即给他们一个良好的体验,那会好得多。在还没有任何训练数据的情况下为新用户做出良好预测的挑战,被称为冷启动问题(cold start problem)。
为一个用户社区建模
我们已经展示了可以通过改变特征集来解决某些预测问题。但在这个情况下,没有任何对特征集的改变能帮助我们——在我们至少见过一封邮件之前,我们甚至无法计算特征值!但由于我们有的是一个分类模型而非一个固定的分类算法,我们有一个额外的选项可用:改变模型。
我们如何改变模型来解决冷启动问题呢?我们可以利用不同用户往往会回复相同种类邮件这一事实。例如,用户往往更可能回复他们排在收件人栏第一位、或邮件被转发给他们的邮件。这提示我们可能预期学到的权重在用户之间是相似的,至少对那些捕捉用户共有行为的特征桶而言。然而,也可能有其他特征桶捕捉了用户之间行为的差异,我们可能预期它们学到的权重在用户之间会不同。为考察哪些特征桶在用户之间相似,我们可以为前五个用户绘制他们所共有的所有特征桶(即除 Sender 和 Recipients 特征的桶之外的所有桶)学到的权重。得到的图如图 4.21 所示。
图 4.21:为我们数据集中前五个用户学到的各特征桶权重的高斯分布。对大多数特征桶,学到的权重在用户之间相似,表明他们回复具有相似特征的邮件。
如你所见,对许多特征桶,五个用户的权重都相似,即使对那些用户间变异性较大的桶,权重也倾向于全为正或全为负。但在少数情况下,例如 FromMe 特征,用户之间的变异性更大。这种变异性表明这些特征捕捉了用户之间行为的差异,例如某个特定用户是否给自己发邮件作为提醒。总体而言,用户之间似乎有足够的相似性,我们可以利用这种相似性来为一个全新的用户做预测。为此,我们需要对权重如何在多个用户之间变化做出一个新的建模假设:
这个假设是说,我们可以用一个平均权重(高斯分布的均值)和一个衡量典型用户权重偏离这个平均值多少的度量(高斯分布的标准差)来表示一个权重如何在用户之间变化。
让我们改变模型来加入这个假设。由于我们现在为多个用户建模,我们需要添加一个跨用户的板,并把我们整个既有模型放进它里面。这个新板之外唯一的变量将是每个特征桶的两个新变量:weightMean 捕捉跨用户的平均权重,weightPrecision 捕捉跨用户的精度(逆方差)。然后我们把板内的 Gaussian(0,1) 因子(我们过去用作先验的那个)替换为一个连接到 weightMean 和 weightPrecision 的 Gaussian 因子。得到的因子图如图 4.22 所示。
图 4.22:联合分类多个用户邮件的模型。我们的分类模型通过放进一个 users 板内而对每个用户复制一份。然后我们为每个特征桶引入两个共享变量:weightMean 捕捉该桶跨用户的典型(平均)权重,weightPrecision 捕捉该权重跨用户的变化程度。
你会注意到,我们使用了精度(逆方差)而非方差来捕捉权重跨用户的变异性。一个桶的高 weightPrecision 意味着它的权重在用户之间往往非常相似,而低 weightPrecision 意味着桶权重在用户之间往往变化很大。我们选择使用精度,是因为我们现在试图学习这种变异性,而事实证明用精度而非方差来做这件事要容易得多。这个选择允许我们使用一个伽马分布(gamma distribution)来表示 weightPrecision 变量中的不确定性,无论是在设定其先验分布时,还是在推断其后验分布时。伽马分布是一个对连续正值(即大于零的值)的分布。我们需要使用一个新分布,因为精度只能为正——我们不能使用高斯分布,因为它允许负值;我们也不能使用贝塔分布,因为它只允许 0 到 1 之间的值。伽马分布还有一个优点:它是高斯分布精度的共轭分布,这使得推断更容易。
伽马分布有如下密度函数:
$$\mathit{Gamma}(x ; k,\theta) = \dfrac{x^{k-1}e^{-\frac{x}{\theta}}}{\theta^k \,\mathrm{\Gamma}(k)}$$其中 $\mathrm{\Gamma}()$ 是伽马函数,用于确保密度函数下的面积为 1.0。伽马分布有两个参数:形状参数 $k$ 和尺度参数 $\theta$——具有这些参数不同取值的示例伽马分布如图 4.23a 所示。令人困惑的是,伽马分布有时用形状和尺度的倒数(称为率,rate)来参数化。由于两个版本都很常见,检查正在使用的是哪个很重要——在本书中,我们将始终使用形状和尺度参数。
(a)
(b)
图 4.23:(a) 形状和尺度参数不同取值的示例伽马分布。(b) 我们用作权重精度先验的 Gamma(4, 0.5) 分布。
由于我们的用户相对较少,我们需要在选择 weightPrecision 的伽马先验时小心,因为它会对模型的行为有很大的影响。通常我们预期精度高于 1.0,因为我们预期大多数权重在用户之间相似。然而,我们也需要允许精度对那些在用户之间变化很大的较罕见权重在 1.0 左右。图 4.23b 显示了一个满足这两个要求的 Gamma(4,0.5) 分布。
在我们试用图 4.22 中的模型之前,还有一点要讨论。如果你非常细心,你会注意到 threshold 变量已被固定为零。这是因为我们想使用我们共同的 weightMean 和 weightPrecision 来学习 threshold 如何在用户之间变化,正如学习权重如何变化一样。为此,我们可以使用一个常见的技巧:把 threshold 固定为零,并创建一个对所有邮件始终开启的新特征——这被称为偏置(bias)。这个想法是,对所有邮件把 score 改变一个固定值,等价于把 threshold 改变相同的值。所以我们可以使用偏置特征来有效地设定阈值,同时让实际的 threshold 固定为 0。由于特征权重有一个 Gaussian(0,1) 先验,但 threshold 有一个 Gaussian(0,10) 先验,我们需要把这个新偏置特征的值设为 $\sqrt{10}$,以便让模型保持不变——如果我们有一个不确定性为 Gaussian(0,1) 的变量,并把它乘以 $\sqrt{10}$,我们就得到一个不确定性为 Gaussian(0,10) 的变量,正如所需。
解决冷启动问题
冷启动问题的一个动手解法
我们现在可以在前五个用户(其权重在图 4.21 中被绘制的用户)上训练我们共同的模型。尽管我们已经大幅改变了模型,我们仍然能够使用期望传播来做训练或预测这样的推断任务。所以我们不需要发明一个新算法来对多个用户做联合训练——我们只需在扩展后的模型上运行熟悉的 EP 算法。
图 4.24 显示了学到的社区权重分布:每个条形显示对 weightMean 的后验的均值,误差条显示由 weightPrecision 的均值给出的一个标准差。注意误差条的不同用法——用来显示 weightPrecision(学到的跨用户变异性)而非 weightMean 自身的不确定性。如果你把图 4.24 的分布与图 4.21 的各个用户权重相比较,你可以看到学到的分布如何很好地捕捉了权重跨用户的变异性。
图 4.24:从我们数据集中前五个用户学到的社区权重分布。蓝色条显示 weightMean 的期望值,误差条显示这个值两侧各一个标准差,对应于 weightPrecision 的期望值。与图 4.21 比较表明,学到的权重分布与为每个用户单独学到的权重一致。
为把我们学到的社区权重分布应用于一个新用户,我们可以使用为单个用户配置的同一模型,把对 weightMean 和 weightPrecision 的先验替换为从前五个用户学到的高斯和伽马后验。即使我们还没见过新用户的任何邮件,我们也可以使用这个模型来做预测。但我们也可以使用这个模型在收到新用户邮件时做在线训练。当我们使用社区模型做在线训练时,我们可以从做出可能适用于任何用户的通用预测,平滑地演化为做出特定于新用户的个性化预测。这种演化完全通过在我们的模型中做推断而自动发生——我们无需指定一个从社区预测切换到个性化预测的临时过程。
图 4.25 显示了在社区模型中使用在线训练所做预测的准确性,与个体模型(使用批量大小 5)相比,在不同训练数据量下的情况。对这幅图我们再次在全部十个用户上平均——我们使用一个在后五个用户上训练的单独社区模型来为前五个用户做预测结果。结果非常令人满意——初始准确性很高(平均 AP 为 41.8%),然后它继续平滑上升,直到在训练了 500 封邮件后达到平均 AP 43.2%。正如我们所希望的,我们的社区模型从一开始就做出良好的预测,然后随着模型个性化到具体用户而变得更好。冷启动问题被解决了!
(a) 曲线下面积
(b) 平均精确率
图 4.25:使用个体模型或社区模型时,预测准确性对训练数据量的关系。两种情况下训练都以 5 封邮件为批量在线进行。结果在全部 10 个用户上平均——对前五个用户,预测使用在后五个用户上训练的社区模型,对后五个用户反之亦然。
在 Exchange 使用的生产系统中,我们有多得多的用户可以从中学习社区权重。在这种情况下,对 weightMean 和 weightPrecision 的后验变得非常窄。当这些后验被用作先验时,weightMean 和 weightPrecision 的值实际上是固定的。这允许我们对系统做一个有益的简化:一旦我们使用多用户模型学到了社区权重分布,我们就可以回到单用户模型去做在线训练和预测。我们需要做的只是把单用户模型中的 Gaussian(0,1) 先验替换为一个均值和精度由那些窄的 weightMean 和 weightPrecision 分布的期望值给出的高斯先验。所以,在生产中,多用户模型在大量用户上离线训练一次,然后学到的社区权重分布被用来为每个用户分别做训练和预测。这种分离使部署、管理和调试系统行为更容易,因为每个用户可以被单独考虑。
在我们把系统部署给一些 beta 测试者之前,还有最后一件事要做。还记得我们在本章开头搁在一边的邮件数据测试集吗?现在是时候把它们拿出来,看看我们在测试集上得到的结果是否与我们在验证集上看到的结果相当。验证集和测试集的对比结果如表 4.5 所示。
表 4.5:每个用户和总体的验证集和测试集的最终准确性结果。右侧各列显示每个数据集中被回复的邮件数量,这给出了相应平均精确率指标可靠性的一个指示。
该表显示,用户测试集的 AUC 测量值通常与验证集的相当相似,没有明显偏向其中之一的偏置。这表明在设计我们的模型和特征集时,我们没有对验证数据过拟合。AP 测量值差异更大,特别是对某些用户——这是因为测试集相当小,有些只包含少数被回复的邮件。在这种情况下,AP 测量值变得相当嘈杂和不可靠。然而,即使我们聚焦于那些有更多被回复邮件的用户,测试 AP 似乎也不一致地低于验证 AP。所以两个评估指标都表明测试集和验证集准确性之间没有根本差异,因此我们应当预期为真实用户达到相似的预测准确性。
最终测试与改动
此时,预测系统被部署给 beta 测试者以进行进一步的真实世界测试。问卷被用来获取关于系统对用户工作得如何的反馈。这次测试和反馈凸显了两个额外的问题:
- 随着用户行为的演变,预测似乎随时间变得不那么准确,例如,当他们更换项目或更换团队时,杂物邮件预测似乎变化得不够快以匹配更新后的行为。
- 系统的校准虽然平均而言正确,但对个别用户不正确。预测概率对某些用户太高,对另一些用户太低。
对第一个问题的调查识别出一个与我们在第 3 章中诊断的问题相似的问题。我们假设了模型中的权重对某个特定用户在时间上是固定的。这个假设不允许用户行为改变。解法是改变模型以允许权重随时间改变,正如我们在 TrueSkill 系统中允许技能随时间改变一样。修改后的模型对每个时间段(例如每周一个变量)的每个桶权重都有随机变量。图 4.26a 显示了一个包含两个连续周权重 $\mathit{weight}_{(1)}$ 和 $\mathit{weight}_{(2)}$ 的示例模型片段。为允许权重随时间改变,通过添加方差非常低的高斯噪声,第二周的权重被允许与第一周的权重略有不同。与 TrueSkill 系统一样,这个改动允许系统追踪缓慢变化的用户行为。
(a)
(b)
图 4.26:为修复 beta 测试者发现的问题而对模型所做的修改。(a) 允许权重随时间改变,解决了行为预测不随用户行为改变而演化的问题。(b) 显式地建模意图行为标签与实际行为标签之间的差异,解决了当意图标签与实际标签不匹配时出现的糟糕校准。
第二个问题更难诊断。对该问题的调查发现,过高的预测概率出现在杂物量低的用户身上,而过低的预测概率出现在杂物量高的用户身上。原来问题在于我们在第 4.5 节中遇到的带噪声的真实标签——对杂物量高的用户,很多杂物项被错误地标记为非杂物,对杂物量低的用户则反之。用这些不正确的标签训练,把一个相应的偏置引入了预测的杂物概率。这里的解法是改变模型以显式地表示标签噪声。例如,对于回复预测,我们可以在模型中创建一个新变量 intendedToReply,表示用户是否真正意图回复该消息的真实标签。然后我们把已观测的标签 repliedTo 定义为这个变量的一个带噪声版本,使用一个像我们早在第 2 章中使用的 AddNoise 因子那样的因子。图 4.26b 显示了加入这个改动后修改的模型的相关片段。做出这个改动后,发现校准在所有用户之间都更接近理想,杂物量高或低用户的系统性校准变化消失了。
在处理这些问题的每一个时,我们都需要对模型做出改动,这对于一个黑盒分类算法是不可能的,但却是基于模型的机器学习方法的核心。有了这些模型改动,杂物预测系统现在作为 Office365 的一部分被部署,帮助从人们的收件箱中移除杂物邮件。图 4.27 显示了系统运行中的一个截图,全部使用基于模型的机器学习!
图 4.27:Office 365 中运行中的杂物系统。
本页引入概念回顾
冷启动问题(cold start problem):在几乎没有(或没有)特定于某个新实体(例如一个新用户)的可用训练数据时,为该实体做出良好预测的问题。一般来说,冷启动问题可以出现在任何引入新实体的系统中——例如,在一个推荐系统中,当试图预测某人是否会喜欢一部尚未收到任何评分的新上映电影时,就会出现冷启动问题。
伽马分布(gamma distribution):一个对正连续随机变量的概率分布,其概率密度函数为
$$\mathit{Gamma}(x ; k,\theta) = \dfrac{x^{k-1}e^{-\frac{x}{\theta}}}{\theta^k \,\mathrm{\Gamma}(k)}$$其中 $\mathrm{\Gamma}()$ 是伽马函数,用于确保密度函数下的面积为 1.0。伽马分布有两个参数:形状参数 $k$ 和尺度参数 $\theta$。
下图显示了 $k$ 和 $\theta$ 不同取值的伽马分布:
偏置(bias):一个对所有数据项始终开启的特征。由于偏置特征始终开启,它的权重编码了标签的先验概率。例如,偏置权重可能编码在我们查看某封特定邮件的任何特征之前,用户会回复一封邮件的概率。等价地,使用一个偏置特征允许 threshold 变量被固定为零,因为它不再需要表示先验标签概率。
参考文献
[Bishop, 2006] Bishop, C. M. (2006). Pattern Recognition and Machine Learning. Springer.
下一章:做出推荐
- 本文作者:BeanHsiang
- 本文链接:https://beanhsiang.github.io/post/2026-08-31-mbml-emailclassifier_learning_as_emails_arrive/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. 进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。