Mail.ru Mail 中机器学习的操作

Mail.ru Mail 中机器学习的操作

基于我在 Highload++ 和 DataFest Minsk 2019 上的演讲。

对于今天的许多人来说,邮件是在线生活不可或缺的一部分。 在它的帮助下,我们可以进行商务信函,存储与财务、酒店预订、下订单等相关的各种重要信息。 2018年中,我们制定了邮件开发的产品策略。 现代邮件应该是什么样的?

邮件必须是 聪明的,即帮助用户浏览不断增加的信息:过滤、结构化并以最便捷的方式提供信息。 她一定是 有用,允许您直接在邮箱中解决各种任务,例如支付罚款(不幸的是,我使用了该功能)。 当然,同时,邮件必须提供信息保护,切断垃圾邮件并防止黑客攻击,即 安全.

这些领域定义了许多关键问题,其中许多问题可以使用机器学习有效解决。 以下是作为该战略的一部分开发的现有功能的示例 - 每个方向一个。

  • 智能回复。 邮件具有智能回复功能。 神经网络分析信件的文本,理解其含义和目的,从而提供三种最合适的回应选项:积极、消极和中立。 这有助于显着节省回信时间,而且通常会以非标准且有趣的方式回复。
  • 对电子邮件进行分组与在线商店中的订单相关。 我们经常在网上购物,并且通常商店可以为每个订单发送多封电子邮件。 例如,最大的服务速卖通,一个订单会包含很多字母,我们计算出,在终端情况下,它们的数量最多可达 29 个。因此,使用命名实体识别模型,我们提取订单号以及文本中的其他信息,并将所有字母分组到一个线程中。 我们还在单独的框中显示有关订单的基本信息,这使得使用此类电子邮件变得更加容易。

    Mail.ru Mail 中机器学习的操作

  • 反网络钓鱼。 网络钓鱼是一种特别危险的欺诈性电子邮件类型,攻击者试图利用该电子邮件获取财务信息(包括用户的银行卡)和登录信息。 这些信件模仿了该服务发送的真实信件,包括视觉上的模仿。 因此,在计算机视觉的帮助下,我们可以识别大公司(例如 Mail.ru、Sber、Alfa)的徽标和信件的设计风格,并将其与垃圾邮件和网络钓鱼分类器中的文本和其他特征一起考虑在内。

机器学习

关于电子邮件中的机器学习的一些一般知识。 邮件是一个高负载的系统:平均每天有 1,5 亿封信件通过我们的服务器,为 30 万 DAU 用户提供服务。 大约 30 个机器学习系统支持所有必要的功能和特性。

每个字母都会经过整个分类流程。 首先,我们切断垃圾邮件并留下好的电子邮件。 用户通常不会注意到反垃圾邮件的工作,因为 95-99% 的垃圾邮件甚至没有进入适当的文件夹。 垃圾邮件识别是我们系统中非常重要的部分,也是最困难的部分,因为在反垃圾邮件领域,防御和攻击系统之间不断适应,这为我们的团队提供了持续的工程挑战。

接下来,我们将来自人和机器人的字母分开。 来自人们的电子邮件是最重要的,因此我们为他们提供了智能回复等功能。 机器人发出的信件分为两部分:交易性的——这些是来自服务的重要信件,例如购买或酒店预订、财务的确认,以及信息性的——这些是商业广告、折扣。

我们相信交易电子邮件与个人信件同等重要。 它们应该在手边,因为我们经常需要快速查找有关订单或机票预订的信息,并且我们会花时间搜索这些信件。 因此,为了方便起见,我们自动将其分为六个主要类别:旅行、订单、金融、门票、登记,最后是罚款。

信息信件是最大且可能不太重要的一组,不需要立即回复,因为如果用户不阅读此类信件,其生活不会发生任何重大变化。 在我们的新界面中,我们将它们折叠成两个线程:社交网络和时事通讯,从而在视觉上清理收件箱,只留下重要的消息可见。

