广告 / NOTEBOOK 课程

54 · 广告候选索引与约束匹配

明确构造机制实验(非真实广告日志)

构造机制 / 模拟市场只读 · 已保存的实验

已有输出来自保存的教学实验,并非打开页面时重新执行。 代码和原始输出保持不变;数据与历史注释保留原始语言。

A08 · 广告候选索引与约束匹配

先修:公用31–34;A07。

证据类型:明确构造机制实验(非真实广告日志)。本章不声称工业系统复现或线上收益。

学习顺序:先预测 → 只改一个变量 → 运行 → 解释结果。

问题与输入输出契约

为每个关键词构造倒排集合,查询词间OR并集;然后与地域、活动启用、正预算AND相交。top-k只可在合格候选中做。逐个广告暴力扫描是本例oracle,用以核验倒排结果。向量相似度即使高也不能越过资格约束。预算在候选后仍可能变化,出价或扣费前必须复查。

运行前预测:本章只改变的变量会使哪一项结果变化?哪些不变量必须保持?

PYTHON · 01
from pathlib import Path
import sys
root=Path.cwd()
if not (root/'reclab').exists(): root=root.parent
if str(root) not in sys.path: sys.path.insert(0,str(root))
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from reclab import ads_curriculum as ac

运行单变量对照

输入是源码中可见的小型构造数据,输出单位和约束按上文定义。运行断言核验数学与账本。

PYTHON · 02
for query in ('跑鞋','运动 旅行','未知'):
 for region in ('上海','北京'):
  print(query,region,[a['id'] for a in ac.candidates(query,region)])
assert len(ac.candidates(topk=1))==1
assert ac.candidates(query='旅行')==[]
import inspect
print(inspect.getsource(ac.candidates))
Notebook 保存的输出 · 本页未执行
跑鞋 上海 ['a', 'b']
跑鞋 北京 ['b']
运动 旅行 上海 ['a']
运动 旅行 北京 []
未知 上海 []
未知 北京 []
def candidates(query='跑鞋', region='上海', topk=3):
    ads=inventory(); index={}
    for a in ads:
        for key in a['keywords']: index.setdefault(key,set()).add(a['id'])
    tokens=set(query.split()); recalled=set().union(*(index.get(t,set()) for t in tokens))
    eligible=[a for a in ads if a['id'] in recalled and region in a['regions'] and a['active'] and a['budget']>0]
    oracle=[a for a in ads if tokens & a['keywords'] and region in a['regions'] and a['active'] and a['budget']>0]
    assert {a['id'] for a in eligible}=={a['id'] for a in oracle}
    return sorted(eligible,key=lambda a:(-a['quality']*a['bid'],a['id']))[:topk]

解释与局限

多词OR不能误写成所有条件都OR。d有旅行关键词但预算0、地域也不合,必须排除。检索结果数量小于k是正常资格结果,不能为填满广告位放松硬条件。

查看源码,再做练习

把词间OR改成AND,用暴力oracle验证;模拟活动在检索后暂停,确认扣费不会继续。

PYTHON · 03
import inspect
print(inspect.getsource(ac.candidates))
Notebook 保存的输出 · 本页未执行
def candidates(query='跑鞋', region='上海', topk=3):
    ads=inventory(); index={}
    for a in ads:
        for key in a['keywords']: index.setdefault(key,set()).add(a['id'])
    tokens=set(query.split()); recalled=set().union(*(index.get(t,set()) for t in tokens))
    eligible=[a for a in ads if a['id'] in recalled and region in a['regions'] and a['active'] and a['budget']>0]
    oracle=[a for a in ads if tokens & a['keywords'] and region in a['regions'] and a['active'] and a['budget']>0]
    assert {a['id'] for a in eligible}=={a['id'] for a in oracle}
    return sorted(eligible,key=lambda a:(-a['quality']*a['bid'],a['id']))[:topk]

来源与下一步

A-LIU定向/竞价目录;候选约束索引是Lab自编展开。这是Lab自行设计的小实验,不复制讲义全文。

GitHub中文单章 · 作者RTB讲义。中文PPT不是现代广告工程全套课;不将历史平台机制描述当作当前市场事实。

完成练习后回到广告学习路径,继续下一语义单元。

继续阅读原文

本章来源

学习标记可选,仅保存在当前浏览器中。打开页面不会自动标记已学。