想象你是一家餐厅门口负责迎宾的服务员。一位顾客推门进来,只丢下一句“随便吃点”。这四个字背后却藏着无数种可能:TA也许只想花五分钟买个三明治赶下午的会;也许想和朋友坐下来喝酒聊天两小时;也许已经看中橱窗里的招牌菜,就差下单;又也许只是在为家人的生日宴踩点。你绝不能只看字面意思,而是要飞快地打量穿着、时间、有没有同行的人,在心里瞬间判断出“随便吃点”背后的真实意图,再决定是带路、递菜单、推荐套餐还是预订包间。 搜索引擎和你其实是同行。用户在搜索框里敲下几个字,背后可能藏着“找官网”“查资料”“想下单”或“在比价”四种心思。把这层潜台词摸清楚,正是搜索意图识别要解决的核心问题。这篇文章将从零带你认识搜索意图识别:它如何定义、如何提取线索、如何用贝叶斯与决策树分类、如何用深度学习增强,又如何落地到真实的搜索系统并持续评估优化。

岗位关联

掌握搜索意图识别,是搜索算法、推荐系统和广告算法工程师的必修课。它能帮你从“匹配关键词”进化到“理解用户”,让搜索转化率和用户体验双双提升。

目录
  1. 可视化演示
  2. 意图分类基础
  3. 特征提取引擎
  4. 概率分类器
  5. 决策树路径
  6. 深度学习增强
  7. 工程落地实战
  8. 效果评估体系
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示搜索意图三分法分类路由、意图识别建模方法从规则到深度学习的演进、意图感知多通道召回与排序优化,交互理解搜索引擎意图识别系统。

本节配有交互动效(进入视口后自动加载,约 3KB)。

'+modeData.classify.caption+'

意图分类基础

想象你是一家餐厅的迎宾员。一位顾客推门进来,只留下一句“随便吃点”。这四个字看似简单,背后却藏着四种不同的诉求:也许TA只想五分钟买个三明治赶下午的会;也许TA想约朋友坐下来聊两小时;也许TA已经看中招牌菜,就差下单;也许TA只是在替家人踩点,看这家店适不适合办生日宴。有经验的迎宾员从不按字面接话,而是快速打量衣着、时间、同行者,去猜那句“随便吃点”的潜台词。

搜索引擎面临的正是同样的场景。用户敲进搜索框的词(我们叫“查询”)往往短小、模糊、口语化。搜“苹果”,可能是想找苹果官网(导航意图),也可能是想了解苹果的营养价值(信息意图),还可能想买一部iPhone(交易意图)。业界把用户藏在查询背后的真实目的称为“搜索意图”,并总结为四类:导航类、信息类、交易类、商业调查类。搜索引擎要做的第一件核心任务,就是给查询判定意图。

为什么这个判定如此重要?因为同样一句话,配错答案的代价完全不同。导航意图需要官网入口,信息意图需要百科或教程,交易意图需要商品卡片和购物车,商业调查需要对比评测和真实用户评价。一旦意图判错,用户会在几秒内跳出,广告主白白浪费一次竞价点击。于是系统把意图识别抽象为一个选择问题:从候选意图里,选概率最大的那个。

所以,意图识别的第一步,本质上是“带着概率思维猜潜台词”。不过这样的猜测并非凭空而来,服务员必须借助大量观察线索才能提高猜中的概率。这些线索,正是下一节要说的特征。

intent=arg⁡max⁡c∈C P(c∣q)\text{intent} = \arg\max_{c \in C} \, P(c \mid q)
通俗解释:公式在做的事,就是服务员从四张意图卡片里,选出当前查询条件下“最可能”的那一张。
  1. intent最终判定的意图标签,比如“导航”“信息”“交易”或“调查”,代表系统写给排序引擎的指令。
    intent∈{导航,信息,交易,调查}\text{intent} \in \{\text{导航}, \text{信息}, \text{交易}, \text{调查}\}
  2. argmax一种“挑最大”运算:遍历后面所有候选,返回让函数取值最大的那一个。相当于服务员把四种可能性逐个掂量,挑出最像的那个。
    arg⁡max⁡cf(c)=使 f(c) 最大的 c\arg\max_{c} f(c) = \text{使 } f(c) \text{ 最大的 } c
  3. c 与 Cc 表示一个具体的候选意图,C 表示全部候选意图的集合(四类)。如同菜单上的四道套餐,c 是其中一道菜。
    C={c1,c2,c3,c4}C = \{c_1, c_2, c_3, c_4\}
  4. P(c | q)在已知用户输入查询 q 的前提下,真实意图为 c 的条件概率。服务员看到“苹果”两个字时,心中对四种可能分别在估概率。
    P(c∣q)=查询为 q 时属于 c 的概率P(c \mid q) = \text{查询为 } q \text{ 时属于 } c \text{ 的概率}
  5. q用户的原始查询,可能是单词、短语,甚至带错别字的搜索串,它是所有判断的出发点。
    q=用户输入的搜索词q = \text{用户输入的搜索词}