Mail.ru Mail 中机器学习的操作

开发

系统数量众多,给操作带来很多困难。 毕竟,模型会随着时间的推移而退化,就像任何软件一样:功能损坏、机器故障、代码变得错误。 此外,数据在不断变化:新数据的添加、用户行为模式的转变等,因此没有适当支持的模型随着时间的推移会变得越来越糟糕。

我们不能忘记,机器学习越深入用户的生活,对生态系统的影响就越大,市场参与者可以获得的经济损失或利润就越大。 因此,在越来越多的领域,玩家正在适应机器学习算法的工作(典型的例子是广告、搜索和已经提到的反垃圾邮件)。

此外,机器学习任务有一个特殊性:系统中的任何(即使是微小的)更改都可能会导致模型产生大量工作:处理数据、重新训练、部署,这可能需要数周或数月的时间。 因此,模型运行的环境变化越快,维护它们所需的精力就越多。 一个团队可以创建很多系统并对此感到高兴,但随后会花费几乎所有资源来维护它们,而没有机会做任何新的事情。 我们在反垃圾邮件团队中曾经遇到过这样的情况。 他们得出了明显的结论:支持需要自动化。

自动化

什么可以自动化? 事实上,几乎一切。 我确定了定义机器学习基础设施的四个领域:

  • 数据采集​​;
  • 附加训练;
  • 部署;
  • 测试和监控。

如果环境不稳定且不断变化,那么模型周围的整个基础设施就会比模型本身重要得多。 它可能是一个很好的老式线性分类器,但如果你为其提供正确的功能并从用户那里获得良好的反馈,它将比具有所有花哨功能的最先进模型工作得更好。

反馈回路

这个周期结合了数据收集、额外的训练和部署——实际上是整个模型更新周期。 它为什么如此重要? 查看邮件中的报名时间表:

Mail.ru Mail 中机器学习的操作

机器学习开发人员实施了一种反机器人模型,可防止机器人在电子邮件中注册。 该图表下降到仅保留真实用户的值。 一切都很好! 但四个小时过去了,机器人调整了脚本,一切恢复正常。 在此实施中,开发人员花了一个月的时间添加功能并重新训练模型,但垃圾邮件发送者能够在四个小时内适应。

为了不那么痛苦,也不必以后重做所有事情,我们必须首先考虑反馈循环会是什么样子,以及如果环境发生变化我们会做什么。 让我们从收集数据开始——这是我们算法的燃料。

数据收集

显然,对于现代神经网络来说,数据越多越好,而且它们实际上是由产品的用户生成的。 用户可以通过标记数据来帮助我们,但我们不能滥用这一点,因为在某些时候用户会厌倦完成你的模型并会切换到另一个产品。

最常见的错误之一(这里我引用了吴恩达)是过于关注测试数据集的指标,而不是用户的反馈,这实际上是衡量工作质量的主要指标,因为我们创建了为用户提供的产品。 如果用户不理解或不喜欢模型的工作,那么一切都毁了。

因此,用户应该始终能够投票,并且应该为用户提供反馈工具。 如果我们认为一封与财务相关的信件已到达邮箱,我们需要将其标记为“财务”,并绘制一个按钮,用户可以单击该按钮并说这不是财务。

反馈质量

我们来谈谈用户反馈的质量。 首先,您和用户可以将不同的含义赋予一个概念。 例如,你和你的产品经理认为“金融”就是银行的信件,而用户认为奶奶写的一封关于她养老金的信也指的是金融。 其次,有些用户喜欢盲目地按没有任何逻辑的按钮。 第三,用户的结论可能存在严重错误。 我们实践中的一个引人注目的例子是分类器的实现 尼日利亚垃圾邮件,一种非常有趣的垃圾邮件,要求用户从突然发现的非洲远亲那里拿走几百万美元。 实施此分类器后,我们检查了这些电子邮件上的“非垃圾邮件”点击,结果发现其中 80% 是有趣的尼日利亚垃圾邮件,这表明用户可能非常容易上当受骗。

