介绍LinNét。使用丰富的图像和文本数据对产品进行大规模分类
上次我们在这个博客上讨论产品分类的时候,Shopify正在为超过100万的商家提供服务。此后,我们不断成长,目前为170多万商家提供服务,这些商家在不同的行业中销售数十亿的产品。随着新商户的涌入,我们决定重新评估我们现有的产品分类模型,以确保我们了解商户的销售情况,这样我们就可以建立最好的产品,帮助他们提高销售。
为了做到这一点,我们考虑了两个最重要的指标。
- **我们的预测多长时间是正确的?**为了回答这个问题,我们看了模型的精度、召回率和准确率。这对任何有分类机器学习模型经验的人来说应该是非常熟悉的。为了简单起见,我们把这组指标称为 "准确性"。这些指标的计算是使用一个保留集,以确保无偏见的测量。
- **我们多长时间提供一次预测?**我们现有的模型过滤掉了低于一定信心阈值的预测,以确保我们只提供我们有信心的预测。因此,我们定义了一个名为 "覆盖率 "的指标:有预测的产品数量与产品总数的比率。
除了这两个指标,我们还关心这些预测是如何被消费的,以及我们是否提供了正确的访问模式和SLA来满足所有用例。举个例子,我们可能想为我们的消费者提供低延迟的实时预测。
在根据这些指标评估了我们的模型,并考虑到我们希望建立的各种数据产品后,我们决定建立一个新的模型来提高我们的性能。当我们接近这个问题时,我们提醒自己注意现有模型的盲点。这些包括诸如只使用文本特征进行预测,以及只能理解英语产品的能力。
在这篇文章中,我们将讨论我们如何发展和更新我们的产品分类模型,使我们的叶子精度提高8%,同时使我们的覆盖率翻倍。我们将深入探讨大规模解决这一问题所面临的挑战,以及我们在这一过程中所作的技术权衡。最后,我们将描述一个产品,该产品目前被多个内部团队和我们的合作伙伴生态系统用来构建衍生数据产品。我们把这个版本的模型命名为。LinNét,以被认为是现代分类法之父的Carl Von Linné命名。
为什么产品分类很重要?
在我们讨论这个模型之前,让我们回顾一下为什么产品分类是一个需要解决的重要问题。
商家在我们的平台上销售各种产品,这些产品在不同的销售渠道销售。我们相信,为我们的商户建立最好的产品的关键是了解他们在销售什么。例如,通过将我们商户销售的所有产品归入一套标准的类别,我们可以建立一些功能,如在所有渠道进行更好的搜索和发现,以及个性化的洞察力,以支持商户的营销努力。
我们目前的分类模型使用谷歌产品分类法(GPT)。GPT是一个超过5500个类别的列表,帮助我们组织产品。与大多数分类问题常见的传统平面类别或标签列表不同,GPT有一个分层的树形结构。分类法中类别的庞大数量以及不同类别之间的复杂结构和关系都使得这个问题很难被建模和解决。
以动物和宠物用品分类为例的GPT样本分支
模型
在我们能够深入创建我们的改进模型之前,我们必须考虑到我们必须通过探索我们可用的产品功能来工作的内容。下面是一个产品管理页面的例子,你会在Shopify商家的商店后台看到。
Shopify商店后台的产品管理页面
上面的图片显示了Shopify管理中的产品管理页面。我们已经强调了可以帮助我们识别产品的功能。这些包括标题、描述供应商、产品类型集合、标签和产品图片。
很明显,我们有一些功能可以帮助我们识别产品是什么,但没有任何结构化的格式。例如,销售同一产品的多个商家可以对产品类型使用不同的值。虽然这为商家提供了很大的灵活性来组织他们的内部库存,但在对这些产品进行分类和跨店索引时却造成了更大的难题。
大体上说,我们有两种类型的特征可供选择。
文本特征 |
|
视觉特征 |
|
这些是我们用来对产品进行分类的特征。
特征矢量化
首先,我们必须选择我们的特征需要什么样的矢量化方法,因为文本和图像特征在其原始状态下不能被大多数机器学习模型使用。经过大量的实验,我们采用了使用神经网络的转移学习。我们使用预先训练好的图像和文本模型将我们的原始特征转换成嵌入,以进一步用于我们的分层分类。这种方法为我们提供了灵活性,以纳入我们将在下一节详细讨论的几个原则。
我们对几个预训练的模型进行了竞赛,以决定使用哪些模型进行图像和文本嵌入。需要考虑的参数包括模型性能和计算成本。当我们平衡了这两个参数后,我们确定了以下选择。
- 用于文本的多语言BERT
- 用于图像的MobileNet-V2
模型结构
正如我们在上一篇文章中所解释的那样,对分层分类问题的分类给我们带来了超越平面多类问题的额外挑战。我们从以前解决这个问题的尝试中得到了两个教训。
- 保留这个问题的多类性质对进行预测极为有利。比如说。分类法中的第1级有21个不同的类标签,而第3级则有500多个标签。
- 学习父结点有助于预测子结点的情况。例如,如果我们回过头来看Shopify产品管理的例子中的图片,如果我们已经预测了该产品属于 "狗用品",那么预测该产品为 "狗床 "就更容易了。
因此,我们把这个问题归纳为一个多任务、多类别的分类问题,以便把这些知识纳入我们的模型。
-
多任务。 分类法的每一层都被视为一个独立的分类问题,每一层的输出将被反馈到下一个模型,以进行下一层的预测。
-
多类。分类法中的每一层都有不同数量的类可供选择,因此每个任务都成为一个单一的多类分类问题。
分类法前两层的模型结构概要
上面的图片说明了我们为纳入这些经验所采取的方法。如前所述,我们使用预先训练好的模型来嵌入原始文本和图像特征,然后将嵌入物送入多个隐藏层,然后有一个多类输出层用于第1级预测。然后,我们将该层的输出与原始嵌入一起,送入后续的隐藏层以预测第2级输出。我们一直持续这个反馈循环,直到第7级。
一些需要注意的要点。
- 我们总共有七个输出层,对应于分类法的七个级别。每个输出层都有自己的损失函数与之相关。
- 在模型的前向传递过程中,父节点影响子节点的输出。
- 在反向传播过程中,所有七个输出层的损失都以加权的方式结合起来,得出一个单一的损失值,用来计算梯度。这意味着低层的表现可以影响高层的权重,并将模型推向正确的方向。
- 尽管我们将父节点预测反馈给子节点预测任务,以影响这些预测,但我们并不强加任何硬性约束,即子节点预测应该严格是上一级预测的子节点。举例来说,即使模型预测第1级为 "艺术和娱乐",也允许它将第2级预测为 "宠物用品"。我们在训练过程中允许这样做,这样子节点的准确预测可以将父节点的错误预测引向正确的方向。我们将在随后的章节中,在推理阶段重新审视这一点。
- 我们可以在训练阶段使用类权重来处理类的不平衡。我们的数据集是高度不平衡的。这使得我们很难训练出一个能泛化的分类器。添加类权重使我们能够减轻类不平衡的影响。通过提供类别权重,我们能够惩罚那些样本较少的类别的预测错误,从而克服这些类别中缺乏观察的问题。
模型训练
Shopify的规模的好处之一是可以获得大量的数据集来建立伟大的数据产品,使我们的商家和他们的买家受益。对于产品分类,我们已经收集了数以亿计的观察值来学习。但是,这也带来了它自己的挑战!我们上面描述的模型在复杂性上是巨大的。它最终有超过2.5亿个参数。再加上我们的数据集的大小,在合理的时间内训练这个模型是一项具有挑战性的任务。使用一台机器来训练这个模型,即使使用GPU,也要花上数周时间。我们需要在不牺牲模型性能的同时减少训练时间。
我们决定采用数据并行化的方法来解决这个训练问题。这将使我们能够通过对训练数据集进行分块,并在每个分块中使用一台机器来训练模型,从而加快训练过程。该模型是使用分布式Tensorflow在谷歌云平台上使用多个工作者和GPU建立和训练的。我们进行了多种优化,以确保我们尽可能有效地利用这些资源。
模型推理和预测
正如模型架构部分所描述的,在训练期间,我们不限制模型严格遵循层次结构。虽然这在训练过程中是可行的,但我们不能允许在推理过程中出现这样的行为,否则我们就会危及为消费者提供可靠和流畅的体验。为了解决这个问题,我们在推理步骤中加入了额外的逻辑。预测期间的步骤是
- 从训练好的模型进行原始预测。这将返回七个置信度分数的数组。每个数组代表分类法的一个层次。
- 选择在第一层具有最高置信度分数的类别,并将其指定为第一层预测。
- 收集第1级预测的所有直系子孙。从这些子代中,选择置信度最高的子代,并将其指定为第2级预测。
- 继续这个过程,直到我们达到第7级预测。
我们将上述逻辑作为Tensorflow操作来执行,并建立一个Keras子类模型,将这些操作与训练好的模型相结合。这使我们能够拥有一个单一的Tensorflow模型对象,其中包含批处理和在线推理中使用的所有逻辑。
包括额外推理逻辑的子类模型示意图
上面的图片说明了我们如何建立一个Keras子类模型,以采取原始训练的Keras功能模型,并将其附加到下游的Tensorflow图中,以进行递归预测。
指标和性能
我们收集了一套不同的指标来衡量分层分类模型的性能。这些指标包括。
- 层次准确度
- 层次精度
- 分层召回率
- 层次性的F1
- 覆盖率
除了上述所有指标的提升,新的模型还能对产品进行多语言分类,并且不局限于英文文本的产品,这对我们进一步推进Shopify的使命--让全世界的人都能更好地享受商业。
为了确保只有最高质量的预测被浮出水面,我们在不同级别的信心分数上设置了不同的阈值,以过滤掉低信心的预测。这意味着并非所有的产品在每个级别都有预测。
这方面的一个例子见下图。
智能阈值处理
上图说明了狗床的照片是如何导致四个级别的预测的。前三层都有一个高置信度分数,并将被曝光。第四级预测的可信度得分很低,这个预测不会被曝光。
在这个例子中,由于第四级预测不符合我们的最低置信度要求,所以我们不会曝光第三级以上的预测。
在这个过程中,我们学到的一件事是如何调整模型,使这些不同的指标以最佳方式得到平衡。例如,我们可以以降低覆盖率为代价实现更高的分层精度。这些都是很难做出的决定,需要我们了解我们的业务用例和优先级来做出这些决定。我们怎么强调都不为过,关注业务用例和商户体验以指导我们是多么重要。我们为减少商家的负面体验和摩擦进行优化。虽然指标是模型性能的重要指示,但我们也对我们的预测进行了抽查和人工QA,以确定关注的领域。
一个例子是我们如何密切关注属于 "宗教和礼仪 "等敏感类别的项目的模型性能。虽然整体指标可能看起来不错,但它们也可能掩盖了模型在分类法的小范围内的表现,这可能会导致大量的商户摩擦。我们手动调整了置信度的阈值,以确保在这些敏感领域的高性能。我们鼓励读者在推出任何由机器学习驱动的面向消费者的数据产品时也采用这种做法。
我们该何去何从?
从以前的模型升级后,我们在精度和覆盖面上都有了很大的提升。在一个较高的水平上,我们能够将精度提高8%,同时覆盖率也几乎翻了一番。我们对更多的产品有了更准确的预测。虽然我们改进了模型,并提供了一个强大的产品,使我们的商户受益,但我们相信我们可以进一步改进它。一些需要改进的地方包括。
-
**数据质量。**虽然我们确实有一个巨大的丰富的标记产品的数据集,但它确实包含了高度的不平衡性。虽然我们可以使用各种众所周知的技术来解决数据集中的不平衡问题,如类权重和过度/反抽样,但我们也认为我们应该在目前没有足够数据的地方收集新的数据点。随着Shopify的发展,我们注意到商家销售的产品越来越多样化。这意味着我们需要不断收集这些新类别和分类法部分的数据。
-
商家层面的特征。目 前的模型专注于产品层面的特征。虽然这是最明显的起点,但也有很多信号严格来说并不属于单个产品层面,而是滚动到商户层面,可以帮助我们做出更好的预测。这方面的一个简单的例子是一个名为 "Acme Shoe warehouse "的假想商家。看起来很明显,这个商店的名字强烈暗示了这个商店销售的产品可能是什么。
Kshetrajna Raghavan是一名数据科学家,在Shopify的商务算法团队工作。他喜欢解决复杂的问题,帮助大规模地使用机器学习。他与他的妻子和两条狗住在旧金山湾区。在LinkedIn上与Kshetrajna联系,进行 交流。
如果你对大规模解决复杂问题充满热情,并且渴望了解更多--我们一直在招聘!请联系我们或在我们的招聘网页上申请。
在您的收件箱中获得这样的故事!
来自构建和扩展Shopify的团队的故事。这个商务平台为全球超过170万家企业提供支持。
电子邮件地址是的,给我登记
与我们分享您的电子邮件并接收每月的更新。
谢谢你的订阅。
你很快就会开始收到免费的提示和资源。