特征提取引擎

服务员之所以能猜对,不是因为会读心术,而是因为会看细节。客人进门,穿西装的可能是商务午宴,带两个哭闹孩子的多半要尽快安排家庭桌,手里提着奶茶、眼睛盯着菜单的人可能在犹豫要不要尝鲜。这些细节就是“特征”。搜索引擎也一样,它首先要做的,是把一次模糊的查询转化成一组可以计算的数字信号。

搜索引擎的特征体系主要包含四类。查询词特征是最直接的:关键词、词频、词序,比如“手机壳 硅胶 便宜”里的“便宜”强烈暗示交易倾向。会话上下文则看同一登录用户在本次搜索前后的行为:先搜“苹果”再搜“13 价格”,前面的词就帮我们锁定了交易意图。点击行为信号包括点击率、停留时长、二次点击率:用户搜“手机”后点进商品页却立刻退出,说明商品列表没有满足TA的深层需求,可能意图判断有偏。场景信息包括设备类型、时间、地理位置:深夜在手机上搜“附近火锅”,比清晨搜同样词更接近到店用餐的交易意图。

有了这些信号,如何把它们变成模型能读懂的数值?最经典的文本表示法是TF-IDF。它的思路很朴素:一个词在当前查询里出现得越频繁,说明它越重要;但如果这个词在几乎所有网页里都出现,说明它没什么区分度。两者相乘,就得到了每个词的权重,拼成一个向量供下游模型使用。

把上面这些特征打包,交给分类器,就像把客人的名片、穿着、时间一起递给老练的服务员,让TA有底气地判断该带你去哪个区域。

TF-IDF(t,q)=TF(t,q)×log⁡(NDF(t)+1)\text{TF-IDF}(t, q) = \text{TF}(t, q) \times \log\left(\frac{N}{\text{DF}(t)}+1\right)
通俗解释:词频×逆文档频率:查询里常出现、全局里又稀有的词,权重最高,比如“越狱教程”里的“越狱”比“手机”更能区分意图。
  1. TF(t, q)词频,单词 t 在当前查询 q 里出现的次数除以查询总词数,衡量“这个词有多显眼”。比如“手机价格”中“价格”的TF是1/2。
    TF=词 t 在 q 中的出现次数查询总词数\text{TF} = \frac{\text{词 } t \text{ 在 } q \text{ 中的出现次数}}{\text{查询总词数}}
  2. N索引中的文档总数,代表搜索引擎的全局视野。比如索引了100亿个网页,N就是100亿。
    N=全网文档总数N = \text{全网文档总数}
  3. DF(t)包含单词 t 的文档数量。若“手机”出现在30亿个页面中,DF就是30亿,说明这个词太常见、区分能力弱。
    DF(t)=包含词 t 的文档数\text{DF}(t) = \text{包含词 } t \text{ 的文档数}
  4. log(N/DF(t)+1)逆文档频率。词越常见,这一项越小;“的”“了”这类停用词会被压到很低的权重。
    IDF=log⁡(NDF(t)+1)\text{IDF} = \log\left(\frac{N}{\text{DF}(t)}+1\right)
  5. TF × IDF 相乘综合了局部重要性和全局区分度,得到每个词的最终特征权重。
    权重=词频×逆文档频率\text{权重} = \text{词频} \times \text{逆文档频率}

概率分类器

老服务员有个习惯:从不凭单条线索下结论,而是把多种线索按经验叠起来。比如穿西装的客人,七成是商务宴请;如果还带着公文包,概率能升到九成;如果又是在工作日中午,那几乎可以断定是商务午餐。这种“根据经验不断更新判断”的过程,正是贝叶斯分类器的精髓。

朴素贝叶斯把这类经验转化为概率计算。它先统计每类意图在历史数据中的占比,这叫先验概率;再统计在某个意图下出现某个词的条件概率,这叫似然概率。把两者乘起来,就得到后验概率——也就是我们在第一节里提到的 P(c|q)。最后选取后验最大的类别作为结论。