我们不要忘记,这些按钮不仅可以被人点击,还可以被各种伪装成浏览器的机器人点击。 所以原始反馈不利于学习。 您可以利用这些信息做什么?

我们使用两种方法:

  • 来自链接 ML 的反馈。 例如,我们有一个在线反机器人系统,正如我提到的,它根据有限数量的迹象做出快速决策。 还有第二个缓慢的系统在事后才起作用。 它有更多关于用户、他的行为等的数据。 因此,做出的决策是最明智的,因而具有更高的准确性和完整性。 您可以将这些系统的操作差异引导至第一个系统作为训练数据。 因此,一个更简单的系统总是会尝试接近一个更复杂的系统的性能。
  • 点击分类。 您可以简单地对每个用户点击进行分类,评估其有效性和可用性。 我们在反垃圾邮件中使用用户属性、历史记录、发件人属性、文本本身和分类器的结果来执行此操作。 结果,我们得到了一个验证用户反馈的自动系统。 由于它需要重新训练的频率要低得多,因此它的工作可以成为所有其他系统的基础。 该模型的首要任务是精度,因为使用不准确的数据训练模型会带来后果。

当我们清理数据并进一步训练我们的机器学习系统时,我们不能忘记用户,因为对我们来说,图表上成千上万的错误只是统计数据,而对于用户来说,每个错误都是一场悲剧。 除了用户必须以某种方式忍受产品中的错误之外,在收到反馈后,他预计将来会消除类似的情况。 因此,不仅值得为用户提供投票的机会,而且还可以纠正机器学习系统的行为,例如为每次反馈点击创建个人启发法;就邮件而言,这可能是过滤的能力此类信件的发件人以及该用户的头衔。

您还需要根据一些报告或请求构建模型,以半自动或手动模式提供支持,以便其他用户不会遇到类似的问题。

启发式学习

这些启发法和拐杖有两个问题。 首先,拐杖的数量不断增加,难以维护,更不用说长期的质量和性能了。 第二个问题是错误可能不会频繁发生,并且几次点击来进一步训练模型是不够的。 如果应用以下方法,这两种不相关的影响似乎可以被显着抵消。

  1. 我们制作了一个临时拐杖。
  2. 我们将数据从它发送到模型,它会定期自我更新,包括接收到的数据。 当然,在这里,启发式方法具有高精度非常重要,以免降低训练集中数据的质量。
  3. 然后我们设置监控来触发拐杖,如果一段时间后拐杖不再起作用并且完全被模型覆盖,那么你就可以安全地将其移除。 现在这个问题不太可能再次发生。

所以一支拐杖大军是非常有用的。 最主要的是他们的服务是紧急的而不是永久性的。

附加训练

再训练是添加根据用户或其他系统的反馈获得的新数据,并在其上训练现有模型的过程。 额外的训练可能会出现几个问题:

  1. 该模型可能根本不支持额外的训练,而只能从头开始学习。
  2. 自然书中没有任何地方写到额外的培训肯定会提高生产工作的质量。 常常会发生相反的情况,即只会恶化。
  3. 变化可能是不可预测的。 这是我们自己确定的一个相当微妙的点。 即使新模型在 A/B 测试中显示出与当前模型相似的结果,但这并不意味着它的工作原理相同。 他们的工作可能只有百分之一的差异,这可能会带来新的错误或返回已更正的旧错误。 我们和用户都已经知道如何忍受当前的错误,并且当出现大量新错误时,用户也可能不明白发生了什么,因为他期望可预测的行为。

因此,额外训练最重要的是保证模型得到改善,或者至少不会恶化。

当我们谈论额外培训时,首先想到的是主动学习方法。 这是什么意思? 例如,分类器确定电子邮件是否与金融相关,并在其决策边界周围添加标记示例的样本。 例如,在广告领域,这种方法效果很好,因为那里有很多反馈,您可以在线训练模型。 如果反馈很少,那么我们会得到相对于生产数据分布高度偏差的样本,在此基础上无法评估模型在运行过程中的行为。

