百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

AI 驱动的搜索12 克服学习相关性模型中的偏差

toyiye 2024-06-21 12:36 9 浏览 0 评论


本章涵盖

  • 使用实时用户获取有关我们的 LTR 模型的反馈
  • 与实时用户进行 A/B 测试搜索相关性解决方案
  • 探索我们始终向用户展示的顶级结果之外的可能相关结果
  • 平衡利用我们从历史数据中学到的知识和探索可能相关的内容

到目前为止,我们的学习排名工作是在实验室进行的。在前面的章节中,我们使用根据用户点击自动构建的训练数据来构建模型。在本章中,我们将把我们的模型带入现实世界,与(模拟)真实用户进行试驾!

回想一下,我们将完整的自动学习排名系统与自动驾驶汽车进行了比较。在内部,汽车有一个引擎:第 10 章中讨论的基于历史判断的端到端模型再训练。在第 11 章中,我们将模型的训练数据与自动驾驶汽车方向进行了比较:我们应该优化什么来自动学习基于以前与搜索结果的交互?我们构建了训练数据,并克服了点击数据固有的关键偏差。

在本章中,我们离开实验室!我们在现实世界中监控我们的模型。我们看到模型在哪里做得很好,并了解前两章的工作是失败还是成功。这意味着探索一种新的测试来验证我们的模型:A/B 测试。在A/B 测试中,我们将实时用户随机分配到不同的模型并检查业务成果(如销售等),看看哪个模型表现最好。您可能熟悉其他环境中的 A/B 测试,但在这里我们将把对自动化 LTR 系统的影响归零。

实时用户不仅帮助我们进行验证,还帮助我们摆脱模型可能陷入的危险负反馈循环,如图 12.1 所示。

图 12.1。呈现偏差的负反馈循环。用户永远不会点击搜索永远不会返回的内容,因此相关性模型永远不会超出当前模型的知识范围。


在图 12.1 中,我们的模型只能学习向用户显示的结果中相关的内容!换句话说,我们的模型经常会模仿用户所看到的内容。不幸的是,我们遇到了先有鸡还是先有蛋的问题。好的 LTR 会尝试优化点击次数最多的结果,但用户只会点击他们前面的内容。当训练数据似乎无可救药地偏向搜索当前排名时,LTR 怎样才能变得更好呢?训练数据中的这种偏差(模仿当前显示的结果)称为呈现偏差

在我们探索了 A/B 测试之后,我们将在本章的其余部分中对抗呈现偏差。就像一辆只学习了一条次优路径的自动驾驶汽车一样,我们必须战略性地探索替代的、有前途的路径(在我们的例子中是新类型的搜索结果),以学习与用户相关的新模式。在图 12.2 中,我们看到自动化 LTR 循环通过探索得到了增强。

图 12.2。自动化 LTR 满足实时用户需求。为了发挥作用,我们的自动化 LTR 系统必须通过与用户一起探索尚未看到的结果来扩大训练数据覆盖范围,从而克服呈现偏差。


在我们开始讨论这个非常重要的主题之前,我们必须首先将第 10 章和第 11 章中学到的所有内容包装成几行代码。然后我们将能够快速迭代,探索 A/B 测试并克服呈现偏差。

12.1 我们的自动化 LTR 引擎只需几行代码

在开始 A/B 测试之前,我们将把第 10 章和第 11 章中的所有知识收集到一小部分 Python 辅助函数中。首先,我们将定义一个函数,让我们使用 SDBN 点击模型(全部第 11 章)从原始会话点击中重建训练数据。接下来,我们将创建一个同样简单的代码片段,以使用该训练数据训练模型(全部第 10 章)。在本章其余部分中,我们将快速总结这些功能,然后再深入进行 A/B 测试并克服呈现偏差。

12.1.1 将点击转化为训练数据(第11章一行代码)

在第 11 章中,我们将点击转化为训练数据。在本节中,我们将简要回顾该代码以创建一个方便的辅助函数。

回想一下第 11 章,我们克服了用户点击搜索结果的偏见。您了解了 SDBN(简化动态贝叶斯网络)点击模型。现在,我们只需将该代码包装到本节中的一个便利函数中,即可根据需要重新生成训练数据。

提醒一下,我们的点击模型将原始点击转化为训练标签或等级,映射文档与关键字的相关程度。我们构建训练数据所需的原始输入包括查询字符串、显示结果的排名、该位置的文档以及是否被单击。我们可以看到该数据框中存储的数据:

    sess_id    query       rank        doc_id          clicked
0       50002   blue ray        0.0         600603141003        True
1       50002   blue ray        1.0         827396513927        False
2       50002   blue ray        2.0         24543672067     False
3       50002   blue ray        3.0         719192580374        False
4       50002   blue ray        4.0         885170033412        True

给定这个输入,我们可以将第 11 章的所有内容包装到一个计算训练数据的函数中。回想一下,我们使用术语“判断列表”“判断”来指代我们的训练数据。我们在清单 12.1中看到了我们的判断计算。

清单 12.1。将会话转化为训练数据(第 11 章一行!)

sdbn = sessions_to_sdbn(sessions,
                        prior_weight=10, #1
                        prior_grade=0.2) #2
sdbn

输出

                                               clicked examined        grade   beta_grade
query               doc_id
blue ray                27242815414             42.0    42.0    1.000000        0.846154
                    600603132872            46.0        88.0    0.522727        0.489796
                    827396513927            1304.0      3381.0  0.385685        0.385137
                    600603141003            978.0       2620.0  0.373282        0.372624
                    885170033412            568.0       2184.0  0.260073        0.259799

...     ...     ...     ...     ...     ...
transformers dvd        47875819733             24.0    1679.0  0.014294        0.015394
                    708056579739            23.0        1659.0  0.013864        0.014979
                    879862003524            23.0        1685.0  0.013650        0.014749
                    93624974918         19.0    1653.0  0.011494        0.012628
                    47875839090         16.0    1669.0  0.009587        0.010721

让我们通过查看清单 12.1的输出来简要回顾一下我们在第 11 章中学到的内容。正如您在输出中看到的,我们计算一个数据帧,其中每个查询-文档对都有对应的clicked和examined计数。点击次数顾名思义:该产品因该查询收到的原始点击次数的总和。回想一下,这examined对应于点击模型认为用户注意到结果的次数。