为了简化计算,朴素贝叶斯做了一个“朴素”假设:各个词在给定类别时相互独立。有了这个假设,就可以把整句查询拆成词,单独计算每个词的条件概率后相乘。虽然现实中的词语往往互相影响,但实验证明这个简化假设在文本分类中相当好用。

朴素贝叶斯就像一位经验丰富的服务员,把每条线索独立摊开、逐项打分,最后把总分最高的可能性当作结论。虽然“各线索独立”在现实中难以完全成立,但在搜索意图识别上常常已经足够好。

P(c∣q1,q2,…,qn)=P(c)⋅∏i=1nP(qi∣c)P(q1,q2,…,qn)P(c \mid q_1, q_2, \ldots, q_n) = \frac{P(c) \cdot \prod_{i=1}^{n} P(q_i \mid c)}{P(q_1, q_2, \ldots, q_n)}
通俗解释:后验 ∝ 先验 × 各项词语似然的乘积,最后归一化。分母对所有类别都一样,比较时可以直接忽略。
  1. c候选意图类别,比如“交易”。服务员要判定的“这位客人来干什么”。
    c∈{导航,信息,交易,调查}c \in \{\text{导航}, \text{信息}, \text{交易}, \text{调查}\}
  2. q1, q2, ……, qn查询被切分后的词序列,比如“手机 优惠 下单”就切成了三个词。
    q=(q1,q2,…,qn)q = (q_1, q_2, \ldots, q_n)
  3. P(c)先验概率,表示没有看到查询时,历史用户属于类别 c 的比例。如同服务员在没有其他信息时先按客流猜测。
    P(c)=类别 c 的样本数总样本数P(c) = \frac{\text{类别 } c \text{ 的样本数}}{\text{总样本数}}
  4. P(q_i | c)似然概率,在已知类别 c 下出现词 qi 的概率,衡量“交易意图常伴随哪些词”。
    P(qi∣c)=类别 c 中词 qi 的出现次数类别 c 的总词数P(q_i \mid c) = \frac{\text{类别 } c \text{ 中词 } q_i \text{ 的出现次数}}{\text{类别 } c \text{ 的总词数}}
  5. Π(连乘)将所有词的条件概率乘起来,表示整条查询在类别 c 下的综合证据。
    ∏i=1nP(qi∣c)=P(q1∣c)×P(q2∣c)×⋯\prod_{i=1}^{n} P(q_i \mid c) = P(q_1\mid c) \times P(q_2\mid c) \times \cdots
  6. 分母 P(q1,……,qn)归一化常数,对所有类别都一样,比较时可以直接忽略。
    P(q1,…,qn)=∑cP(c)⋅∏iP(qi∣c)P(q_1, \ldots, q_n) = \sum_{c} P(c) \cdot \prod_i P(q_i \mid c)

决策树路径

有些服务员靠直觉,有些服务员靠“流程单”:先看时间——若是午餐时段,再看同行者——有没有带小孩,再看客人手里有没有购物袋……新手照着流程单一步步走也能得出结论。这正是决策树的天然表达:把复杂的判断拆成一连串简单的“是/否”问题。

决策树把判断过程建模成一棵树:根节点是第一个要考察的特征,比如“查询词里有没有‘买’‘价’‘领券’”;每个内部节点继续按特征分叉,直到叶节点给出最终意图标签。训练的目标,是找到最能有效区分的特征作为分裂点。而“是否有效区分”,靠的是信息增益来衡量。

信息增益衡量“用特征 A 切分数据之后,数据混乱度下降了多少”。混乱度用信息熵来度量:熵越大,数据类别越混乱;切分后熵越小,说明特征越有区分力。所以每次分裂时,算法遍历所有候选特征,选出信息增益最大的那一个,不断重复,就长成了一棵完整的树。

决策树如同一张服务流程卡,把“什么时候该往哪个方向引导”写得明明白白,既容易理解,也方便运营人员检查,但面对高维文本时容易过拟合,通常会配合剪枝来控制规模。