Mail.ru Mail 中机器学习的操作

事实上,我们的目标是保留旧的模式、已知的模型,并获取新的模型。 连续性在这里很重要。 我们经常煞费苦心推出的模型已经在发挥作用,因此我们可以专注于它的性能。

邮件中使用了不同的模型:树、线性、神经网络。 对于每一个,我们都会制定自己的附加训练算法。 在额外训练的过程中,我们不仅收到新数据,而且经常收到新特征,我们将在下面的所有算法中考虑到这些新特征。

线性模型

假设我们有逻辑回归。 我们从以下组件创建损失模型:

  • 新数据的 LogLoss;
  • 我们规范新特征的权重(我们不触及旧特征);
  • 我们还从旧数据中学习以保留旧模式;
  • 也许最重要的是:我们添加了谐波正则化,这保证了根据规范,权重相对于旧模型不会发生太大变化。

由于每个Loss分量都有系数,我们可以通过交叉验证或根据产品需求为我们的任务选择最佳值。

Mail.ru Mail 中机器学习的操作

Деревья

让我们继续讨论决策树。 我们编写了以下算法来进行树的额外训练:

  1. 该产品运行着一个由 100-300 棵树组成的森林,并根据旧数据集进行训练。
  2. 最后,我们删除 M = 5 块并添加 2M = 10 个新块,在整个数据集上进行训练,但新数据的权重较高,这自然保证了模型的增量变化。

显然,随着时间的推移,树木的数量大大增加,必须定期减少树木以满足时间要求。 为此,我们使用现在无处不在的知识蒸馏(KD)。 简单介绍一下其工作原理。

  1. 我们有当前的“复杂”模型。 我们在训练数据集上运行它并在输出处获得类概率分布。
  2. 接下来,我们训练学生模型(在本例中是树较少的模型),以使用类别分布作为目标变量来重复模型的结果。
  3. 这里需要注意的是,我们不以任何方式使用数据集标记,因此我们可以使用任意数据。 当然,我们使用战斗流中的数据样本作为学生模型的训练样本。 因此,训练集使我们能够保证模型的准确性,而流样本保证了在生产分布上的类似性能,补偿了训练集的偏差。

Mail.ru Mail 中机器学习的操作

这两种技术的结合(添加树并使用知识蒸馏定期减少树的数量)确保了新模式的引入和完整的连续性。

在 KD 的帮助下,我们还对模型特征执行不同的操作,例如删除特征和处理间隙。 在我们的例子中,我们有许多重要的统计特征(按发件人、文本哈希、URL 等)存储在数据库中,这些特征往往会失败。 当然,该模型还没有准备好应对事件的这种发展,因为训练集中不会发生故障情况。 在这种情况下,我们结合 KD 和增强技术:在训练部分数据时,我们删除或重置必要的特征,并采用原始标签(当前模型的输出),学生模型学习重复此分布。

Mail.ru Mail 中机器学习的操作

我们注意到,模型操纵越严重,所需的线程样本百分比就越大。

特征删除是最简单的操作,只需要流程的一小部分,因为只有几个特征发生变化,并且当前模型是在同一组上训练的 - 差异很小。 为了简化模型(减少数倍的树数量),已经需要50到50棵了,而对于重要统计特征的遗漏,会严重影响模型的性能,甚至需要更多的流量来均衡工作量。适用于所有类型字母的新防遗漏模型。

Mail.ru Mail 中机器学习的操作

快速文本

让我们继续讨论 FastText。 让我提醒您,单词的表示(嵌入)由单词本身的嵌入及其所有字母 N 元语法(通常是三元语法)的嵌入之和组成。 由于三元组可能相当多,因此使用了Bucket Hashing,即将整个空间转换为某个固定的hashmap。 这样就得到了内层每个单词数+桶的维度的权重矩阵。