统计数据grade和beta_grade是训练标签。这些对应于文档与查询相关的概率。回想一下grade简单地除以clicked:examinedSDBN 点击模型的第一个简单实现。然而,我们在第 11 章中了解到,最好考虑一下我们拥有多少信息(参见第 11.3 节)。我们不希望一次点击一次检查 (1/1 = 1.0) 与一百次点击一百次检查 (100/100 = 1.0) 一样重要。因此,对beta_grade包含更多信息的结果给予更高的权重(更喜欢一百次点击的示例)。因此,我们将在重新训练 LTR 模型时使用beta_gradeVS grade。

这些数据用作我们在第 10 章中训练的模型的训练数据。接下来让我们看看如何轻松地获取这些训练数据、训练模型并将其部署给用户。

12.1.2 通过几个函数调用进行模型训练和评估

除了重新生成训练数据之外,我们还需要在部署到实际用户之前重新训练模型。在本节中,我们将探讨核心 LTR 模型训练引擎的便利功能。这使我们能够在本章的其余部分快速试验模型。

我们将模型训练和离线评估包装在清单 12.2中的几行简单代码中。

清单 12.2。根据一些特征训练和评估模型

random.seed(1234) #1

feature_set = [ #2
    {
      "name" : "long_description_bm25",
      "store": "test",
      "class" : "org.apache.solr.ltr.feature.SolrFeature",
      "params" : {
        "q" : "longDescription:(${keywords})"
      }
    },
    {
      "name" : "short_description_constant",
      "store": "test",
      "class" : "org.apache.solr.ltr.feature.SolrFeature",
      "params" : {
        "q" : "shortDescription:(${keywords})^=1"
      }
    }
]

train, test = test_train_split(sdbn, train=0.8) #3
ranksvm_ltr(train, model_name='test1', feature_set=feature_set) #4
eval_model(test, model_name='test1', sdbn=sdbn) #5
{'blue ray': 0.0,
 'dryer': 0.0,
 'headphones': 0.0,
 'dark of moon': 0.0,
 'transformers dvd': 0.003258006235976338}

通过查看清单 12.2,让我们简要回顾一下我们在第 10 章中学到的内容。我们定义一个功能集:我们想要用来学习排名函数的 Solr 查询集。我们必须谨慎选择:希望找到能够从清单 12.1中学习训练数据的特征。

我们如何知道我们的模型是否很好地学习了训练数据?还记得第 10 章中我们在查询级别执行了测试训练拆分。这保留了一些训练数据用于测试集中的评估。我们就像教授给学生(这里是模型)进行期末考试。您可能会给学生许多示例问题来研究测试(训练数据)。但要看看学生是否真正学习了这些材料,你会给他们进行期末考试(测试问题)。这可以帮助您在将学生送入现实世界之前评估他们是否了解您所教的内容。

(当然,众所周知,课堂上的成功并不总是等同于现实世界中的成功。将我们的模型推向现实世界,对现场用户进行 A/B 测试,可能会表明它的表现并不好正如我们所希望的!稍后会详细介绍。)

最后,每个测试查询旁边的统计信息是什么?我们如何评估学生在测试问题上的成功?回想一下第 10 章,我们简单地使用了精度(相关查询的比例)。该统计数据将前 N 个等级相加并除以 N(对于我们而言,N=10),即有效的平均相关性等级。我们建议探索模型训练和评估的其他统计数据,这些统计数据偏向于获得正确的最高位置,例如贴现累积增益 (DCG)、标准化 DGC (NDCG) 或预期倒数排名 (ERR)。不过,就我们的目的而言,您的大脑已经很满了,因此我们将继续使用更简单的精确统计数据。

只要看看清单 12.2中测试查询的相关性指标,我们的模型在离线测试中表现就很差。当然,通过改进我们的离线指标,我们会在 A/B 测试中看到实时用户的显着改善。

12.2 新模型的 A/B 测试

在本节中,我们将模拟运行 A/B 测试,并将清单 12.2的模型与在实验室中表现更好的模型进行比较。我们将反思 A/B 测试的结果,为完成第 11 章中介绍的自动 LTR 反馈循环做好准备。最后,我们将反思哪些进展不顺利,并花费剩余的时间这一章为我们的自动 LTR 反馈循环添加了一个关键的、缺失的部分。

12.2.1 拿出更好的模型进行试驾

我们最初的 LTR 模型表现不佳,如清单 12.2的输出所示。在本节中,我们将训练一个新模型,一旦它看起来很有前途,我们将针对我们在清单 12.2中训练的模型在 A/B 测试中部署该模型。

让我们介绍一个改进的模型,如清单 12.3所示。

清单 12.3。通过更改功能而改进的新模型

random.seed(1234) #1

feature_set_better = [ #2
    {
      "name" : "name_fuzzy",        #3
      "store": "test",
      "class" : "org.apache.solr.ltr.feature.SolrFeature",
      "params" : {
        "q" : "name_ngram:(${keywords})"
      }
    },
    {
      "name" : "name_pf2",  #4
      "store": "test",
      "class" : "org.apache.solr.ltr.feature.SolrFeature",
      "params" : {
        "q" : "{!edismax qf=name name pf2=name}(${keywords})"
      }
    },
    {
      "name" : "shortDescription_pf2",   #5
      "store": "test",
      "class" : "org.apache.solr.ltr.feature.SolrFeature",
      "params" : {
        "q" : "{!edismax qf=shortDescription pf2=shortDescription}(
        [CA]${keywords})"
      }
    },
]

sdbn = sessions_to_sdbn(sessions)

train, test = test_train_split(sdbn, train=0.8)
ranksvm_ltr(train, 'test2', feature_set_better) #6
eval2 = eval_model(test, 'test2', sdbn=sdbn)     #6

eval2
{'blue ray': 0.0,
 'dryer': 0.07068309073137659,
 'headphones': 0.06426395939086295,
 'dark of moon': 0.25681268708548066,
 'transformers dvd': 0.10077083021678328}

关于清单 12.3,我们首先注意到的是它的输出。在同一组测试查询上,我们的模型似乎表现得更好。这看起来很有希望!事实上,我们选择了一组似乎可以更好地捕获相关性的文本匹配方面的功能!