Gain(D,A)=Ent(D)−∑v∈A∣Dv∣∣D∣⋅Ent(Dv)\text{Gain}(D, A) = \text{Ent}(D) - \sum_{v \in A} \frac{|D_v|}{|D|} \cdot \text{Ent}(D_v)
通俗解释:分裂前的不确定性 − 分裂后的加权不确定性,差得越大的特征越值得优先使用。
  1. D当前数据集,比如一批标注好的查询样本。
    D={(查询,意图标签),…}D = \{(\text{查询}, \text{意图标签}), \ldots\}
  2. A候选特征,比如“是否包含价格词”或“是否为深夜查询”。
    A={价格词,深夜,长查询,…}A = \{\text{价格词}, \text{深夜}, \text{长查询}, \ldots\}
  3. Ent(D)数据集 D 的信息熵,衡量类别分布的混乱程度。所有样本全是“交易”,熵为0;四类意图平均分布,熵最大。
    Ent(D)=−∑cP(c)⋅log⁡P(c)\text{Ent}(D) = -\sum_{c} P(c) \cdot \log P(c)
  4. Dv在特征 A 上取值为 v 的样本子集。比如特征“是否深夜”,v 取“是”或“否”。
    Dv={x∈D∣A(x)=v}D_v = \{x \in D \mid A(x) = v\}
  5. |Dv| / |D|子集样本占全集的比例,表示这个子集在总体中的权重。
    ∣Dv∣∣D∣=子集占比\frac{|D_v|}{|D|} = \text{子集占比}
  6. Σ所有取值子集的加权熵之和,即分裂后的加权混乱度。
    ∑v∈A∣Dv∣∣D∣⋅Ent(Dv)\sum_{v \in A} \frac{|D_v|}{|D|} \cdot \text{Ent}(D_v)

深度学习增强

老服务员工作久了,会形成一种难以言说的整体直觉:不等逐项推理,光是门口一瞥,就能感到“这位客人是来办生日宴的”。这种整体直觉,很像深度学习模型从海量数据中自动学到的“语义感觉”。它不再依赖人工列举规则,而是自己从数据中找出规律。

深度学习首先用“词嵌入”把每个词映射到一个高维向量,意思相近的词在向量空间中彼此靠近,于是“手机”和“电话”不再被看作两个无关的词。查询向量和文档向量都可以表示成这些词向量的加权组合,再通过余弦相似度来判断某篇文档是否匹配用户意图。更进一步,RNN能按顺序记住整句查询的上下文,注意力机制则能让模型聚焦在最重要的词上,比如“可退换”“包邮”这些决定交易意图的强信号。

深度学习模型的优势是不需要手工枚举特征,坏处是需要大量标注数据和算力。在意图识别任务中,它特别擅长处理长尾查询:用户写“这玩意儿能免费退吗”,传统词典完全懵,深度学习却能借助“免费”和“退”这些词的向量关联,判断出交易倾向。

如果说贝叶斯是“逐条线索打分”,深度学习就是“整体感知直接读心”。这种直觉虽然强大,但需要足够多的“阅人经验”来喂养——对应到工程上就是数据和算力。

sim(q,d)=q⃗⋅d⃗∥q⃗∥⋅∥d⃗∥\text{sim}(q, d) = \frac{\vec{q} \cdot \vec{d}}{\|\vec{q}\| \cdot \|\vec{d}\|}
通俗解释:两个向量的夹角余弦值越接近1,说明查询和内容在语义上“越聊得来”。
  1. q 向量查询词经过嵌入后的向量表示,可以理解为查询点在语义空间中的坐标。
    q⃗=emb(q1)+emb(q2)+⋯\vec{q} = \text{emb}(q_1) + \text{emb}(q_2) + \cdots
  2. d 向量候选结果文档或商品的向量表示,是目标在语义空间中的坐标。
    d⃗=emb(d1)+emb(d2)+⋯\vec{d} = \text{emb}(d_1) + \text{emb}(d_2) + \cdots
  3. q · d两个向量的点积,反映它们在方向上是否一致。
    q⃗⋅d⃗=∑kqk⋅dk\vec{q} \cdot \vec{d} = \sum_{k} q_k \cdot d_k
  4. ||q|| 和 ||d||向量的模,用于把结果归一化到 [-1, 1],排除文本长度干扰。
    ∥q⃗∥=∑kqk2\|\vec{q}\| = \sqrt{\sum_k q_k^2}
  5. 分数 > 0.8 通常视为语义相近工程上常用阈值筛选高匹配结果。
    sim∈[−1,1]\text{sim} \in [-1, 1]

工程落地实战

再厉害的服务员,如果餐厅没有标准流程,也无法规模化。真正成熟的餐厅会把服务经验固化成培训手册:怎么记录顾客偏好、怎么给顾客打标签、怎么根据不同场景安排座位。搜索引擎的工程化也是同理:意图识别不是实验室里的一个模型,而是一条稳定运转的数据流水线。

搜索意图识别系统的标准流程是:日志采集 → 数据标注 → 模型训练 → 阈值路由 → 上线回流。首先从搜索日志中拿到海量查询和点击数据;再由标注人员给查询打上意图标签;接着训练分类模型;上线时,如果模型对某个查询的置信度足够高,就派给专用结果页,否则退回通用搜索结果,避免误伤。

