尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

搜索引擎用户满意度评估:从搜索日志到SUE指标的完整实战

搜索引擎用户满意度评估:从搜索日志到SUE指标的完整实战 简介《搜索引擎用户满意度评估》PDF是一份面向Web开发、互联网搜索与信息检索技术的研究型文献聚焦用户满意度这一搜索引擎性能评价的核心指标适合搜索引擎研发人员、高校科研人员及中高级Web技术爱好者阅读。压缩包内含1个PDF文件大小7.58MB内容为论文全文排版工整便于直接阅读与打印。目前已有88人浏览学习。文档源自清华大学计算机系的研究工作系统梳理了传统相关性评价方法的局限性分析了异质化搜索结果页SERPs中垂直结果的质量、样式和位置对用户满意度的影响并提出从鼠标移动模式中提取高质量特征来预测满意度的新策略实验证明该方法在异质搜索环境中优于现有方式。通过这份材料读者可掌握搜索满意度评估的相关性与用户感知关系、实验设计思路及基于行为数据的预测建模方法对优化搜索产品体验具有直接参考价值。1. 搜索引擎用户满意度评估别只盯着 CTR也不要把问卷当全部产品经理在周会上问“搜索引擎的满意度到底是涨了还是跌了”很多人第一反应是拉一版 CTR。CTR 上涨可能是摘要写得更夸张点进去并不是用户想要的内容CTR 下跌也可能是首屏结果变差了但用户懒得再翻第二页。搜索引擎用户满意度评估的核心任务是把用户的主观感受拆成可观测、可复现、可下钻的信号从点击、停留、翻页和主动反馈里还原真实偏好最终形成一份能被评审会接受的 PDF 报告。这套评估方案不仅适用于通用网页搜索也适用于全文搜索引擎、网盘搜索引擎等垂直场景。搜索算法工程师、推荐系统工程师和用户研究员都能从中找到可以直接复用的指标口径和统计方法。2. 满意度指标设计把主观感受翻译成可计算的中间指标2.1 显式反馈与隐式行为怎样让两者互相校准显式反馈是用户主动表达的判断例如“这个结果有用吗”按钮、星级评分或问卷。信噪比高不受位置偏差干扰缺点也很明显收集率低通常只有百分之几的用户愿意点击且带有幸存者偏差特别生气和特别满意的用户更倾向反馈中间沉默的大多数消失了。隐式行为才是搜索引擎里覆盖率最高的证据。一次点击代表用户认为某个结果有吸引力停留 30 秒以上说明内容接住了意图点击后立刻返回搜索页并换词重搜说明刚才那次点击基本是失败的。行为数据噪声大但可以通过规则统一打标。所以评估的第一原则是显式反馈用来校验规则和做抽样审计隐式行为用来全量打标。两者结合而不是互相替代。如果一个点击停留 50 秒但用户随后点了踩说明该会话不能算满意反之如果用户点击“没问题”但秒退也要在报告中打上异常标记。2.2 满意度指标表从点击、翻页到长期留存下面这组指标是我在搜索引擎满意度评估里最常用到的。它们的共同点是都能从搜索日志算出来且报告读者不需要太多背景就能看懂。指标计算口径使用场景展示点击率 CTR点击次数 / 展示次数衡量结果吸引力和位置效应不作为满意度主指标满意点击率 SCTR满意点击次数 / 总点击次数满意度核心指标依赖停留时间与回跳行为首条满意率点击了首条且该点击为满意的会话数 / 有首条点击的会话数首条结果权重最高单独监控无点击会话率0 点击会话数 / 会话总数结果完全不吸引或查询语句有问题翻页率翻到第 2 页及以上的会话数 / 会话数越高代表首屏满足能力越弱无结果率返回零结果的查询次数 / 查询总次数索引覆盖问题单独汇报次日回访率次日有搜索行为的新用户数 / 当日新用户数长期满意度信号适合月报单看任何一个指标都会误导。翻页率上涨可能是首屏结果变差也可能是用户在做精确资料核对故意多翻CTR 上涨可能是标题党变得更多。因此需要把多个指标合成为一个指数但合成之前要先确定“满意点击”的判定规则。2.3 用 SQL 把“满意”定义为可执行规则业内最常见的满意点击判定是点击后停留时间大于阈值且没有在同一会话内快速返回搜索页。阈值一般取 30 秒或 60 秒。导航类结果可以直接进入目标页停留短也属于正常因此要先按 query_type 区分。-- 以会话为单位计算满意点击率 WITH click_events AS ( SELECT session_id, query, query_type, click_position, dwell_time_sec, CASE WHEN follow_return_search_sec 30 THEN 1 ELSE 0 END AS is_quick_return FROM search_event_log WHERE event_type click ), satisfied AS ( SELECT *, CASE WHEN dwell_time_sec 30 AND is_quick_return 0 THEN 1 ELSE 0 END AS is_satisfied FROM click_events ) SELECT query_type, COUNT(*) AS total_clicks, AVG(is_satisfied) AS satisfied_click_rate FROM satisfied GROUP BY query_type;这段 SQL 的逻辑分两步先计算每个点击后 30 秒内是否发生回跳再把“停留 30 秒且未回跳”标记为满意。dwell_time_sec 30和follow_return_search_sec 30是两个核心参数前一个要根据内容深浅调整后一个基本不需要动。如果日志里没有follow_return_search_sec可以用“该 session 内下一个搜索行为时间戳与点击时间差”来替代。2.4 组成满意度指数时权重怎么给才不拍脑袋把一个指标集合成一个数值最简单的是加权平均。权重来源有三种常见路径专家打分、历史实验回归、业务目标对齐。专家打分适合冷启动。例如让搜索产品、算法和用研各出 5 个权重方案取平均值后归一化。历史实验回归是更省力的做法拉出过去三个月所有搜索相关 A/B 实验的胜负结果用逻辑回归拟合各底层指标对实验结论的贡献把标准回归系数的绝对值归一化后作为权重。业务目标对齐则要求团队先回答“这个季度优先提升什么”如果目标是提升新用户首次搜索体验就应该把首条满意率和无点击会话率权重调高。权重定下来之后建议每季度重新做一次校准而不是一直沿用。新功能上线后某些指标可能被优化得失去区分度例如满意点击率普遍超过 80% 时它对改进的敏感度就会下降。2.5 常见误用平均停留时间、CTR 漂移和位置偏差我见过最多的三个误用。第一直接看平均停留时间认为停留越长越满意。停留时间分布严重长尾极少数阅读长文的用户会把均值拉高应该用中位数或 P75。第二把 CTR 放进满意度指数后不做位置归一化。Top1 的点击率高是位置带来的不是结果质量带来的。如果某个改版让 Top1 的标题更醒目CTR 上涨很容易掩盖 SCTR 下跌。第三把无点击会话一律算作不满意。用户可能通过摘要就满足了根本没有点击必要。建议在日志中单独记录“仅看摘要并结束会话”的比例作为中性地带。3. 从搜索日志到满意度分Python 实战与置信区间3.1 评估所用的搜索日志字段清单线上搜索日志通常包含曝光、点击、转化三张表做评估前要先 join 成一张事件宽表。以下是我在项目里最依赖的字段字段类型说明event_time时间戳用户行为发生时间session_id字符串一次搜索会话的唯一 IDuser_id字符串用户标识用于分层抽样query字符串用户输入query_type字符串网页、图片、网盘等资源类型shown_positions数组每次曝光的结果位置clicked_positions数组点击过的结果位置dwell_time_sec数值点击后停留秒数return_within_30s布尔点击后 30 秒内是否重新搜索is_conversion布尔会话是否完成目标转化如果 click 事件和 search 事件分离可以把 search-event 表和 click-event 表按 session_id 做左连接再按 click 事件打标。下面直接以规整好的 DataFrame 为例方便你快速套用。3.2 会话级指标计算的 Python 实现import pandas as pd import numpy as np def mark_satisfied_clicks(df, dwell_min30, return_max30): 给每条点击记录打上满意标记。 dwell_min: 最小停留秒数低于该值判定为不满意 return_max: 点击后多少秒内重新搜索判定为回跳 df df.copy() df[is_satisfied] ( (df[dwell_time_sec] dwell_min) ~df[return_within_30s] ).astype(int) return df def session_satisfaction_agg(df): 输入已打上 is_satisfied 标记的点击流水 输出每个 session 的满意点击数与满意点击率 df df.copy() agg df.groupby(session_id).agg( total_clicks(click_position, size), satisfied_clicks(is_satisfied, sum), has_conversion(is_conversion, max), query(query, first), query_type(query_type, first), ) agg[sctr] agg[satisfied_clicks] / agg[total_clicks] return agg.reset_index() # 实际使用 # df pd.read_parquet(search_log.parquet) # df mark_satisfied_clicks(df, dwell_min30, return_max30) # session_df session_satisfaction_agg(df)mark_satisfied_clicks中的两个参数建议放到配置文件里每次调整都要留下记录。dwell_min的默认值按资讯站点习惯设成 30如果你的业务大多是查电话、查天气等即时满足场景可以改为 10 到 15 秒。return_max保持 30 秒即可过长会把偶然的二次搜索也当成回跳。3.3 加权满意度指数 SUE 的归一化与计算会话级指标出来后通常按周聚合然后做 min-max 归一化。归一化的上下界不能直接用当前样本的 max 和 min否则这周数字高下周数字会被顶高报告里数字波动失真。我一般取过去 13 周该指标的 P5 和 P95 作为固定上下界。def minmax(series, floorNone, ceilNone): 归一化到 0-1带平滑项防止除零 floor series.quantile(0.05) if floor is None else floor ceil series.quantile(0.95) if ceil is None else ceil return (series - floor) / (ceil - floor 1e-9) def compute_sue(weekly_metrics, weights): weekly_metrics: 按周聚合的指标 DataFrame weights: dict键为指标名值为权重权重之和应为 1 normalized pd.DataFrame(indexweekly_metrics.index) for name in weights: normalized[name] minmax(weekly_metrics[name]) sue pd.Series(0.0, indexweekly_metrics.index) for name, w in weights.items(): sue w * normalized[name] return suecompute_sue的返回值是每周一个满意度指数。这里要特别强调权重字典里的顺序不会影响结果但所有指标的方向必须一致。例如翻页率是无序指标翻页越多满意度越差需要先取负值或1 - value再参与归一化否则会出现“翻页越多 SUE 越高”的倒挂。3.4 Bootstrap 置信区间重采样不能破坏会话结构只有 SUE 的点估计很难判断两周之间 0.02 的差异是真实波动还是随机噪声。用 bootstrap 可以对会话样本重采样得到置信区间。def bootstrap_ci(session_df, weights, metric_fn, n_boot2000, seed202405): session_df: 会话级数据 weights: 指标权重 metric_fn: 输入 session_df 输出周度 SUE 的函数 rng np.random.default_rng(seed) user_ids session_df[user_id].unique() n_users len(user_ids) boot_sue [] for _ in range(n_boot): sample_users rng.choice(user_ids, sizen_users, replaceTrue) sample session_df[session_df[user_id].isin(sample_users)] if sample.empty: continue boot_sue.append(metric_fn(sample, weights)) return np.percentile(boot_sue, [2.5, 97.5])注意这里抽样单位是用户而不是 session。同一个用户多次搜索之间存在强相关直接重采样 session 会低估方差导致置信区间假性收紧。n_boot2000在百万级用户量下仍然很快如果样本量特别大可以调到 1000seed固定后报告可以复现这点在评审时很重要。3.5 下钻定位满意度变化来源整体 SUE 下跌 0.03产品经理第一反应是“哪里崩了”。用多维下钻可以快速缩小范围。常见维度有 query_type、设备端、新老用户、搜索入口。def drill_down_sue(session_df, weights, dimquery_type): result [] for value in session_df[dim].unique(): sub session_df[session_df[dim] value].copy() # 如果只用均值衡量要记录样本量避免小样本抖动 if len(sub) 100: continue week_col sub[event_time].dt.to_period(W) weekly sub.groupby(week_col).agg( sctr(sctr, mean), no_click_rate(no_click, mean), ) sue_series compute_sue(weekly, weights) result.append({ dim: value, sue_mean: sue_series.mean(), sessions: len(sub), }) return pd.DataFrame(result)这段代码把每个 query_type 单独算一遍 SUE并留下sessions字段。线上实际使用时要加上环比差和置信区间只靠一个值容易误判。特别是网盘搜索引擎这类资源型场景同一个 query 可能对应多种资源格式建议再增加资源的文件类型维度和结果页平均首次加载时间。4. 从数字到 PDF自动化输出满意度评估报告4.1 报告结构先回答“变没变”再回答“为什么”一份能被评审会接纳的满意度 PDF 报告结构可以固定为四个部分结论、趋势、下钻、建议。结论放在第一页直接写“满意度指数未显著变化”或“满意度指数下降 3%主要来自移动端无结果率上升”不要在前面放一堆方法说明。方法能放进附录就行。我会在报告里强制要求画一个带置信区间的 SUE 趋势图并且用误差棒标出区间。没有误差棒的数字别人很难判断波动。4.2 用 matplotlib 和 PdfPages 自动输出多页 PDF生产环境可以用 reportlab 或 weasyprint 做复杂排版但快速生成周报时matplotlib 自带的 PdfPages 更轻量只需要一个 Python 脚本就能把趋势图、结论文本和明细表合进同一个 PDF。import matplotlib.pyplot as plt import numpy as np from matplotlib.backends.backend_pdf import PdfPages weeks [W01, W02, W03, W04] sue [0.62, 0.64, 0.63, 0.65] ci [(0.59, 0.65), (0.61, 0.67), (0.60, 0.66), (0.62, 0.68)] yerr_low [m - lo for m, (lo, hi) in zip(sue, ci)] yerr_high [hi - m for m, (lo, hi) in zip(sue, ci)] with PdfPages(search_user_satisfaction_report.pdf) as pdf: fig, ax plt.subplots(figsize(8, 3.5)) ax.errorbar(weeks, sue, yerr[yerr_low, yerr_high], fmt-o, capsize4, color#1f77b4) ax.axhline(0.64, colorgray, linestyle--, linewidth0.8) ax.set_title(Search User Satisfaction Evaluation) ax.set_ylabel(SUE) ax.grid(alpha0.3) pdf.savefig(fig) plt.close(fig) fig2, ax2 plt.subplots(figsize(8, 5)) ax2.axis(off) ax2.text(0.05, 0.8, 结论W04 SUE 为 0.65较 W01 的 0.62 上升 0.03。 置信区间存在重叠当前不能判定为统计显著改善。, vatop, fontsize12) pdf.savefig(fig2) plt.close(fig2)这段代码用errorbar把置信区间画成误差棒第二页用纯文本页写结论。关键参数是yerr的低位和高位数组它们必须来自 bootstrap 结果不能手写到代码里。axhline(0.64)是往季基线有了这条线读者一眼就能看出本周是否超过历史水位。4.3 一个关键技巧误差棒会说话但别让它带节奏最后落一个容易被忽视的细节当你要对比两个版本的满意度时不要只画两条独立的误差棒要画“差值的置信区间”。如果差值置信区间跨过 0就不要在结论里写“有提升”。否则评审会上很可能被资深的用研同学问倒你这两个置信区间有大量重叠凭什么说效果好用 bootstrap 对两个版本分别采样再计算差值分布得到差值的 2.5% 和 97.5% 分位点。只有下限大于 0才能下“显著提升”的结论。这个逻辑同样适用于不同 query_type 之间的对比。写报告时把差值置信区间画成横向条形图每行一个维度区间不跨 0 的维度高亮出来。这样即使不看文字管理层也能快速看出真正有差异的点在哪里。本文还有配套的精品资源点击获取
返回列表