通过额外的训练,新的符号出现:单词和三元组。 Facebook 的标准后续培训没有发生任何重大事件。 只有具有交叉熵的旧权重才会根据新数据进行重新训练。 因此,不使用新特征;当然,这种方法具有与生产中模型的不可预测性相关的所有上述缺点。 这就是我们对 FastText 进行一些修改的原因。 我们添加了所有新的权重(单词和三元组),用交叉熵扩展整个矩阵,并与线性模型类似地添加调和正则化,这保证了旧权重的变化不显着。

Mail.ru Mail 中机器学习的操作

美国有线电视新闻网

卷积网络稍微复杂一些。 如果最后几层在 CNN 中完成,那么当然可以应用调和正则化并保证连续性。 但如果需要对整个网络进行额外的训练,那么这种正则化就不能再应用于所有层。 然而,可以选择通过 Triplet Loss 来训练互补嵌入(原创文章).

三重态损失

以反钓鱼任务为例,我们来概括一下 Triplet Loss。 我们采用我们的徽标以及其他公司徽标的正面和反面示例。 我们最小化第一个之间的距离并最大化第二个之间的距离,我们以较小的间隙来确保类的更紧凑。

Mail.ru Mail 中机器学习的操作

如果我们进一步训练网络,那么我们的度量空间就会完全改变,并且它与之前的度量空间完全不兼容。 这是使用向量的问题中的一个严重问题。 为了解决这个问题,我们将在训练期间混合旧的嵌入。

我们已将新数据添加到训练集中,并正在从头开始训练模型的第二个版本。 在第二阶段,我们进一步训练我们的网络(微调):首先完成最后一层,然后整个网络解冻。 在组合三元组的过程中,我们仅使用经过训练的模型计算部分嵌入,其余部分使用旧模型。 因此,在额外训练的过程中,我们保证了度量空间v1和v2的兼容性。 谐波正则化的独特版本。

Mail.ru Mail 中机器学习的操作

整体架构

如果我们以使用反垃圾邮件的整个系统为例,那么模型并不是孤立的,而是相互嵌套的。 我们拍摄图片、文本和其他特征,使用 CNN 和 Fast Text 获得嵌入。 接下来,在嵌入之上应用分类器,它提供各种类别的分数(字母类型、垃圾邮件、徽标的存在)。 信号和标志已经进入树林,等待做出最终决定。 该方案中的各个分类器可以更好地解释系统的结果,并在出现问题时更具体地重新训练组件,而不是将所有数据以原始形式输入决策树。

Mail.ru Mail 中机器学习的操作

因此,我们保证各个层面的连续性。 在CNN和Fast Text的底层,我们使用调和正则化,对于中间的分类器,我们还使用调和正则化和速率校准来保证概率分布的一致性。 嗯,树提升是增量训练的或使用知识蒸馏。

一般来说,维护这样一个嵌套的机器学习系统通常很痛苦,因为较低级别的任何组件都会导致上面整个系统的更新。 但由于在我们的设置中,每个组件都略有变化并且与前一个组件兼容,因此整个系统可以逐个更新,而不需要重新训练整个结构,这使得它可以在没有严重开销的情况下得到支持。

部署

我们已经讨论了不同类型模型的数据收集和额外训练,因此我们将继续将它们部署到生产环境中。

A/B 测试

正如我前面所说,在收集数据的过程中,我们通常会得到一个有偏差的样本,从中无法评估模型的生产性能。 因此,在部署时,必须将模型与之前的版本进行比较,以了解实际情况如何,即进行A/B测试。 事实上,推出和分析图表的过程非常常规,并且可以轻松实现自动化。 我们逐渐向 5%、30%、50% 和 100% 的用户推出模型,同时收集有关模型响应和用户反馈的所有可用指标。 在一些严重异常值的情况下,我们会自动回滚模型,而对于其他情况,在收集了足够数量的用户点击后,我们决定增加百分比。 因此,我们完全自动地将新模型带给 50% 的用户,并且向整个受众的推出将由一个人批准,尽管此步骤可以自动化。

