夜市里有个叫老周的小吃摊老板,他不用菜单,永远能一眼认出熟客:小王无辣不欢,阿丽偏爱甜口,老张深夜收工后总要点一份烤腰子。老周的“推荐心得”朴素得很——记得每个人的口味,发现口味相近的客人,再把他们爱吃的菜端给还没尝过的人。可夜市一天几千人路过,光靠脑子记,他最多照顾得了三十个熟客。 游戏公司面对的“夜市”更大:几千万玩家、上万件道具,每秒钟都有人在登录、在组队、在犹豫买不买。AI推荐系统就是那个能记住所有熟客的“超级老周”——它从玩家的行为数据里学会每个人的口味,找出“口味相近的神队友”,再在合适的时机把合适的道具端到玩家面前。本文要讲的,就是这位“超级老周”怎么练成:从协同过滤的老手艺,到深度学习的火眼金睛,再到新菜上架的冷启动、公平试吃的A/B测试,最后是菜单的持续改良。理解了这套逻辑,你就掌握了游戏运营里最值钱的提款机与留客器——它既能让道具收入飞涨,也能和反作弊风控联动,把福利投给真玩家、挡掉工作室小号。
掌握游戏推荐系统的完整链路,是 AI 游戏运营工程师的核心竞争力——它直接决定道具收入、玩家留存与反作弊风控的联动效率。
目录
可视化演示
演示协同过滤物品相似度推荐计算、Wide&Deep深度推荐模型记忆泛化融合、A/B测试流量分割与冷启动三阶段策略三大模式交互动画。
本节配有交互动效(进入视口后自动加载,约 3KB)。
协同过滤物品相似度推荐 计算道具间购买共现相似度构建物品相似矩阵 基于已购道具最近邻推荐高相似度物品 sim(i,j) = |U_i ∩ U_j| / √(|U_i|·|U_j|) Item-CF无需用户画像适合道具推荐场景
推荐系统概述:从“熟人记忆”到数据画像
老周在小吃摊上练就一身“人肉推荐”的本事:小王一擦汗他就递上冰可乐,阿丽加班到深夜他就把辣度减半。老周的推荐从来不是“啥都端上来”,而是看人、看时间、看状态。游戏里的推荐系统也是一样——它的输入不是单一道具,而是“谁、在什么时候、想干什么”。
术语上,我们把老周的观察写成三元组:玩家特征、道具特征、上下文特征。推荐模型把这些输入变成一个小数,表示“玩家对道具的喜爱程度”。得分越高,道具在商城弹窗里就排得越靠前。游戏里最典型的应用场景,就是内购商城的“每日推荐位”与好友匹配的“可能认识的人”——前者卖道具,后者留玩家,都是推荐系统的生意。
一套完整的推荐流程要从“海选”走到“定榜”。首先是召回:从几万件道具里快速捞回几百个候选,避免模型在全部道具上做精细计算;然后是排序:用模型给候选精确打分;最后是重排:考虑多样性、新道具曝光、风控约束,把列表再“调理”一遍。模型用历史日志离线训练,玩家打开商城的几百毫秒内完成在线预测,这就是离线与在线的分工。
老周的“眼力”其实就是召回加排序:他先扫一圈摊上有什么新鲜食材,再根据面前这位客人定夺——这是召回;最后掂量一下火候、分量和摆盘——这是重排。把这三步交给机器,夜市再大,老周也照顾得过来。
- 符号 uu 代表“哪一个玩家”,在游戏里对应玩家 ID、等级、付费档位等画像。
- 符号 ii 代表“哪一件道具”,来自全部道具集合。
- 特征向量 x三个加粗的向量,相当于老周眼里的“人、菜、时辰”。
- 模型 f 与输出f 是打分函数,输出偏好分数,分数越高越该被推荐。
协同过滤算法:让口味相投的人替你试菜
老周有个偷懒又聪明的推荐新菜的办法:看熟客。小王爱吃辣,老周就把同样无辣不欢的老张爱吃的烤串端给小王。他甚至不必研究菜里放了什么——只管“谁和谁口味像”。这就是协同过滤(Collaborative Filtering)的质朴直觉:物以类聚,人以群分,口味相似的人会喜欢相似的东西。
正式地说,协同过滤分两派。用户协同过滤(UserCF)先找与目标玩家口味最像的一群“邻居”,再把他们喜欢的道具推荐过来;物品协同过滤(ItemCF)反过来,先计算道具之间的相似度——“买过这把剑的人也买过这面盾”,然后用玩家买过的道具去找相似道具。在手游内购场景,道具数量通常比玩家少且变化慢,ItemCF 往往更稳定;而对好友匹配这种讲究“玩得到一起”的场景,UserCF 更顺手。
计算相似度最常用的工具是余弦相似度。把玩家对每个道具的打分看成高维空间里的一个向量,两个向量夹角的余弦值越接近 1,口味越一致。有了相似度,就能预测玩家对没尝过道具的评分:先找 K 个近邻,用他们的评分加权平均,再按玩家自己的平均口味基准修正——毕竟有人慷慨、习惯打高分,有人苛刻、从不给五星。
老周向小王推荐老张爱吃的烤串,靠的正是 UserCF;向买过辣椒酱的客人推荐同品牌的孜然粉,就是 ItemCF。协同过滤的最大优点,是不需要懂“菜品成分”,只要你身边的人替你试过菜就行。
- 共同品尝集合 I_uv两位玩家都打过分的道具集合,等于评分向量的“重叠部分”。
- 评分 r_ui玩家 u 对道具 i 的评分,游戏里常用点击、购买、充值金额换算成 1 到 5 分。
- 余弦相似度 sim(u,v)把两个评分向量夹角的余弦当作口味距离,越接近 1 越相似。
- 邻居集合 N(u)与玩家 u 相似度最高的 K 个玩家。
- 基准口味与加权预测先减去每人打分习惯的偏差,再加回目标玩家的基准,得到最终预测分。
深度推荐模型:练就“火眼金睛”
单纯靠“模仿邻居”有天花板:新玩家还没有邻居,新道具还没有人尝过。老周后来练出了一双火眼金睛——不用问别人,光看客人这身打扮、说话的嗓音、今天的天气,就能猜个八九不离十。深度推荐模型做的正是这件事:把玩家、道具、场景的原始特征直接“看”进去,学出一个复杂的打分函数。
第一步是特征工程。把离散特征(玩家性别、道具品类、设备型号)做 one-hot 编码或嵌入向量,再拼上连续特征(等级、在线时长、历史付费额)。难点在于交叉特征:“爱玩刺客”和“周三晚高峰上线”单独看都没什么,组合起来却强烈预示他会买打折皮肤。传统人工组合特征费时费力,因子分解机(FM)提出用两个隐向量的内积自动捕捉二阶交叉。
在此基础上,DeepFM 把 FM 和深度神经网络拼接:FM 负责低阶特征组合,Deep 部分负责高阶非线性组合,两部分共享原始特征输入,一起训练。线上预估时,模型输出经过 sigmoid 变成 0 到 1 的购买概率,直接作为排序分数——这就是“火眼金睛”的投入使用。
老周这双“火眼金睛”,就是这样一层一层练出来的:先看单品相,再看搭配,最后看整体气质。放到游戏里,就是特征、交叉、深度网络层层递进,最终在玩家付款前的零点几秒内给出判断。
- sigmoid 激活 σ把任意实数压到 0 到 1 之间,当作购买概率。
- 全局偏置 w0所有道具的平均热度,类似夜市的整体客流大小。
- 一阶项 wi xi每个特征单独的贡献,比如“价格低”本身就会提高购买率。
- 二阶交叉项特征 i 与 j 的隐向量内积乘上特征值,自动挖掘“打包组合”的魔力。
冷启动应对:新客人来了怎么办
新玩家第一次进游戏,老周完全不知道他爱吃甜还是辣;新道具上架,没有任何人试吃过。这就是冷启动:缺乏行为数据,一切相似度计算都失灵。老周的办法很朴素——先搭话:问两句家乡在哪、口味偏咸偏淡,再端一小碟招牌菜试探。接到游戏里,就是用“内容特征”和“探索策略”破冰。
对新道具,内容特征兜底:用品类、价格、美术风格、数值强度等属性,在已有道具里找“长得像”的老道具,把新道具映射到老道具的推荐位上。对新玩家,则可以用注册时选择的偏好标签、新手问卷、首登设备信息等做初始画像。但兜底终究是“猜”,更重要的是给不确定性付学费——探索。
探索与利用的权衡是推荐系统的做人哲学:一直推荐确定好卖的热门(利用),新道具永远没机会证明自己;一直试新(探索),又浪费短期收益。工程上常用 UCB(置信上界)这类多臂老虎机算法,给每个道具算一个“潜力分”:曝光越少,潜力分越高,从而获得更多试吃机会。风控场景里也可以反过来用这个分数——给工作室小号压曝光,给真人新玩家送探索流量。
老周给新菜每桌只送一小碟,既不让客人吃腻,又能快速收集反馈——这就是游戏里“新道具送体验券”的策略。探索、反馈、再决策,冷启动的坑,靠的是有纪律的“试错”,而不是瞎猜。
- 当前口碑道具 i 目前收到的平均评价值,相当于老周听到的前几个试吃反馈。
- 总服务次数 N系统到目前为止推荐出去的次数总和,代表“夜市累计接待了多少客人”。
- 单品曝光 n_i道具 i 被推荐试吃的次数,越小说明越“陌生”。
- 探索系数 c控制“爱尝鲜”的程度,c 越大越敢把没卖过的新菜端上桌。
A/B测试评估:试吃台上的公平对决
老周想换菜单:新配方比老配方更好吗?他不会凭感觉拍板,而是同一道菜分两锅,请两队客人试吃,记下哪锅被吃得更干净。这就是 A/B 测试:把玩家随机分成两组,A 组用旧推荐策略,B 组用新策略,其余条件完全一致,最后对比指标。
实验设计的关键有三条。第一,分流要随机且互不干扰,避免“高付费玩家恰好被分到 B 组”造成偏差,通常按用户 ID 或设备哈希分流;第二,样本量要够大,内购推荐的样本量不够时,差异很容易被随机波动淹没;第三,观察期要覆盖完整业务周期——礼包推荐至少看 7 天付费行为,不能只看 3 小时。指标口径上,内购推荐的核心看购买转化率、人均付费、ARPU,辅助看弹窗关闭率与次日留存,防止“赚了钱却丢了人”。
统计上,我们比较两组转化率,用 z 检验判断差异是否显著。若 z 的绝对值超过 1.96(对应 95% 置信水平),就认为差异不是随机波动;同时用 lift(提升度)表示相对提升幅度,方便向运营同学解释“新策略比旧策略好多少”。上线节奏上,先用 10% 流量灰度跑两天,确认没有事故再逐步放量到全量。
老周的两锅试吃,最后还要看“哪锅客人回头的多”——对应游戏里的留存指标。灰度发布就是先把新策略放到 10% 的玩家身上跑两天,确认没翻车再全量。夜市换菜单要小步快跑,推荐系统上线也一样。
- 转化率 p̂A 与 p̂BA、B 两组中实际购买人数占总人数的比例。
- 合并估计 p̂把两组数据合起来算一个总体转化率,用于估计抽样误差。
- z 统计量差异除以标准误,衡量“信号”与“噪声”的比值。
- 提升度 lift相对于对照组,实验组的转化率提升了百分之多少。
效果优化经验:菜单的持续迭代
老周的菜单从不安于现状:每周记下哪些菜卖光、哪些菜被剩下,再微调配料和定价。推荐系统的优化也是两套仪表盘。离线评估在历史日志上快速验证模型:AUC 衡量排序能力——随机猜是 0.5,越接近 1 越好;GAUC 把 AUC 按玩家分组加权,防止“头部玩家刷高指标”。
在线指标才是最终裁判:点击率、购买转化率、人均付费、次日留存。二者经常背离——离线 AUC 涨了,线上付费率却跌了,常见原因是模型把流量集中推给高付费玩家,伤害了长尾玩家的体验。因此需要多目标权衡:把付费率、留存、体验评分合成一个加权目标,或给每个目标设底线约束,坚决避免“杀鸡取卵”式推荐。迭代节奏上,按“周级小迭代 + 月级大迭代”前进,每次只改一个变量,出了问题能快速定位。
老周发现烤冷面最近点的人多,不是因为好吃,而是因为新来的师傅手快出锅快——他立刻分两条线考核“口味分”和“出餐速度”。推荐系统也要分开考核离线能力与在线体验,配合风控分数,把福利资源投给真玩家、撤下工作室小号。菜单持续迭代,生意才能长红。
- AUC_u单个玩家 u 的兴趣排序能力,衡量“正样本排在负样本前面”的概率。
- 曝光权重 n_u玩家 u 获得的推荐曝光次数,曝光越多,话语权越大。
- 加权平均把每个玩家的 AUC 按曝光量加权聚合,得到全局 GAUC。
AI 应用场景
手游内购礼包推荐
阶段:召回与排序(在线推荐)
解决的问题:传统做法是运营配置固定礼包、全服一视同仁,转化率低且反复打扰非付费玩家。AI 通过协同过滤加深度模型预估每个玩家的购买概率,按玩家画像生成差异化礼包与弹窗时机——就像老周给不同熟客端上不同的菜,而不是全场发同一张菜单。
具体案例:某卡牌手游对回归玩家使用“首充双倍 + 角色碎片”组合,模型预测该玩家偏好某角色,就推送对应碎片礼包,付费转化率提升 18%;同时对零付费玩家减少弹窗打扰,次留反而提升。
好友匹配与开黑组队
阶段:离线计算相似度 + 在线召回归并
解决的问题:按段位匹配容易“强带弱”体验差。用户协同过滤通过活跃时段、游戏风格、付费习惯计算玩家相似度,找出“玩得到一起”的人——这正是老周把口味相投的熟客拼到一桌的智慧。
具体案例:某 MOBA 游戏用 UserCF 计算玩家相似度,把刚输掉排位、情绪低谷且活跃时段相近的玩家互邀组队,组队后对局时长与次日留存双双提升。
反作弊联动的人群触达
阶段:风控打分 + 推荐策略联动
解决的问题:工作室小号大量消耗福利资源,真人新玩家却领不到新手礼包。把风控分数作为特征注入推荐排序,降低异常账号的福利曝光,同时给真人新玩家增加探索流量——相当于老周一眼认出“蹭吃蹭喝的托儿”,把试吃小碟只递给真正的食客。
具体案例:某 MMO 对风控评分超过阈值的账号屏蔽新手礼包曝光,异常账号不再制造虚高数据,真实用户的新手礼包领取率上升 22%,同时风控拦截量下降 15%。
Python 演示
# 基于用户的协同过滤(UserCF)推荐器class UserCF: def __init__(self, ratings): self.ratings = ratings # {用户: {物品: 评分}} self.users = list(ratings.keys()) def cos_sim(self, u, v): """计算两个用户评分向量的余弦相似度""" common = set(self.ratings[u]) & set(self.ratings[v]) if not common: return 0.0 dot = sum(self.ratings[u][i] * self.ratings[v][i] for i in common) norm_u = sum(self.ratings[u][i] ** 2 for i in self.ratings[u]) ** 0.5 norm_v = sum(self.ratings[v][i] ** 2 for i in self.ratings[v]) ** 0.5 if norm_u == 0 or norm_v == 0: return 0.0 return dot / (norm_u * norm_v) def recommend(self, user, top_k=2): """给目标用户推荐 top_k 个未购买过的物品""" scores = {} for other in self.users: if other == user: continue sim = self.cos_sim(user, other) if sim <= 0: continue for item, rating in self.ratings[other].items(): if item not in self.ratings[user]: scores[item] = scores.get(item, 0.0) + sim * rating ranked = sorted(scores.items(), key=lambda kv: kv[1], reverse=True) return [item for item, _ in ranked[:top_k]] if __name__ == "__main__": # 模拟三位玩家的道具评分:5分最爱,1分不喜欢 data = { "alice": {"sword": 5, "shield": 4, "potion": 1}, "bob": {"sword": 4, "shield": 5, "potion": 2}, "carol": {"sword": 1, "potion": 5, "boots": 4}, } cf = UserCF(data) for user in data: print(user, "->", cf.recommend(user))
common = set(self.ratings[u]) & set(self.ratings[v])取两个人共同打过分、也就是“一起吃过”的道具集合。dot = sum(...)分子:共同道具的评分乘积和,衡量两人口味叠加的强度。norm_u = sum(...) ** 0.5分母:评分向量的长度,用于归一化消除打分习惯差异。if sim <= 0: continue过滤掉不相似甚至相反的邻居,避免噪声干扰。scores[item] = scores.get(item, 0.0) + sim * rating用相似度做权重,累加邻居对候选道具的评分。ranked = sorted(...)按预测分从高到低排序,取前 top_k 个道具。
常见误区
误区我觉得现在做推荐系统,不上 DeepFM 这类深度模型就等于落后,协同过滤是老古董,实战里没人再用。
正解协同过滤依然是工业界的强力基线:数据稀疏度可控时,UserCF/ItemCF 训练快、可解释性强,还常作为深度模型的候选召回手段。深度模型擅长吃海量特征,但需要数据、算力和特征工程,小团队一上来就上 DeepFM 反而容易过拟合。老周先用熟客口碑就能撑起生意,不必一上来就上“米其林后厨”。
为何常见:深度学习在媒体上被神化,论文又总是新模型对比旧基线,容易让人误以为“旧 = 废”。
误区我认为推荐系统的目标就是把高价值礼包怼到每个玩家面前,客单价越高越好。
正解推荐是在匹配玩家当下的偏好与场景。给零氪玩家推 648 礼包只会让他关弹窗甚至流失。正确做法是分层定价、按画像推荐合适档位,用长期留存换总付费。推荐帮玩家找到“想吃的那道菜”,而不是“最贵的招牌菜”。
为何常见:运营 KPI 常盯着客单价和收入,容易把“贵”误当成“好”。
误区新玩家没有数据,我把全服最热门的道具推荐给他总没错吧,总比什么都不推强。
正解全推热门只解决了“有内容可推”,没解决“适合谁”。热门道具转化率高往往因为基数大,对不同画像的玩家推同一热门,会浪费曝光并积累错误反馈。正确做法是内容特征兜底个性化,再配合探索策略给小众但匹配的道具机会——老周对新客人也会先问两句口味,而不是直接上最辣的菜。
为何常见:热门榜是人人可见、最容易想到的“兜底答案”,但个性化才是推荐与运营位的本质区别。
误区新模型离线 AUC 比老模型高了 0.03,我直接全量上线,指标涨了肯定赚钱。
正解离线指标衡量的是在历史数据上的拟合与排序能力,不等于线上收益。线上有数据分布漂移、延迟、用户反馈回路,旧模型可能更稳定。必须经过小流量 A/B 测试,验证在线转化率与留存显著提升后,再灰度、全量。离线提升是“厨师的自我感觉”,在线数据才是“客人的买单量”。
为何常见:离线实验快、成本低,容易被单一数值上涨冲昏头,忽略了离线与在线的鸿沟。
误区组队系统不就是把段位差不多的玩家匹配在一起吗?胜率差不多体验就差不多。
正解段位只是“实力维度”。玩得到一起还需要活跃时段一致、游戏风格互补(有人爱输出有人爱辅助)、付费节奏相近。用用户协同过滤算“行为相似度”,比单纯按段位匹配能显著提升组队后的对局时长与次日留存。就像老周拼桌,不光看食量,还看吃辣程度和吃饭节奏。
为何常见:段位是玩家最显眼的标签,大家习惯用“最简单可见的特征”代替“真正有效的特征”。
面试题
Q1. 协同过滤推荐的核心思想是什么?
- A.分析物品本身的颜色和价格属性
- B.利用相似用户或相似物品的行为预测偏好← 正确答案
- C.只统计所有道具的全局点击量
- D.完全依赖运营人工配置的推荐位
答案:B。协同过滤不分析物品属性,而是借“相似用户/相似物品的行为”做推荐,就像老周看小王爱辣、就把老张爱吃的烤串端过去。A 属于内容推荐,C 是热度榜,D 是人工运营位,都偏离了“从行为学偏好”的核心。
Q2. 游戏里“新玩家没有历史行为数据”属于什么问题?
- A.梯度消失问题
- B.特征爆炸问题
- C.冷启动问题← 正确答案
- D.过拟合问题
答案:C。新玩家或新道具缺乏行为记录,相似度算不出来,推荐系统没有“口味样本”可用,这正是冷启动问题。老周遇到新客人也得先搭话试探,梯度消失和过拟合是训练阶段的优化问题,特征爆炸是特征工程问题,均与“没数据”无关。
Q3. 物品协同过滤(ItemCF)的推荐思路是?
- A.找到相似玩家并推荐他们喜欢的物品
- B.找到与已购物品相似的物品再推荐← 正确答案
- C.按物品价格从高到低依次进行推荐
- D.随机推荐当前尚未购买的任何物品
答案:B。ItemCF 先算物品之间的相似度,再推荐“已购物品的相似品”,类似买过辣椒酱的客人会被推荐同品牌孜然粉。A 是 UserCF 的思路,C 和 D 都没有利用行为数据学习相似关系。
Q4. 余弦相似度公式中的分子表示什么?
- A.用户与物品的特征数量总和
- B.两个用户共同评分物品的评分乘积之和← 正确答案
- C.两个用户评分向量的长度之积
- D.全体用户对某一物品评分的算术平均
答案:B。分子的确是两个用户共同打过分(交集)的物品评分乘积之和,共同口味越多、分值越高,相似度越大。C 说的是分母,A 和 D 与余弦相似度的含义无关。
Q5. A/B 测试中 p<0.05 说明什么?
- A.样本量只有 5%,说明实验无效
- B.实验组效果一定比对照组差很多
- C.由随机误差造成当前差异的概率低于 5%← 正确答案
- D.必须把两组玩家合并继续测试
答案:C。显著性水平 5% 表示“纯靠运气看到这么大差异的概率不足 5%”,是统计判断而非实验进度条。老周两锅试吃,A 组多卖 20 份,他要确认这不是“今天左锅位置风水好”的偶然,而是配方真的更好。
Q6. 下列属于推荐系统离线评估指标的是?
- A.AUC← 正确答案
- B.GAUC← 正确答案
- C.服务器平均负载
- D.内存占用率
答案:AB。AUC 和 GAUC 都能拿历史日志离线计算,用于快速衡量排序能力,是“厨房里的试菜打分”。服务器负载和内存占用是工程容量指标,与推荐效果无关,属于“后厨设备健康度”。
Q7. 手游内购礼包推荐的最终排序目标通常是?
- A.最大化推荐位里道具种类的数量
- B.最小化推荐系统本身的平均计算延迟
- C.优先推荐库存积压时间最长的道具
- D.预估点击或购买概率并按期望价值排序← 正确答案
答案:D。排序目标要同时兼顾“买不买”和“值多少”,即预估购买概率并乘以道具价值,按期望价值排序。A 只求种类多,B 只优化性能不优化效果,C 是清库存思维,都会伤害玩家体验。
Q8. UCB 公式中探索项的作用是?
- A.只惩罚曝光次数过少的全新物品
- B.给曝光不足的物品加探索奖励以平衡探索利用← 正确答案
- C.让所有道具的推荐次数完全一模一样
- D.只提高价格最高道具的曝光概率
答案:B。探索项的数值随曝光次数 n_i 增大而减小,给曝光少的道具附加“潜力分”,让新道具也有机会被试吃,实现探索与利用的平衡。它不是惩罚、不是平均主义,更与价格无关。
Q9. 新道具上线没有任何用户行为,最稳妥的冷启动做法是?
- A.在推荐位随机展示且不做任何数据回收
- B.直接下架该道具以避免产生任何亏损
- C.用内容特征匹配相似老道具并给少量探索曝光← 正确答案
- D.只推荐给全服付费最高的前百名玩家
答案:C。标准做法是内容特征兜底——用品类、价格、美术风格找到“长得像”的老道具,把新道具放进对应的推荐位,同时给少量探索曝光验证真实反馈。A 随机且无回收等于白测,B 放弃机会,D 只给头部玩家会污染数据且体验差。
Q10. 关于推荐效果的多目标权衡与反作弊联动,下列正确的有?
- A.付费率与玩家体验冲突时需设置权重平衡← 正确答案
- B.风控分数可作为特征抑制异常账号的推荐曝光← 正确答案
- C.长期收益可通过探索策略牺牲少量短期付费换取← 正确答案
- D.只要离线 AUC 提升就应立即全量上线新模型
答案:ABC。多目标之间冲突时,要用加权或底线约束来平衡,不能只看付费率;风控分数是典型的“上下文特征”,能压制工作室小号的福利曝光;探索牺牲短期付费换取新道具和长尾玩家的长期价值。离线 AUC 提升只是“厨房试菜好吃”,必须经过 A/B 测试验证在线收益才能上线,D 违背了实验纪律。