置信度通常由 sigmoid 函数把分类器得分映射到 0~1 之间。得分越高,置信度越接近 1;得分越低,置信度越接近 0。工程上会设定一个阈值,比如 0.7:大于 0.7 的查询才使用特定意图路由,小于 0.7 则走通用兜底,宁可保守也不冒险。

有了这本“培训手册”,服务员的经验才能从个人天赋变成餐厅的标准战斗力。同样,离线训练、在线路由、日志回流持续改进,意图识别才能在企业级场景稳定运转。

conf(z)=11+e−z\text{conf}(z) = \frac{1}{1 + e^{-z}}
通俗解释:sigmoid 把任意实数“压缩”到 0 到 1 之间,分数越高越接近 100% 信任。
  1. z分类器输出的原始得分,可以是线性组合或神经网络输出,范围可能是负无穷到正无穷。
    z=模型对某类意图的原始打分z = \text{模型对某类意图的原始打分}
  2. e−z自然指数函数的负数幂。z 很大时,e−z 趋近 0,整个分母逼近 1,conf 逼近 1。
    e−z=1eze^{-z} = \frac{1}{e^z}
  3. conf最终置信度,在 0 到 1 之间,表示模型对该意图判断的信心。
    conf∈(0,1)\text{conf} \in (0, 1)
  4. 阈值路由工程上把 conf > 0.7 的样本路由到专用意图页,低于阈值进入通用结果页,避免误伤。
    conf(z)>0.7⇒专用意图页\text{conf}(z) > 0.7 \Rightarrow \text{专用意图页}

效果评估体系

餐厅好不好,不能只看服务员自己的感觉,得看顾客满意度、翻台率、差评率这些硬指标。意图识别系统也需要一整套效果评估体系,来回答一个关键问题:“模型是不是真的变好了?”

离线评估常用的指标是精确率和召回率。精确率回答“判成交易意图的查询里,有多少真的想交易”;召回率回答“所有真正想交易的查询里,系统抓住了多少”。这两者往往此消彼长:阈值提高,精确率上升但召回率下降;阈值降低,召回率上升但精确率下降。所以通常合并成 F1 分数来统一衡量。

混淆矩阵则把四类意图的预测情况摊开成一张表,显示哪些类别互相混淆。比如“商业调查”经常被误判成“信息”,说明两者特征相近,需要补充更多区分性特征。最后还要做在线 A/B 实验:将部分真实流量切换到新模型,用点击率、转化率、跳出率等业务指标决定是否全量上线。

就像餐厅老板不会只听服务员自夸,而要看顾客复购率一样,意图模型的每一点优化,都要先有离线指标证明方向正确,再经过 A/B 实验证明真实收益,才能真正上线服务用户。

F1=2×Precision×RecallPrecision+RecallF1 = \frac{2 \times \text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}}
通俗解释:F1 是精确率和召回率的调和平均:只有两者都高,F1 才会高。
  1. Precision精确率 = 真正例 / (真正例 + 假正例),衡量“预测为正的样本中真实为正的比例”。
    Precision=TPTP+FP\text{Precision} = \frac{TP}{TP + FP}
  2. Recall召回率 = 真正例 / (真正例 + 假负例),衡量“真实为正的样本中被预测出来的比例”。
    Recall=TPTP+FN\text{Recall} = \frac{TP}{TP + FN}
  3. 2 × Precision × Recall分子是两者乘积的 2 倍,保证只有两者都大才得出大 F1。
    2⋅P⋅R2 \cdot P \cdot R
  4. 分母为两者之和实现“调和平均”的数学约束,惩罚严重偏科。
    P+RP + R

AI 应用场景

电商搜索导购

阶段:搜索排序与用户意图路由

解决的问题:用户搜“荣耀手机”,传统搜索引擎只按字面匹配返回参数页,结果用户又搜“荣耀手机评测”,说明第一次的意图判断错了。这类“想比价”的查询如果被当成“直接买”,会带来大量跳出和流失。意图识别系统将查询分为交易与商业调查两类:商业调查查询优先展示对比评测、口碑文章,交易查询则展示商品卡与价格提醒。

具体案例:某电商平台接入意图分类器后,“评测”“对比”“值不值”类查询的引导点击率提升22%,加购转化率提升9%。运营人员还发现,深夜时段的“手机推荐”查询更多是商业调查意图,于是增加了测评类内容位。

智能客服意图路由

阶段:企业级客服系统中的自然语言处理