精明的读者可能会注意到我们保留了与清单 12.2相同的测试查询。为了清楚起见,我们特意这样做了。它“足够好”,可以教您基本的人工智能搜索技能。然而,在现实生活中,我们希望进行真正随机的测试训练分割,以更好地评估模型的性能。我们甚至可以更进一步,执行交叉验证——在不同的测试/训练数据集分割上对许多模型进行重新采样和训练,以确保模型能够很好地泛化,而不会过度拟合训练数据。如果您想更深入地了解离线模型评估,我们推荐一本更通用的机器学习书籍,例如Alexey Grigorov 的Machine Learning Bootcamp (https://www.manning.com/books/machine-learning-bookcamp)。

也许您的搜索团队认为清单 12.3中训练的模型有希望,并且足以部署到生产中!团队的希望很高,所以让我们看看当我们部署到生产环境以便与实时用户进行更深入的评估时会发生什么。

12.2.2 在自动化 LTR 的背景下定义 A/B 测试

通过自动化 LTR 再训练循环设置,我们可以轻松部署有前景的新模型。但有几个问题仍未得到解答:我们如何知道我们在实验室中构建的东西是否真正在现实世界中发挥作用?处理真实的场景是完全不同的事情。

在本节中,我们将探讨(模拟)真实用户的 A/B 测试结果。我们将看到 A/B 测试如何充当自动化 LTR 系统成功的最终仲裁者:有机会纠正离线自动化 LTR 模型训练中的问题,以便我们的反馈循环变得越来越可靠。

您可能了解 A/B 测试。在这里,我们将了解它们如何纳入自动化 LTR 系统。如图 12.3 所示,A/B 测试将用户随机分配到两个变体。每个变体都包含一组不同的应用程序功能。这可能包括从不同的按钮颜色到新的相关性排名算法的任何内容。由于用户被随机分配到变体,因此我们可以更可靠地推断哪个变体在选定的业务成果(例如销售、在应用程序上花费的时间、用户保留或企业可能选择优先考虑的其他任何内容)上表现最佳。

图 12.3。搜索 A/B 测试。搜索用户被随机分配到两个相关性解决方案(这里是两个 LTR 模型)并跟踪结果。


12.2.3 将更好的模型分级为 A/B 测试

接下来,我们将把test2清单 12.3中的有前途的新模型部署到 A/B 测试中。然后我们将探讨测试结果的含义。希望很高,您的团队认为这个模型可能会在竞争中脱颖而出:清单 12.2中表现不佳的模型,我们将其称为test1。

在本节中,我们将模拟 A/B 测试,为每个模型随机分配 1000 个用户。在我们的例子中,这些模拟用户有他们想要购买的特定物品。如果他们看到这些商品,他们就会购买,并满意地离开我们的商店。如果他们不这样做,他们可能会四处浏览,并且很可能不购买而离开。当然,我们的搜索团队不知道用户希望购买什么 - 这些信息对我们来说是隐藏的。我们只看到点击和购买流,正如我们将看到的,这很大程度上受到呈现偏差的影响。

在清单 12.4中,我们有一群用户通过搜索来寻找最新的变形金刚电影transformers dvd。在我们的讨论中,我们将继续关注这个单一的查询。当然,通过真正的 A/B 测试,我们会查看完整的查询集。用户群体不会这么静态。但通过将一个查询归零,我们可以更具体地理解 A/B 测试对自动化 LTR 的影响。要更深入地了解良好的 A/B 测试实验,我们推荐 David Sweet 所著的 Manning 书籍“Tuning Up”(https://www.manning.com/books/tuning-up-from-ab-testing-to-bayesian ) -优化)。

回到清单 12.4,对于 的每次运行a_or_b_model,都会随机分配一个模型。然后,该功能live_user_query模拟用户使用查询和所选型号进行搜索、扫描结果,可能还单击并进行购买。我们不知道的是,我们的用户群体在他们的查询背后隐藏着偏好:他们希望购买清单 12.4wants_to_purchase中的商品,而购买 中的商品的概率较低。我们运行1000 次,收集使用每种型号的用户的购买情况。might_purchasea_or_b_model

清单 12.4。模拟 A/B 测试,仅关注“变形金刚 DVD”查询

random.seed(1234)  #1

wants_to_purchase = ['97360724240', '97363560449', '97363532149',
[CA]'97360810042'] #2
might_purchase = ['97361312743', '97363455349', '97361372389'] #3

def a_or_b_model(query, a_model, b_model):
    draw = random.random()

    user_made_purchase = False #3
    model_name = None
    if draw < 0.5:
        model_name=a_model  #3
    else:
        model_name=b_model  #3

    purchase_made = live_user_query(query=query,  #4
                                   model_name=model_name,
                                   desired=wants_to_purchase,
                                   meh=might_purchase)
    return (model_name, purchase_made)


NUM_USERS=1000
purchases = {'test1': 0, 'test2': 0}
for _ in range(0, NUM_USERS): #5

    model_name, purchase_made = a_or_b_model(query='transformers dvd',
                                             a_model='test1',
                                             b_model='test2')
    if purchase_made: #6
        purchases[model_name]+= 1

purchases
{'test1': 21, 'test2': 15}

正如我们在清单 12.3的输出中看到的,我们的黄金学生 modeltest2实际上在这个 A/B 测试中表现更差!怎么会这样?到底是哪里出了问题,导致离线测试指标表现如此良好,但在现实世界中结果却很差?在本章的其余部分,我们将深入研究正在发生的事情并尝试解决问题。因此,您将了解实时用户如何提高自动化 LTR 系统的准确性,让您充满信心地进行重新培训!

12.2.4 当“好”模型变坏时:我们可以从失败的 A/B 测试中了解到什么?

正如我们在清单 12.4中看到的,当我们的模型进入现实世界时,很多事情都会发生变化。在本节中,我们将反思刚刚运行的 A/B 测试的含义,以了解接下来的步骤是合适的。

当模型在实验室中表现出色,但 A/B 测试失败时,这意味着什么?这意味着,根据我们的训练数据,我们构建了一个“正确”的 LTR 模型。不幸的是,训练数据误导了我们。我们建立了一个很好的模型,但规格错误。我们需要纠正训练数据本身的问题:从我们的点击模型生成的判断。

但是,我们基于点击模型的判断会如何出现问题呢?我们在第11章中看到了几个问题:持仓偏差置信偏差。根据您的目标、用户体验和领域,可能会出现额外的偏见。在电子商务中,用户可能会被诱惑点击正在销售的商品,从而使数据偏向于这些商品。在研究环境中,一篇文章可能在搜索结果中提供比另一篇文章更丰富的摘要。一些偏见模糊了“偏见”与该领域的实际相关性之间的界限。例如,缺少图片的产品可能会获得较少的点击次数。它在技术上可能与另一个没有图像的“相关”产品相同。然而,对于用户来说,缺少图像的产品似乎不太可信,因此不会被点击。这是一种偏见吗?或者只是该领域“相关性”的实际指标,其中产品可信度是一个因素?

为了做出更好的判断,是否应该忽略或打折点击次数,而应该使用其他行为信号?也许应该包括点击“喜欢”按钮、将商品添加到购物车或“阅读更多”按钮后的后续操作?当用户点击后立即点击后退按钮时,也许我们应该忽略“廉价”或意外点击?

使用点击后操作可能很有价值。然而,我们必须问搜索排名对购买或添加到购物车等事件的影响有多大,或者我们是否应该归因于其他因素。例如,缺乏购买可能表明产品显示页面或复杂的结账流程存在问题,而不仅仅是搜索结果与特定查询的相关性存在问题。

这似乎与我们刚刚运行的 A/B 测试背道而驰。与直觉相反,我们可能会使用所有查询的总购买量等结果来评估 A/B 测试。除排名算法外,应用程序中的所有其他内容均保持不变。因此,我们知道,在宏观、系统层面上的任何重大变化,必定是由我们改变的一件事引起的。然而,当您将注意力归零到微观:文档关系的特定查询,并远离大局时,因果关系就会变得复杂。任何单一产品的购买量都会很少(许多人观看 1000 美元的电视,但很少有人购买)。数据的数量可能根本不足以了解购买是否与产品的特定查询相关性相关。

考虑到搜索用户体验、领域和行为的所有变化可能会写满很多书,但仍然不够。搜索空间不断发展,与搜索结果交互的新方式时起时落。归根结底,对于大多数场景,使用点击和标准点击模型就足够了。搜索用户界面中的点击已得到深入研究。尽管如此,做出良好的判断既是一门艺术,也是一门科学:您可能会发现对考虑额外信号的点击模型进行轻微修改对您的领域很重要,并且可能会为您的模型在 A/B 测试中的表现带来巨大的收益。您可以花与搜索本身一样多的时间来完善您的点击模型。

然而,有一个普遍有害的训练数据问题对所有点击模型提出了挑战:呈现偏差。无论我们使用点击还是更复杂的信号,用户都不会与他们看不到的东西进行交互!我们在 A/B 测试中看到,我们的用户群体想要购买某组电影。我们可能会问:这些电影是否出现在训练数据中?如果用户从未见过它们,任何自动化 LTR 系统是否能够知道它们是相关的?毕竟,如果它们从未向用户显示,就永远不会被点击,我们永远不会知道它们是否相关!

接下来我们将深入研究这个难题,并学习如何同时自动优化我们的训练数据和模型。

12.3 克服表现偏差:知道何时探索与利用

搜索专家通常会说“用户不会点击,他们找不到什么!”。换句话说,自动化 LTR 背后是一个先有鸡还是先有蛋的问题。如果原始的、调整不当的系统永远不会返回相关结果 - 任何基于点击的机器学习系统如何得知该结果是相关的?这就是呈现偏差

在本节中,您将了解一种机器学习工具,该工具会选择要探索的文档,尽管这些结果没有点击数据。自动 LTR 系统的最后一个缺失部分不仅有助于构建针对训练数据优化的模型,而且还积极参与其自身的学习,以扩大可用训练数据的广度。我们将参与自身学习的系统称为主动学习系统。

图 11.15 捕捉到了呈现偏差。右侧的项目可能与我们的查询相关,但由于没有流量,我们没有任何数据可以知道。最好为这些结果提供一些流量以了解它们是否相关。

图 12.4。呈现偏差


为了克服呈现偏差,我们必须仔细平衡利用模型当前来之不易的知识和探索超越该知识的知识。这是探索与利用的权衡。探索让我们获得知识,将点击模型的覆盖范围扩大到新的和不同类型的文档。然而,如果我们总是探索,我们永远不会利用我们的知识。当我们利用时,我们会针对目前已知表现良好的内容进行优化。利用对应于我们当前的 LTR 模型,该模型与我们的训练数据一致。了解如何系统地平衡探索和利用是关键 - 我们将在接下来的几节中使用为此工具构建的机器学习过程来讨论这一点。

12.3.1 RetroTech 训练数据中的呈现偏差

我们首先分析当前的训练数据来了解一下情况。训练数据缺少哪些类型的搜索结果?我们的知识哪里不完整?“呈现偏差”的另一种说法是,训练数据中排除了潜在的相关搜索结果:我们必须检测并克服盲点。一旦我们在本节中定义了这些盲点,我们就可以积极地退后一步来解决它们。这将使我们能够使用更强大的模型进行重新训练。

在清单 12.5中,我们创建了一个新的feature_set名为 的explore,其中我们创建了三个简单的特征:long_desc_match、short_desc_match和name_match,告诉我们给定的字段匹配是否发生。这些对应于我们的模型已经学习的特征。此外,我们还添加了一个功能has_promotion。1.0如果产品正在销售并通过营销渠道进行促销,则此功能将成为一个。我们之前没有探索过这个功能;也许这是一个盲点?

清单 12.5。transformers dvd分析判决中缺失的文件类型

sdbn = sessions_to_sdbn(sessions,   #1
                        prior_weight=10,
                        prior_grade=0.2)

feature_set = [
    {
      "name" : "long_desc_match",   #2
      "store": "explore",
      "class" : "org.apache.solr.ltr.feature.SolrFeature",
      "params" : {
        "q" : "longDescription:(${keywords})^=1"
      }
    },
    {
      "name" : "short_desc_match",   #2
      "store": "explore",
      "class" : "org.apache.solr.ltr.feature.SolrFeature",
      "params" : {
        "q" : "shortDescription:(${keywords})^=1"
      }
    },
    {
      "name" : "name_match",     #2
      "store": "explore",
      "class" : "org.apache.solr.ltr.feature.SolrFeature",
      "params" : {
        "q" : "name:(${keywords})^=1"
      }
    },
    {
      "name" : "has_promotion",   #3
      "store": "explore",
      "class" : "org.apache.solr.ltr.feature.SolrFeature",
      "params" : {
        "q" : "promotion_b:true"
      }
    },
]

sdbn_ftrs = sdbn_with_features(sdbn, feature_set)  #4
transformers_dvds = sdbn_ftrs[sdbn_ftrs['query'] == 'transformers dvd'] #5
transformers_dvds

输出:

    query grade long_desc_match        short_desc_match name_match     has_promotion
618     transformers dvd        0.0 1.0 0.0     1.0     0.0
623     transformers dvd        0.0 1.0 1.0     1.0     0.0
622     transformers dvd        0.0     1.0     1.0     1.0     0.0
621     transformers dvd        0.0     1.0     0.0     1.0     0.0
620     transformers dvd        0.0     1.0     0.0     1.0     0.0
619     transformers dvd        0.0     1.0     0.0     1.0     0.0
617     transformers dvd        0.0     0.0     0.0     1.0     0.0
610     transformers dvd        0.3     0.0     0.0     1.0     0.0
615     transformers dvd        0.3     0.0     0.0     1.0     0.0
614     transformers dvd        0.3     0.0     0.0     1.0     0.0
613     transformers dvd        0.3     0.0     0.0     1.0     0.0
612     transformers dvd        0.3     0.0     0.0     1.0     0.0
611     transformers dvd        0.3     0.0     0.0     1.0     0.0
624     transformers dvd        0.0     0.0     0.0     1.0     0.0
616     transformers dvd        0.0     0.0     1.0     1.0     0.0
625     transformers dvd        0.0     1.0     0.0     1.0     0.0

我们在清单 12.5的输出中看到训练数据的知识存在一些差距:

  • 每个项目都包含一个名称匹配
  • 不存在“促销”
  • 有一系列 long_desc_match 和short_desc_match 值

直观上,如果我们想扩展我们的知识,我们将向用户展示从清单 12.5的输出中搜索transformers dvd完全超出框框的内容。这意味着向用户展示促销商品,可能是名称不匹配的商品。换句话说,我们需要通过明确地使我们向用户显示的内容与训练数据中的内容多样化来使搜索脱离其自身的回音室。唯一的问题是:我们愿意冒多大的风险来提高我们的知识?我们不想仅仅为了扩大我们的训练数据而用随机产品覆盖搜索结果。

到目前为止,我们所做的还不是系统性的:我们只关注单个查询来看看缺少什么。我们如何实现自动化?接下来,我们将讨论一种使用称为高斯过程的工具进行自动化探索的方法。

12.3.2 超越临时性:用高斯过程进行深思熟虑的探索

高斯过程是一种统计模型,它通过捕获该预测的确定性的概率分布进行预测。在本节中,我们将使用高斯过程来选择要探索的区域。在本节之后,我们将创建一种更强大的方法来查找数据中的差距,而不仅仅是目测。

高斯过程示例:利用现有知识探索新河流

为了直观地了解高斯过程,让我们使用现实生活中探索的具体示例。这有助于您理解底层数学的作用,让您了解如何进行探索与利用权衡。只要我们愿意,这个类比就会得到回报,我们保证!您将更深入地思考我们如何从数学上进行探索与利用的权衡。

想象一下,您是一名科学家,计划调查荒野深处一条罕见的河流。当您计划旅行时,您只能从过去的探险中获得参差不齐的河流深度观察结果来了解何时可以安全旅行。例如,一项观测显示,四月份河流有两米深,而八月份的另一次观测则为一米深。您希望为您的探险选择一个理想的日期,以优化理想的河流条件(即不是季风季节,但也不是在干旱时期)。然而,您也是科学家 - 您还想在一年中尚未观测到的时间进行观测,以增加对河流的了解。所以你想要有点冒险精神。图 12.5 显示了全年进行的河流深度测量,您可以用它来计划您的旅行

图 12.5。探索河流时,过去的观察会增加对河流深度的不确定性。我们如何选择一年中最好的时间,既安全又最大限度地增加我们对河流深度的了解?



我们如何选择探险日期?如果您在 4 月 14 日观察到河流深度为 2 米,您会猜测 4 月 15 日的深度将非常接近 2 米。在那段时间旅行可能会很愉快:你知道河流不会被过度淹没。然而,你不会获得太多关于这条河的知识。尝试远离这一观察几个月,比如一月,怎么样?一月距离四月太远,无法了解河流可能的深度。我们可能会在一年中的危险时期旅行。然而,我们几乎肯定会获得新知识——也许远远超出我们的预期!由于可做的事情太少,一年中的这个时候探索的风险太大。

在图 12.5 中,我们根据相邻日期之间的预期相关性(4 月 15 日和 14 日应该非常接近)看到了对河流水位的有根据的猜测。当我们远离直接观察时,我们的确定性水平就会降低:图 12.5 中灰色区域不断扩大。

图 12.5 是一个高斯过程。它以数学方式捕获预测,以及每个预测中的不确定性。这与相关性排名有何关系?正如附近日期的河流水位相似一样,相似的搜索结果的相关性也会相似。考虑explore清单 12.5中的功能。那些名字匹配的人transformers dvd,未升级,并且没有短/长描述匹配可能具有相似的相关性等级 - 全部都是中等相关性。当我们远离这些常见的例子时——也许会添加一些促销的项目——我们对我们有根据的猜测越来越不那么确定。如果我们走得很远,一些超出框框的东西,比如没有名称匹配的搜索结果,那么就会被提升,但是如果有强大的短/长描述字段匹配,我们的不确定性就会变得非常高。就像科学家考虑一月份旅行一样,我们几乎没有能力很好地猜测这些结果是否相关。向用户展示这些结果可能会带来太大的风险。

我们使用高斯过程来平衡利用现有相关知识与冒险探索以获得知识。高斯过程使用不完整的信息来仔细权衡可能的质量和获得的知识。例如,权衡理想的河流状况或可能相关的搜索结果与更多地了解河流状况或了解新型搜索结果的相关性。我们可以仔细选择我们想要冒险获取新知识的已知安全搜索结果的距离。

在我们的transformers dvd例子中,什么样的搜索结果会具有较高的优势,也可能具有相关性/安全性,而且还能最大程度地增加我们的知识?让我们训练一个高斯过程并找出答案!

12.3.3 训练和分析高斯过程

接下来我们将亲自动手看看高斯过程是如何工作的。我们将针对查询训练高斯过程transformers dvd。然后我们将使用它来生成最佳的探索候选者。您将看到我们如何对这些探索候选人进行评分,以最大限度地降低我们的风险并增加我们获得知识的可能性。

在清单 12.6GaussianProcessRegressor中,我们使用来自 的(又名gpr)来训练高斯过程sklearn。此代码创建一个 GaussianProcess,尝试grade根据explore我们记录的特征来预测相关性。

清单 12.6。GaussianProcessRegressor使用我们的训练数据训练 a

from sklearn.gaussian_process import GaussianProcessRegressor

y_train = transformers_dvds['grade'] #1
x_train = transformers_dvds[['long_desc_match', 'short_desc_match',
                             'name_match', 'has_promotion']] #2

gpr=GaussianProcessRegressor() #3
gpr.fit(x_train, y_train) #3

一旦我们训练了GaussianProcessRegressor,我们就可以用它来进行预测。请记住GaussianProcessRegressor,这不仅意味着预测实际值,还意味着该预测的概率分布。这有助于我们衡量模型的确定性。

在清单 12.7中,我们生成了我们想要探索的候选特征值。在我们的河流勘探示例中,这些值对应于我们科学家探险的可能勘探日期。在我们的例子中,由于每个特征可以是 0 或 1,因此我们将每个可能的特征值视为候选。

清单 12.7。预测一组要探索的候选者

zero_or_one = [0,1]

index = pd.MultiIndex.from_product([zero_or_one] * 4,
                  names = ['long_desc_match', 'short_desc_match',
                      'name_match', 'has_promotion']) #1
explore_options = pd.DataFrame(index=index).reset_index()

predictions_with_std = gpr.predict(explore_options[
[CA]['long_desc_match', 'short_desc_match', 'name_match',
[CA]'has_promotion']], return_std=True) #2
explore_options['predicted_grade'] = predictions_with_std[0]  #3
explore_options['prediction_stddev'] = predictions_with_std[1] #3

explore_options.sort_values('prediction_stddev')

输出:

    long_desc_match short_desc_match  name_match  has_promotion
    [CA]predicted_grade prediction_stddev
2   0               0                 1           0
[CA]2.250003e-01    0.000000
6   0               1                 1           0
[CA]-3.569266e-08   0.000000
10  1               0                 1           0
[CA]-2.853953e-07   0.000000
14  1               1                 1           0
[CA]-2.458225e-07   0.000000
8   1               0                 0           0
[CA]-2.042939e-07   0.795059
11  1               0                 1           1
[CA]-2.042939e-07   0.795059

在清单 12.7的输出中,我们看到 a predicted_grade- the gpr’s educated guess on the relevance of that example. We also have `prediction_stddev,它捕获了图 12.5 中的灰色带 - 预测中有多少不确定性。

我们在清单 12.7的输出中注意到,名称匹配的标准差为 0。换句话说:gpr具有大量关于何时name_match=1 的信息,正如我们从之前的临时分析中所期望的那样。经过这些观察,我们发现标准差急剧下降。除了这些强名称匹配示例之外,我们还缺乏大量知识。

输出开始显示我们在清单 12.5中直观检测到的呈现偏差。关于姓名匹配的知识非常多,但对其他情况的了解却很少。哪种情况值得实时用户探索,同时最大限度地降低我们在搜索结果中向用户展示完全奇怪的内容的风险?

在清单 12.8中,我们生成探索候选对象并对其进行评分。

清单 12.8。使用预期改进算法对探索候选者进行评分

from scipy.stats import norm

theta = 0.6
explore_options['opportunity'] = explore_options['predicted_grade'] -
[CA]sdbn['grade'].mean() - theta #1

explore_options['prob_of_improvement'] = norm.cdf( (explore_options[
[CA]'opportunity']) / explore_options['prediction_stddev'])  #2

explore_options['expected_improvement'] = explore_options['opportunity'] *
[CA]explore_options['prob_of_improvement'] \
 + explore_options['prediction_stddev'] * norm.pdf( explore_options[
 [CA]'opportunity'] / explore_options['prediction_stddev'])  #3

explore_options.sort_values('expected_improvement', ascending=False).head() #4

输出:

long_desc_match short_desc_match  name_match  has_promotion opportunity
[CA]...   prob_of_improvement expected_improvement
0               0                 0           1             -0.697673
[CA]...   0.226541            0.121908
1               0                 0           1             -3.660364e-08
[CA]...   0.200650            0.104241
1               1                 0           1             -4.993262e-08
[CA]...   0.200650            0.104241
0               1                 0           1             -6.792379e-08
[CA]...   0.200650            0.104241
0               0                 0           0              1.364694e-01
[CA]...   0.208978            0.093904

清单 12.8使用一种称为“预期改进”的算法来选择最佳候选者。除了基本直觉之外,我们不会深入探讨该算法的具体细节,因此我们推荐一篇 distil.pub 文章,标题为“探索贝叶斯优化”( https://distill.pub/2020/bayesian-optimization/ ),如果您想了解更多。

预期改进算法背后的基本直觉是选择具有最高上升空间的候选者。我们如何定义这个?要么是我们高度确定地知道存在上行空间(标准差较低且预测等级较高),要么我们知道存在高度不确定性但预测等级仍然高到足以进行赌博。我们可以在清单 12.8中的以下代码行中看到这一点:

explore_options['expected_improvement'] = explore_options['opportunity'] *
[CA]explore_options['prob_of_improvement'] \
 + explore_options['prediction_stddev'] * norm.pdf( explore_options[
   [CA]'opportunity'] / explore_options['prediction_stddev'])

更多关于探索的“确定的事情”包括:

explore_options['opportunity'] * explore_options['prob_of_improvement']

同时,第二个子句(在 后面)涵盖了具有较大方差的未知机会+:

explore_options['prediction_stddev'] * norm.pdf( explore_options[
[CA]'opportunity'] / explore_options['prediction_stddev'])

在第一个子句中,您会注意到机会(我们期望获得多少)乘以发生改进的概率对应于对结果的信心。另一方面,第二个子句更多地取决于标准差。标准差和机会越高,被选择的可能性就越大。

我们可以使用一个名为 的参数来校准我们的风险承受能力theta:该值越高,我们越喜欢具有较高标准差的候选人。高theta会导致opportunity向 0 减少。这会使评分偏向第二个子句 - 未知的、较高标准差的情况。

如果我们设置得theta太高,我们的gpr操作纯粹是选择候选者来完全了解它们,而不考虑它们是否对用户有用。如果theta太低,我们就不太可能冲破泡沫,反而会偏向现有知识。高度theta类似于图 12.5 中愿意承担高风险(1 月探索)的科学家,而非常低theta就像在规避风险的时间(4 月 14 日)旅行。因为我们使用这个算法来增强现有的 LTR 系统,所以我们选择了theta0.6,有点高,以便为我们提供更多知识。

在清单 12.8的输出中,我们看到这gpr证实了我们之前的临时分析:我们应该向用户展示促销商品。这些产品更有可能产生更多的知识,并可能从赌博中获得很大的好处。

知道我们应该探索什么,让我们收集 Solr 的产品来向用户展示!清单 12.9显示了我们如何从 Solr 中选择用于探索的产品。然后,我们将在现有模型的搜索结果中散布一个或多个“探索”产品,以观察这些新结果是否获得点击。

清单 12.9。从 Solr 选择要探索的 RetroTech 产品

random.seed(1234)

explore_vect = explore_options.sort_values('expected_improvement',
[CA]ascending=False).head().iloc[0][['long_desc_match','short_desc_match',
[CA]'name_match', 'has_promotion']] #1

def explore(query, explore_vect, log=False):
    """ Explore according to the provided explore vector, select
        a random doc from that group."""
    query = explore_query(explore_vect, query) #2

    draw = random.random()

    request = {
            "fields": ["upc", "name", "manufacturer", "score"],
            "limit": 1,
            "params": {                     #3
              "q": query,                   #3
              "sort": f"random_{draw} DESC" #3
            }
        }

    if log:
        print(request)

    resp = requests.post('http://aips-solr:8983/solr/products/select',
                                   json=request).json()

    print(resp)

    return resp['response']['docs'][0]['upc'] #4

explore_upc = explore('transformers dvd', explore_vect)
explore_upc

输出

97360810042

在清单 12.9中,我们采用最佳探索候选者 - 升级项 - 然后发出 Solr 查询来获取具有这些特征的文档。我们省略了将候选项转换为 Solr 查询的一些细节,但您可以想象如果has_promotion在候选项中设置为 1.0,那么我们将发出一个查询来搜索任何带有促销的项目:+promotion_b:true等等。

我们在清单 12.9的输出中看到,对于查询transformers dvd,随机选择的用于探索的促销产品是 UPC 97360810042。这对应于“Transformers Dark of The Moon:两张光盘-蓝光 DVD 组合”。有趣的!

我们应该如何处理这份文件?这归结为设计决策。常见的选择是将其放入结果的第三个位置。这就是我们要做的,创建一个如下所示的新会话。97360810042请注意第三个插槽中的UPC ( rank== 2.0)。

    sess_id query             rank  doc_id        clicked
400 100049  transformers dvd  0.0   93624974918   False
401 100049  transformers dvd  1.0   879862003524  False
402 100049  transformers dvd  2.0   97360810042   False   <-- INSERTED
403 100049  transformers dvd  3.0   708056579739  False

在本章的笔记本中,我们模拟了许多探索过程。每个都根据清单12.9添加一个随机探索候选者,模拟添加的探索结果是否被点击,并将其附加到一组新的会话中with_explore_sessions。回想一下,这些会话作为我们计算 LTR 训练数据所需的输入(第 11 章 /清单 12.1中基于 SDBN 的判断)。

最后,我们回来呼吸空气:我们拥有重新运行自动 LTR 训练循环所需的数据。我们将了解这些添加到训练数据中的训练示例会发生什么,以及最后我们如何将这种探索融入到整个自动化 LTR 算法中。

12.3.4 检查我们探索的结果

我们通过向实时用户展示一些现成的搜索结果进行了探索。现在,我们将新会话附加到存储在数据框中的原始会话数据中with_explore_sessions。在本节中,我们将通过自动化 LTR 函数运行会话数据,以重新生成训练数据并训练模型。最后,我们将在 A/B 测试中运行这个新模型来查看结果。

您可能还记得,我们的自动化 LTR 助手可以使用该sessions_to_sdbn函数重新生成我们的训练数据。我们在清单 12.10中执行此操作,但这一次使用包含探索数据的增强会话。

清单 12.10。从新会话中重新生成 SDBN 判断

new_sdbn = sessions_to_sdbn(with_explore_sessions,
                            prior_weight=10,
                            prior_grade=0.2) #1
new_sdbn.loc['transformers dvd']  #2
doc_id      clicked examined  grade    beta_grade
97360724240     19.0    21.0      0.904762  0.677419
97360810042 78.0    87.0      0.896552  0.824742
97368920347 27.0    32.0      0.843750  0.690476
97363455349 731.0   2116.0    0.345463  0.344779
97361312804 726.0   2112.0    0.343750  0.343073
97363560449 733.0   2133.0    0.343647  0.342977

我们在清单 12.10的输出中看到包含了一个新产品。特别注意添加了 upc 97368920347。有趣的是,这部电影已promoted_b设置为true,这意味着它是上一节中新选择的“探索”候选者之一:

{
    "upc":"97368920347",
    "name":"The Transformers: The Movie - DVD",
    "name_ngram":"The Transformers: The Movie - DVD",
    "name_omit_norms":"The Transformers: The Movie - DVD",
    "name_txt_en_split":"The Transformers: The Movie - DVD",
    "manufacturer":"\\N",
    "shortDescription":"\\N",
    "longDescription":"\\N",
    "promotion_b":true,
    "id":"71a8850d-9295-4a31-a4ef-ccae356be014",
    "_version_":1710117634561802242
}

用户似乎确实被促销产品所吸引。因此,让我们将has_promotion功能从探索功能集移至主模型并重新训练以查看影响。在清单 12.11中,我们训练了一个模型,并添加了这个新功能以查看效果。

清单 12.11。使用更新的判断重建模型

random.seed(1234)

feature_set_better = [
    {
      "name" : "name_fuzzy",
      "store": "test",
      "class" : "org.apache.solr.ltr.feature.SolrFeature",
      "params" : {
        "q" : "name_ngram:(${keywords})"
      }
    },
    {
      "name" : "name_pf2",
      "store": "test",
      "class" : "org.apache.solr.ltr.feature.SolrFeature",
      "params" : {
        "q" : "{!edismax qf=name name pf2=name}(${keywords})"
      }
    },
    {
      "name" : "shortDescription_pf2",
      "store": "test",
      "class" : "org.apache.solr.ltr.feature.SolrFeature",
      "params" : {
        "q" : "{!edismax qf=shortDescription pf2=shortDescription}(
        [CA]${keywords})"
      }
    },
    {
      "name" : "has_promotion",  #1
      "store": "test",
      "class" : "org.apache.solr.ltr.feature.SolrFeature",
      "params" : {
        "q" : "promotion_b:true^=1.0"
      }
    }
]

train, test = test_train_split(new_sdbn, train=0.8)   #2
ranksvm_ltr(train, model_name='test3', feature_set=feature_set_better)  #3
eval_model(test, model_name='test3', sdbn=new_sdbn)  #4

输出

{'blue ray': 0.16923076923076924,
 'dryer': 0.05754359864451608,
 'headphones': 0.2385279187817259,
 'dark of moon': 0.25398773006134967,
 'transformers dvd': 0.563385595947119}

哇!通过比较早期清单 12.3清单 12.11的输出,我们发现将升级产品添加到训练数据中可以显着改进我们的离线测试评估。精度transformers dvd大幅跃升!如果我们搜索transformers dvd,我们会看到这一点反映在我们的数据中:

search('transformers dvd', 'test3', at=10)

输出

[{'name': 'The Transformers: The Movie - DVD'},
 {'name': 'Transformers Animated: Transform and Roll Out - DVD'},
 {'name': 'Transformers: Revenge of the Fallen - Widescreen - DVD'},
 {'name': 'Transformers/Transformers: Revenge of the Fallen: Two-Movie Mega
 [CA]Collection [2 Discs] - Widescreen - DVD'},
 {'name': 'Transformers: Dark of the Moon - Blu-ray Disc'}]

然而,证据就在布丁里!我们以前来过这里。我们知道,漂亮的离线结果并不总能转化为现实世界。当我们重新运行清单 12.4中的 A/B 测试时会发生什么?如果您还记得我们创建了一个函数a_or_b_model,可以为用户的搜索随机选择一个模型。如果结果包含用户秘密想要购买的商品,则很可能会发生购买。如果我们使用此函数重新模拟清单 12.12中的 A/B 测试,我们会发现我们的新模型似乎中了大奖!呜呼!

清单 12.12。对新test3模型重新运行 A/B 测试

NUM_USERS=1000
purchases = {'test1': 0, 'test3': 0}
for _ in range(0, NUM_USERS):      #1

    model_name, purchase_made = a_or_b_model(query='transformers dvd',  #2
                                             a_model='test1',  #2
                                             b_model='test3') #2
    if purchase_made:
        purchases[model_name]+= 1  #3

purchases

输出:

{'test1': 14, 'test3': 227}

我们在训练数据中添加了自动化探索,打造了一个自动化 LTR 系统,不仅可以从最新的用户行为中重新学习,还可以利用用户交互来探索其他可能相关的内容。这里的完整系统就像一个细心的小孩:经常使用它所拥有的知识,但也渴望玩耍和实验。孩子问:当我把牛奶掉在地板上时,我的父母会怎么做?捡起一只昆虫会是什么感觉?这块石头尝起来怎么样?作为成年人,我们知道不能做这些事!但在训练新模型时,我们需要像孩子一样思考:永远是学生,渴望学习和探索!

12.4 探索、利用、收集、冲洗、重复:完整的自动化 LTR 循环

完成最终作品后,我们将看到探索新功能如何帮助我们克服呈现偏差。特征探索和训练数据探索是齐头并进的,因为我们通过了解我们缺乏的、可能需要设计到搜索中的特征来了解我们的呈现偏差。在本章中,我们使用了一个带有“促销”的简单示例,但是还有哪些其他更复杂的功能可能会在训练数据中显示盲点?在本节中,我们通过增强完整的自动化 LTR 算法来结束,不仅包括使用训练数据训练模型,还包括对训练数据当前泡沫之外的探索。

为了总结我们新的自动探索自动 LTR 算法,我们遵循以下三个主要步骤:

1. Exploit: gather known features and train the LTR model for ranking using
[CA]existing training data
2. Explore: use hypothesized, 'explore' features to eliminate training data
[CA]blind spots
3. Gather: with a deployed model, and a trained `gpr` model, show
[CA]explore/exploit search results, and gather clicks to build judgments

我们可以通过将过去三章收集到一个最终代码清单中来总结它们。清单 12.13将所有部分组合在一起(省略了一些内部结构)。我们在此算法中的主要决策点是用于探索和利用的特征。我们还可以在幕后更改所选的点击模型、LTR 模型架构以及我们的风险承受能力(参数theta)。

清单 12.13。全自动LTR算法总结

# =========
# EXPLOIT

exploit_feature_set = [       #1
    {
      "name" : "name_fuzzy",
      "store": "exploit",
      "class" : "org.apache.solr.ltr.feature.SolrFeature",
      "params" : {
        "q" : "name_ngram:(${keywords})"
      }
    }
    ... # more features for exploitation
]

train, test = test_train_split(sdbn, train=0.8) #1
ranksvm_ltr(train, model_name='exploit', feature_set=exploit_feature_set) #1
eval_model(test, model_name='exploit', sdbn=new_sdbn) #1

# ===============
# EXPLORE

explore_feature_set = [     #2
    {
      "name" : "manufacturer_match",
      "store": "explore",
      "class" : "org.apache.solr.ltr.feature.SolrFeature",
      "params" : {
        "q" : "manufacturer:(${keywords})^=1"
      }
    }
    ... # more features for exploitation w/ existing features from exploit
]

explore_vect = best_explore_candidate(sdbn, explore_feature_set, theta=0.6) #3
explore_upc = explore('transformers dvd', explore_vect) #3


# =========
# GATHER                                     #4
sdbn = sessions_to_sdbn(sessions,            #4
                        prior_weight=10,     #4
                        prior_grade=0.2)     #4

# GOTO "exploit" and repeat full loop  #5

在此循环中,我们捕获了更好的自动化 LTR 流程。我们通过理论化训练数据盲点背后可能存在的特征来主动学习训练数据盲点。让循环运行,我们观察其性能,决定何时将探索功能提升为完整的生产“利用”功能集。当我们淘汰旧的点击数据时,我们还可以注意到旧功能何时不再重要,以及新功能何时因趋势和季节性而变得重要。

总而言之,该算法为您提供了一个强大的机制来实现理想的排名,该排名考虑了可以向用户显示的全方位选项。它允许您选择新功能来调查盲点,从而得出相关性算法,最大限度地提高用户期望在搜索中看到的内容。

12.5 总结

  • 在离线测试中表现良好表明我们的特征可以近似训练数据。然而,这并不能保证成功。A/B 测试可以向我们展示训练数据本身具有误导性的情况。
  • 必须监控训练数据是否存在偏差并仔细纠正。
  • 呈现偏差是搜索中最有害的问题之一。当我们的模型无法从用户点击中了解相关内容时,就会出现呈现偏差。当我们的搜索从未显示真正相关的结果时,就会发生这种情况,因此用户永远不会点击它们!
  • 我们可以通过让自动化 LTR 流程积极参与寻找训练数据中的盲点来克服呈现偏差。这样做的模型参与主动学习
  • 高斯过程是选择有希望的探索机会的一种方法。使用一组特征,我们可以找到训练数据中缺少的内容,然后选择那些内容向用户展示。我们可以尝试通过特征描述数据的不同方式,以找到新的、有趣的盲点和研究领域。
  • 当我们将利用现有知识与探索盲点结合起来时,我们就拥有了更好的自动化 LTR - 反映智能,可以自动探索和利用功能,几乎不需要内部维护。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码