然而,A/B 测试过程提供了优化的空间。 事实上,任何 A/B 测试都相当长(在我们的例子中,需要 6 到 24 小时,具体取决于反馈量),这使得它相当昂贵且资源有限。 此外,需要足够高的测试流量百分比才能从本质上加快 A/B 测试的整体时间(招募具有统计意义的样本来评估小百分比的指标可能需要很长时间),这使得A/B 插槽的数量极其有限。 显然,我们只需要测试最有前途的模型,我们在额外的训练过程中收到了很多模型。

为了解决这个问题,我们训练了一个单独的分类器来预测 A/B 测试的成功。 为此,我们将训练集、延迟集以及流中样本的决策统计数据、精度、召回率和其他指标作为特征。 我们还将该模型与当前生产中的模型进行启发式比较,并考虑模型的复杂性。 使用所有这些特征,经过测试历史训练的分类器会评估候选模型(在我们的例子中,这些模型是树木森林),并决定在 A/B 测试中使用哪个模型。

Mail.ru Mail 中机器学习的操作

在实施时,这种方法使我们能够将成功的 A/B 测试数量增加数倍。

测试与监控

奇怪的是,测试和监测不会损害我们的健康;相反,它们会改善我们的健康并减轻我们不必要的压力。 测试可以让你预防故障,监控可以让你及时发现故障,减少对用户的影响。

重要的是要理解,您的系统迟早总会犯错误 - 这是由于任何软件的开发周期造成的。 系统开发之初总是会出现很多bug,直到一切稳定下来,完成创新的主要阶段。 但随着时间的推移,熵会产生影响,并且由于周围组件的退化和数据的变化,错误再次出现,这我在开始时谈到过。

这里我想指出的是,任何机器学习系统都应该从其整个生命周期的利润角度来考虑。 下图显示了系统如何捕获罕见类型的垃圾邮件的示例(图中的线接近于零)。 有一天,由于一个错误缓存的属性,她发疯了。 幸运的是,由于没有监控异常触发,系统开始将大量信件保存到决策边界的“垃圾邮件”文件夹中。 尽管纠正了后果,但该系统已经犯了很多次错误,即使五年后也无法收回成本。 从模型生命周期的角度来看,这是彻底的失败。

Mail.ru Mail 中机器学习的操作

因此,像监控这样简单的事情可能会成为模型生命周期中的关键。 除了标准和明显的指标之外,我们还考虑模型响应和分数的分布,以及关键特征值的分布。 使用KL散度,我们可以将当前分布与历史分布进行比较,或者将A/B测试中的值与流的其余部分进行比较,这使我们能够注意到模型中的异常并及时回滚更改。

在大多数情况下,我们使用简单的启发式方法或模型来启动我们的第一个版本的系统,并在未来用作监控。 例如,我们监控特定在线商店的 NER 模型与常规模型的比较,如果分类器覆盖率与它们相比下降,那么我们就能了解原因。 启发式的另一个有用用途!

结果

让我们再回顾一下这篇文章的核心思想。

  • 纤维甲板。 我们始终为用户着想:他将如何忍受我们的错误,他将如何报告这些错误。 不要忘记,用户并不是训练模型的纯粹反馈来源,需要借助辅助机器学习系统来清除。 如果无法从用户那里收集信号,那么我们会寻找替代反馈源,例如连接系统。
  • 附加训练。 这里最主要的是连续性,所以我们依赖当前的生产模式。 我们训练新模型,由于谐波正则化和类似的技巧,它们与之前的模型没有太大区别。
  • 部署。 基于指标的自动部署大大减少了模型实现的时间。 监控决策的统计数据和分布、用户跌倒次数对于您安宁的睡眠和高效的周末至关重要。

好吧,我希望这可以帮助您更快地改进机器学习系统,更快地将其推向市场,并使其更可靠、压力更小。

来源: habr.com

添加评论