解决的问题:用户发来一句“我流量不够用了”,听起来像是咨询,实际可能是投诉,也可能是想办个流量包。传统的客服机器人按关键词触发固定话术,经常答非所问。意图识别系统将用户消息分为“咨询”“投诉”“业务办理”三类,自动路由给对应业务线,显著减少人工转接。

具体案例:某运营商客服系统上线意图识别后,平均响应时长下降40%,投诉处理满意度提升12%。系统还从话术日志中提取新词,每周自动补充训练数据,持续提升分类准确率。

广告竞价投放策略

阶段:搜索广告系统的实时出价引擎

解决的问题:同一个词“蓝牙耳机”,信息意图的用户还在了解阶段,交易意图的用户已经准备下单。如果不加区分地对所有用户展示强促销广告,不仅浪费预算,还可能引起反感。意图模型实时给查询打分,交易意图提高出价并展示促销创意,信息意图则用品牌宣传占据用户心智。

具体案例:某广告平台按意图分段出价后,广告点击率提升15%,广告投入产出比(ROI)提升25%。同时,“信息意图”用户看过品牌内容后,后续搜索该品牌的转化率也明显提升。

Python 演示

python73 行
# -*- coding: utf-8 -*-# 搜索意图识别:朴素贝叶斯最小实现import refrom math import log  class IntentBayes(object):    """极简朴素贝叶斯搜索意图分类器"""     def __init__(self):        self.doc_count = {}    # 类别 -> 文档数(先验来源)        self.term_count = {}   # 类别 -> {词: 次数}        self.vocab = set()     # 全局词表        self.total_docs = 0    # 总文档数        self.total_terms = {}  # 类别 -> 总词数     def _tokenize(self, text):        # 简单分词:提取中英文和数字片段        return re.findall(r'[a-z0-9\u4e00-\u9fa5]+', text.lower())     def fit(self, texts, labels):        for text, label in zip(texts, labels):            self.doc_count[label] = self.doc_count.get(label, 0) + 1            self.total_docs += 1            if label not in self.term_count:                self.term_count[label] = {}                self.total_terms[label] = 0            for w in self._tokenize(text):                self.term_count[label][w] = self.term_count[label].get(w, 0) + 1                self.total_terms[label] += 1                if w not in self.vocab:                    self.vocab.add(w)     def _score(self, text, label):        prior = log(self.doc_count[label] / float(self.total_docs))        score = prior        # 拉普拉斯平滑,防止未登录词概率为零        for w in self._tokenize(text):            cnt = self.term_count[label].get(w, 0) + 1            denom = self.total_terms[label] + len(self.vocab)            score += log(cnt / float(denom))        return score     def predict(self, text):        best_label, best_score = None, float('-inf')        for label in self.doc_count:            s = self._score(text, label)            if s > best_score:                best_score = s                best_label = label        return best_label  if __name__ == '__main__':    samples = [        ('iphone 15 价格 优惠 下单 立减',       '交易'),        ('iphone 15 评测 对比 参数 值不值',    '商业调查'),        ('iphone 15 电池 续航 改善 方法 多久',  '信息'),        ('苹果官网 登录 首页 入口',             '导航'),        ('笔记本 打折 领券 秒杀 购买',          '交易'),        ('笔记本 性能 排行 哪款 适合',          '商业调查'),        ('笔记本 散热 清理 灰尘 教程',          '信息'),        ('联想官网 售后 客服 电话',             '导航'),    ]    texts = [x[0] for x in samples]    labels = [x[1] for x in samples]     bayes = IntentBayes()    bayes.fit(texts, labels)     test_queries = ['手机 优惠券 购买', '手机 评测 值得吗', '客服 电话 官网']    for q in test_queries:        print('查询: %s => 意图: %s' % (q, bayes.predict(q)))
目的:用不到 60 行实现一个朴素贝叶斯搜索意图分类器,演示“先验概率 + 词似然”的完整训练与预测流程。
  1. self.doc_count[label] = self.doc_count.get(label, 0) + 1按类别统计文档数,这是计算先验概率 P(c) 的原料,相当于服务员记录“今天来了几桌商务客”。
  2. self.term_count[label][w] = self.term_count[label].get(w, 0) + 1统计每个类别下每个词的出现次数,用于计算似然 P(词|意图)。
  3. prior = log(self.doc_count[label] / float(self.total_docs))取对数先验概率,把乘法变成加法,避免极小的连乘结果下溢。
  4. cnt = self.term_count[label].get(w, 0) + 1分子加一,这是拉普拉斯平滑,防止未在训练集中出现的词让整个乘积变成零。
  5. denom = self.total_terms[label] + len(self.vocab)分母加上词表大小,保证平滑后所有词的概率之和仍为 1。
  6. if s > best_score:遍历所有类别,选出对数后验最大的标签,等价于 argmax 操作。

常见误区

误区我以为只要提前写好“买”“价格”“领券”等关键词词典,匹配到哪个词就判断哪个意图,准确率也不会差到哪里去。

正解关键词词典确实简单直观,但中文查询极度稀疏且口语化。例如“这玩意儿能免费退吗”没有“买”也没有“价格”,却是明确的交易意图。真实系统用贝叶斯、决策树或深度学习整合行为、上下文、时间等多种信号,而不是单点匹配。就像服务员不会只凭顾客说了“随便”两个字就安排座位,还要看穿着和时间。

为何常见:词典法容易理解、可解释、调试方便,让人误以为企业级问题也能靠“查表”解决,初学者很容易陷入这个舒适区。

误区我觉得只要收集越来越多的搜索日志,一股脑扔给模型,准确率肯定越来越高。

正解搜索日志里充满了噪声:爬虫发出的机器查询、误点、广告垃圾词、同一条查询在不同场景下的相反标签。不清理直接训练,模型学到的是“假规律”。真实项目里必须先做去重、过滤低质量样本、人工交叉验证标签,数据质量永远比数量更重要。就像服务员培训时,如果不剔除错误的顾客记录,最后学到的可能是错误的服务习惯。

为何常见:直觉上“大数据 = 大智慧”,但忽略了真实业务数据的噪声比教科书数据大得多。

误区离线测试准确率 95%,部署上线效果肯定也差不了,不需要再验证了。

正解线下测试集来自历史数据,线上会遇到新词、长尾、时令热点。例如“苹果发布会”的意图会随时间迁移:发布前是信息查询,发布当天是交易,发布会结束又变回商业调查。因此必须用 A/B 实验验证线上真实点击率、转化率,才能决定是否全量上线。就像餐厅的招牌菜在试菜间评分再高,也要看真实顾客的复购率。

为何常见:离线评估方便、可复现,容易让人忽略线上环境的动态变化和用户反馈闭环。

误区一次搜索只要打一个标签,用户意图就是非黑即白的,多标签没有必要。

正解真实搜索中用户常常“既要想了解信息,又有购买倾向”。比如搜“咖啡机”的人,既想看看什么品牌好,也默认带有购买意愿。现在的系统普遍输出“意图分布”,在排序时按概率加权混合。就像顾客问“你们招牌咖啡怎么样”,服务员既会介绍口感,也会顺手把菜单递上,而不是二选一。

为何常见:标注数据大多是单标签格式,训练目标也是单标签分类,容易让大家误以为真实用户的意图也是单一确定的。

面试题

Q1. 用户搜索“微信官网下载”,最可能的搜索意图是什么?

单选题 · mid

  • A.导航意图——寻找特定网站入口← 正确答案
  • B.信息意图——了解微信的功能介绍
  • C.交易意图——直接购买相关账号商品
  • D.商业调查——对比微信与其他产品优劣

答案:A。搜“微信官网下载”时,用户带有明确目标:找到官方网站入口。导航意图的核心是“我要到达某个指定网站或页面”,而非获取新知识、完成购买或对比产品。就像顾客已经知道要去哪家店,只问服务员路怎么走。

Q2. 用户搜索“高血压日常注意事项”,最贴近哪一类意图?

单选题 · easy

  • A.导航意图,用户想找某个固定网站
  • B.信息意图,用户想获取健康相关知识← 正确答案
  • C.交易意图,用户想直接购买降压药品
  • D.商业调查,用户想对比各家医院优劣

答案:B。用户想看“高血压日常注意事项”,本质是获取知识,属于典型的信息意图。信息意图要求返回科普文章、健康指南等解释性内容。就像顾客问“这道菜怎么做”,服务员要递上菜谱,而不是带路或收银。

Q3. 下面哪些信号可以作为搜索意图识别的有效特征?

多选题 · easy

  • A.查询词的长度和关键词← 正确答案
  • B.用户设备型号与操作系统← 正确答案
  • C.同一会话内的前序查询← 正确答案
  • D.用户最近一周的天气情况

答案:ABC。查询词、设备型号、会话上下文都是意图识别的标准特征。比如先搜“苹果”再搜“13 价格”,可以锁定交易意图。而“最近一周的天气”与当前搜索意图没有稳定关联,不构成有效特征。就像服务员看穿着、时间和同行人数,而不会关心顾客鞋子颜色。

Q4. 朴素贝叶斯中“朴素”一词指的是什么?

单选题 · mid

  • A.假设各个查询词之间互相独立← 正确答案
  • B.假设各个意图类别之间互相独立
  • C.假设各条训练样本之间互相独立
  • D.假设所有类别的先验概率相等

答案:A。朴素贝叶斯的“朴素”在于假设特征(词)在给定类别条件下相互独立,这样连乘计算才成立。类别之间互相独立没有意义,样本独立是机器学习通用假设,先验相等也不是模型要求。就像服务员假设领带和公文包各自独立提供线索,不深究两者搭配的深层含义。

Q5. 在 TF-IDF 中,IDF(逆文档频率)的主要作用是什么?

单选题 · mid

  • A.降低常见词权重,突出罕见词的区分度← 正确答案
  • B.提高常见词权重,让高频词变得更重要
  • C.把一段文本转换成固定长度的向量
  • D.统计某个词在当前查询中出现的次数

答案:A。IDF 的思路是:词在越多文档中出现,区分能力越弱,权重应降低;罕见词 IDF 高,权重被放大。B 把方向颠倒,C 是嵌入层的工作,D 是词频 TF 的定义。就像菜单上的“招牌菜”只出现一次却至关重要,而“的”“了”家家都有,没有区分力。

Q6. 以下哪些是搜索意图识别技术的典型落地场景?

多选题 · mid

  • A.电商搜索结果按用户意图重新排序← 正确答案
  • B.客服机器人判断用户是投诉还是咨询← 正确答案
  • C.广告系统决定是否展示优惠券信息← 正确答案
  • D.天气预报模型预测明天的降雨概率

答案:ABC。电商排序、客服路由、广告出价都是意图识别的核心落地场景。天气预报属于气象时序预测,与用户查询背后的交易、信息等意图无关。就像餐厅服务员负责分桌、引座、推荐菜,但不负责预报明天的天气。

Q7. 决策树中“信息增益”的作用是什么?

单选题 · hard

  • A.衡量某个特征划分后数据纯度的提升幅度← 正确答案
  • B.衡量叶子节点包含样本数量的多少
  • C.计算模型在测试集上的整体准确率
  • D.统计每个词在语料库中出现的次数

答案:A。信息增益 = 分裂前熵 − 分裂后加权熵,数值越大说明该特征越能区分不同类别。B 是叶节点规模,C 是模型评估,D 是词频统计。就像服务员发现“是否带公文包”比“是否戴帽子”更能区分商务客和游客,所以优先用公文包来分。

Q8. 面对从未见过的新查询,意图识别冷启动有哪些有效策略?

多选题 · hard

  • A.结合用户历史会话补全上下文信息← 正确答案
  • B.使用词向量匹配语义相近的历史查询← 正确答案
  • C.将低置信度样本交给在线人工审核← 正确答案
  • D.直接丢弃未命中词典的查询样本

答案:ABC。冷启动的常用方案包括:用会话历史补全上下文、用词向量找相似历史查询、把低置信度样本送人工审核积累数据。直接丢弃未命中词典的查询,会严重拉低召回率,还损失了新词学习机会。就像服务员遇到生面孔,会先观察同伴和互动记录,而不是把客人晾在门口。

Q9. 关于搜索意图识别模型的评估,下列说法正确的是哪一项?

单选题 · hard

  • A.应同时关注精确率、召回率并计算 F1 分数← 正确答案
  • B.只看准确率即可,召回率不重要
  • C.训练集准确率可直接代表线上效果
  • D.用离线测试结果就能代替线上 A/B 实验

答案:A。意图类别往往分布不均衡,只看准确率会被多数类带偏,必须同时关注精确率与召回率,用 F1 综合。C 的过拟合风险和 D 的离线偏差也都是常见陷阱。就像餐厅既要看满意顾客比例,也要看差评率,单看翻台率会误判菜品质量。

Q10. 用户先搜“荣耀手机”,系统返回商品列表后用户没有点击,紧接着又搜“荣耀手机评测”。最合理的意图推测是什么?

单选题 · extreme

  • A.从交易意图转向商业调查意图← 正确答案
  • B.从信息意图转向导航意图
  • C.从商业调查转向交易意图
  • D.用户意图没有任何变化

答案:A。第一次搜“荣耀手机”被推荐商品列表,说明系统推测交易意图;但用户没点商品列表,反而追加“评测”,说明用户真实意图是购买前的对比决策,即商业调查。B、C 方向反了,D 无法解释两次搜索的差异。就像顾客先问服务员“推荐什么套餐”,又认真研究食材来源,显然在为是否下单做功课。