腾讯广告算法大赛2026参赛记录与总结

  • 记于:2026-05-26 上午
  • 地点:浙江省·温州市·家里
  • 天气:多云

前言#

无意间看到了【腾讯广告算法大赛】,关于机器学习/推荐算法的,我其实几乎一点不懂,但是想着借助AI或许可以试一试。

前两天24号第一轮比赛已经结束了,当然,我没入围~排名200名开外~

截止目前26号,工业赛道排名前三分数已经0.854+了,第20名也有0.852+,我最后几天冲刺想要突破0.85+,失败了,最佳分数停留在0.845582。

第一轮赛事04.24-05.23,我是在提前一周左右开始报名、补知识做准备。
从头到尾我本地做了一些还算详细的日志(也是让AI记录的),包括:【学习计划与记录】、【参赛过程日志】、【运行日志】以及一些详细的模型训练和评测记录日志。

基于以上,我让AI写了一份总结与复盘。

以下部分就是AI写的了,我仅做校对与修正。


背景#

这次参加的是 Tencent UNI-REC Challenge,也就是大家常说的 TAAC 2026 / KDD Cup 2026 腾讯广告赛题。
我参加的是 Industrial Track,单人作战,Round 1 最终没有晋级。

先把结论放前面:

  • 我这次不是输在“没交作业”,而是输在没有找到能稳定跨过 0.85 的单模型家族
  • 我不是机器学习、推荐系统出身,而是更偏 Java Web 开发背景;
  • 我这次参赛很大程度上是一次“AI 协作做算法比赛”的真实实验;
  • 最后的已知最强线上模型,还是一条很朴素的稳定主线,AUC 大约卡在 0.8455
  • 后面几条看起来更聪明的终盘结构线,反而在 hidden test 上翻车了。

虽然没有晋级,但这轮比赛对我来说并不是“白打”。
它把我的技术边界、比赛节奏感、实验方法、和 AI 协作方式,都打得比以前清楚得多。

我的技术情况#

先说我自己的起点。

我并不是传统算法选手,也不是推荐系统工程师。
我的主背景更接近:

  • Java Web 开发
  • 业务系统开发
  • 中后端工程实现
  • 一些产品和独立开发经验

但在下面这些方向上,我的基础相对弱一些:

  • 机器学习
  • 推荐系统
  • CTR / CVR 建模
  • 大规模广告排序
  • 比赛型实验设计

所以这次参赛,一开始就不是“硬刚纯算法”,而是一个比较明确的组合打法:

  • 我自己负责方向、执行、取舍、节奏;
  • AI 负责辅助理解规则、梳理代码、帮我控实验发散、一起做技术判断;
  • 平台训练和评测由我自己盯;
  • 日志、决策、实验脉络持续记录下来。

说白了,这次不是“我拿 AI 当搜索框”,而是认真把它当一个高强度协作者来用了。

赛事情况#

这次比赛的几个关键信息,我在前期就反复确认过。

  • 赛题:Tencent UNI-REC Challenge
  • 赛道:我参加的是 Industrial Track
  • Round 1 时间:
    • 2026-04-242026-05-23 23:59:59 AOE
  • Round 2 时间:
    • 2026-05-252026-06-24 23:59:59 AOE
  • 晋级规则:
    • Industrial Track20 进入 Round 2
  • 每天最多 3 次提交
  • 主指标是 ROC-AUC
  • 明确禁止 ensemble
  • Round 2 还要求完整训练和推理代码可复现
  • 还要交 workshop 论文/技术报告

这里有一个对我后面影响很大的点:

这题禁止 ensemble#

这个限制非常关键。

因为很多比赛到了后期,最直接的涨分手段往往不是继续改单模型,而是:

  • 平均
  • 加权
  • blending
  • stacking
  • 多 checkpoint 组合

但这题明确不允许。

这意味着你最后必须回到一件很硬的事情上:

  • 单模型本体到底够不够强

我后面很多焦虑,本质上都来自这里。
因为一旦单模型主线卡住了,你就没有“最后用融合补一脚”的退路。

参赛前的判断#

我前期对这次比赛的定位,其实还算清醒。

我没有把自己当成“成熟算法选手”,而是把自己定位成:

  • 一个工程背景更强的参赛者
  • 一个单人实验负责人
  • 一个用 AI 强化信息处理和决策能力的人

所以我最开始的目标不是一口气冲榜,而是很现实的四步:

  1. 跑通 baseline
  2. 做出有效提交
  3. 找到 1~2 条能稳定改进的单模型主线
  4. 在可复现和时延约束下,尽量把分往上抬

这个起步策略现在回头看,我觉得是对的。

参赛过程#

我把整个过程大致分成三个阶段:

  • 前期:跑通、理解、建立主线
  • 中期:收敛、抬稳定线、确认平台期
  • 后期:追 0.85,赌结构,但没有成功

一、前期:先把 baseline 跑起来,再搞明白什么是真信号#

1. 最开始,我先确认了一件现实问题#

我本地机器是 MacBook M1

所以我一开始就没有幻想“本地完整训练 Round 1”这种事。
本地更适合做的是:

  • 读 demo 数据
  • 看 schema
  • 理解输入输出
  • 跑小样本
  • 改代码
  • 排查脚本问题

真正训练和评测,还是要依赖平台。

这一点如果前面认不清,后面节奏会很乱。

2. baseline 比我想象中更值得认真拆#

很多人拿到 baseline,第一反应是“先跑一下,再说”。
但我这次前面花了不少时间做结构化拆解。

包括:

  • 数据列结构
  • 非序列特征和序列特征怎么分
  • 多域序列怎么组织
  • 模型主干是怎么工作的
  • 训练器和 checkpoint 机制
  • 推理链路和 predictions.json 格式

这个动作当时看起来慢,但后面很值。

因为比赛不是只靠“多开实验”赢的;
很多时候是靠你足够早知道:

  • 这段代码到底在学什么
  • 这条线到底为什么涨
  • 这次离线指标到底意味着什么

3. baseline 第一枪给了我信心#

2026-04-28,baseline 的官方评测结果出来了:

  • AUC = 0.845179

这个分数有两个意义:

  • 第一,证明 baseline 不是完全没法打;
  • 第二,说明这题的单模型 baseline 本身就不低。

也就是说,这不是那种“baseline 0.78,随便改改就 0.84”的题。
这题一开始就站在相对高的位置上,想继续往上推,是很难的。

4. 前期最有价值的改动,是 RoPE#

前期我做过一些小实验:

  • 改序列长度
  • grouped NS tokenizer
  • RoPE
  • LongerEncoder
  • 换 seed
  • focal loss

其中真正最先在线上被验证为正收益的,是 RoPE 那条线。

2026-04-29

  • t3.m38050 = 0.845331

它超过了 baseline 的 0.845179

这个提升不大,但非常重要。
因为它让我确认了一件事:

  • 这个 baseline 不是完全推不动

你在比赛里最怕的不是改动没涨分,而是你根本不知道有没有任何方向会被线上承认。
t3 的意义就在这里。

5. 但前期也很快告诉我:不是所有“看起来合理”的方向都成立#

后面我试了:

  • LongerEncoder(top_k=50)
  • focal loss
  • 一些轻量正则和压缩线

这些方向要么离线就不强,要么线上不承认,要么直接止损。

前期给我的第一个真正比赛感受就是:

  • 广告排序比赛里,“听起来合理” 和 “线上真的有效”,中间隔着很深的沟。

二、中期:开始收敛主线,但也开始碰到平台期#

1. 这中间还有一个大插曲:榜单 reset#

前面做着做着,官方修了 Industrial Track 的测试集,榜单 reset 了一次。

这个事情对我影响很大。

因为它意味着:

  • 之前的线上 best 不能直接当新榜依据
  • 一些旧实验的线上排序可能会变
  • 你必须重新验证自己认为“成立”的路线

这也是我后面为什么越来越强调:

  • 日志要记
  • checkpoint 要审计
  • 不能只记一个分数
  • 必须知道这个分数是在哪个测试集、哪个阶段、哪个配置下出来的

2. 中期我开始做 validation rebuild#

大概到 2026-05-02 之后,我开始更认真地处理 validation 问题。

因为我逐渐发现:

  • 单看某一个 valid split
  • 或者只看主验证 AUC

很容易在 hidden test 上被骗。

所以我开始逐步建立:

  • interleaved primary
  • tail diagnostic
  • time_tail

这些验证口径。

说白了,我在中期逐渐把问题从:

  • “哪个 checkpoint 离线最高”

变成了:

  • “哪个 checkpoint 的离线信号更像 hidden test 会接受的信号”

这个转变我觉得是对的。

3. t24 成了我真正的稳定主线#

中期最核心的一条线,是 t24_user_ns_tokens2_item_ns_tokens1

后面我最终锁定的历史最佳模型也是它:

  • t24_21.m68490
  • 历史已知最好线上 AUC:0.845582

这条线对我来说非常重要。

因为它不花哨,但稳。
它后面基本承担了两个角色:

  • 一个是“当前最强保底线”
  • 一个是“后续所有进攻线的参考基准”

4. 我还开过一条更像“进攻线”的 t30#

t30t24 + batch_size=128 的方向。

离线看,它一度很有戏。
在等效曝光量下,甚至明显强于 t24 同阶段。

这也是中期最容易让人上头的一类情况:

  • 离线曲线很好看
  • 指标也单调改善
  • 你会觉得“这条线快要成了”

但最后线上没有兑现。

这件事给我的教训非常深:

  • 离线强,不等于线上就会更强

尤其当两条线最终线上只差 1e-4 ~ 1e-3 的时候,很多你以为已经“看懂”的信号,其实都还不够稳。

5. 到 t32 的时候,我基本确认:我撞到平台期了#

2026-05-14

  • t32@34185 线上结果是 0.845335

它没有超过 t24@68490 = 0.845582

这一刻我实际上已经得到一个非常关键的判断:

  • 继续在 t24/t30/t32 家族里靠选点、验证切分、batch size 微调,大概率只能在 0.845 附近波动

也就是说:

  • 我需要的不是更会挑 checkpoint
  • 而是另一条更强的模型家族

这就是我后面进入后期“结构进攻”的起点。

三、后期:我开始追 0.85,但最后没追上#

1. 后期的心态其实已经变了#

到后面我逐渐形成了一个很主观、但很现实的判断:

  • 如果 AUC 还不到 0.85,那这轮大概率就不够

严格来说,晋级线不一定就是 0.85
但对我当时的观察和心理预期来说,0.85 已经成了一个很强的目标线。

这也让后期策略变得更激进:

  • 我不再只想“比 0.8455 多一点”
  • 我想要的是能真正跳一个台阶的东西

2. 后期我开的,是一批“更像新家族”的线#

t33 开始,我后面试了不少结构方向:

  • t33:hidden 从 64 -> 96
  • t34:layer 从 2 -> 3
  • t35num_queries = 2
  • t36:item-heavy NS 分配
  • t41:target-aware sequence matching
  • t42:tail sequence summary
  • t43:target-aware + tail16
  • t44:recent target gate
  • t45/t46:稳定化的 hidden96 家族
  • t55-t60:最后几天的终盘修复线和新 query family

这里面,有些方向离线是有正信号的。

比如:

  • t35 证明 queries=2 的排序收益是成立的
  • t34 说明加深不是完全没用
  • t41/t42 在某些阶段也给过我结构上“像是有戏”的感觉

但问题在于:

  • 它们要么没有形成能稳定上线的单点
  • 要么离线增益还不够大
  • 要么被 hidden test 直接否了

3. 最让我难受的一次,是 t58#

终盘我做了一条 t58 线:

  • 保持 t24/t56 骨干
  • 只改 seq_d 的截断方式
  • 把单纯前截断改成 head + tail hybrid truncation

它离线不是特别炸裂,但看起来是有一点收益的。

后来拿到的离线峰值大概是:

  • t58@45276
  • AUC/valid = 0.8633871675
  • LogLoss/valid = 0.2264489681

但线上结果出来以后,直接把这条线判死了:

  • t58.m37730 = 0.835486

这不是“没达到预期”,而是方向性错误

也就是说,这条线不是 checkpoint 选差了,也不是差一点点没兑现;
而是这整个 family 对 hidden test 就是不适配。

这次结果对我打击挺大的。
因为它说明:

  • 不是所有“更贴近最近行为”的想法,hidden test 都会买账

而且一旦这条线线上掉了这么多,你就没法再骗自己说:

  • “也许后一个 step 就好了”

4. 最后一条真正像“新家族”的尝试,是 t60#

比赛最后,我还开了 t60

这条线我其实挺看重的,因为它不是继续加 side branch,而是直接改主干:

  • 把主 query family 改成 item-conditioned
  • 让候选 item 在生成每个序列域 Q token 时就参与条件化

我到现在都觉得,这个方向在思路上是对的。
因为它试图解决的是一个更本质的问题:

  • 你的历史摘要是不是太“通用”了
  • 它有没有真正针对当前 candidate item 来重构历史信息

但现实问题也很明显:

  • t60 开得太晚了
  • 我没有时间把它跑出完整证据链
  • 它没来得及成为一条真正可以和 t24 正面对比的成熟线

5. 最后我还是回头重提了历史最佳 t24#

比赛最后,我又重提了一次历史最佳模型:

  • t24_21.m68490

这次出来的线上结果是:

  • 0.845517

和历史最好 0.845582 只差:

  • 0.000065

这件事最后把结论彻底钉死了:

  • t24 仍然是我已知最强稳定线
  • 但它的真实线上 ceiling 大约就是 0.8455

换句话说:

  • 我不是最后一枪没打对
  • 我是这轮从头到尾都没找到一条稳定跨过 0.85 的单模型家族

最终结果#

Round 1 结束,我没有晋级。

如果只看结果,这当然是失败。

而且不是那种“只差一个操作”的失败。
更准确地说,是:

  • 这轮我把一条稳定 0.8455 的主线打得很清楚了
  • 但我没有把它推成一条 0.85+ 的主线

这个差距,说小不小,说大也不算特别大。
但在比赛里,很多时候就是这几千分之一,决定你有没有下一轮。

我这次做对了什么#

1. 我很早就开始记日志#

这次我最庆幸的一件事,就是从比较早的时候就开始系统记:

  • 规则
  • baseline 理解
  • 数据理解
  • 每条实验线
  • checkpoint
  • 线上结果
  • 决策理由

这让后期虽然很焦虑,但不至于失控。

因为我至少知道:

  • 哪条线是真的成立
  • 哪条线只是离线看着好
  • 哪条线已经明确线上翻车

2. 我没有把资源浪费在大而散的随机试错上#

虽然我开的线不少,但整体上还是比较有层次的:

  • 前期先跑通和找早期正信号
  • 中期收敛到稳定主线
  • 后期再做结构进攻

我没有在第一周就胡乱堆特别多复杂结构,也没有一开始就想着“靠黑科技一把冲榜”。

这个节奏我觉得是合理的。

3. 我较早确认了比赛的真实约束#

比如:

  • 禁 ensemble
  • 提交次数有限
  • 线上 hidden test 和离线 valid 不会完全一致
  • 最后必须考虑 reproducibility 和 latency

这些事情如果前面不重视,后面很容易在错误的问题上消耗很多时间。

4. 我认真把 AI 当协作者用,而不是当搜索框#

这点我自己还是挺满意的。

这次不是简单让 AI 帮我“写个代码”或者“解释个概念”;
而是长期让它参与:

  • 读 baseline
  • 帮我约束实验发散
  • 整理日志
  • 复盘主线
  • 识别平台期
  • 判断哪些方向该止损

这个模式我后面大概率还会继续用。

我这次做错了什么#

1. 我真正的“更强主模型家族”起得还是太晚#

这是最大问题。

我前面虽然做了很多实验,但中期很长一段时间,还是在 t24 家族附近做修补和延长。

这不是完全错;
但如果目标是 0.85+,那你迟早要问自己一句:

  • 这条线是不是已经封顶了?

我真正彻底承认这件事,是在 t32 线上结果出来以后。
到那时再全力转结构进攻,其实已经晚了。

2. 我对 hidden test 的适配方式,理解得还不够深#

比如 t58 这类线,离线看起来是“有道理”的:

  • 最近行为更重要
  • 序列头尾都保留一点

但线上直接掉到 0.835486

这说明我对 hidden test 真实偏好的理解,其实还没有到能稳定做结构命中的程度。

3. 我还是有一点“离线上头”#

比赛里很容易这样:

  • 看到一条曲线涨了
  • 看到某个点 AUC 很好
  • 就想继续加码

但这题后面反复告诉我:

  • 离线 1e-4 级别的优势,很多时候线上根本不稳
  • 甚至方向都可能反

这方面我虽然中后期已经越来越克制,但还是吃了亏。

4. 单人作战的节奏管理,还是会天然吃亏#

单人参赛的优点是:

  • 决策链短
  • 不需要沟通成本

缺点也很明显:

  • 平台训练、日志、判断、代码、提测,全都要自己盯
  • 很容易在某条线上投入过多注意力
  • 很难做到真正意义上的并行脑力分工

这个问题很现实,不是靠“努力一点”就能完全解决的。

关于 AI 这次到底帮了我什么#

如果让我总结一句话:

  • AI 没帮我凭空造出一个 0.85+ 的模型,但它确实帮我把这轮比赛打得比我一个人瞎撞要清楚得多。

它帮到我的地方主要在:

  • 读代码和 baseline
  • 理规则
  • 组织实验信息
  • 维护日志
  • 帮我收敛问题
  • 及时提醒我哪些方向其实已经该停了

它没能替代我的地方也很明显:

  • 最终 hidden test 偏好仍然要靠真实比赛经验和模型直觉
  • 提交节奏和资源取舍还是得自己扛
  • 模型 family 到底强不强,最后还是成绩说话

所以我现在对 AI 的看法反而更稳了:

  • 它不是外挂
  • 也不是答案生成器
  • 它更像一个不会累的高频协作者

前提是你自己得知道你在做什么,至少知道你想逼近什么问题。

如果再来一次,我会怎么打#

如果让我重新打一遍这轮 Round 1,我会改几件事:

1. 更早承认主线封顶#

一旦发现 t24/t30/t32 这类线长期卡在 0.845x,我会更早转向“新 family”,而不是继续做过多保守修补。

2. 更早做 item-conditioned 主干,而不是更晚才想到#

t60 这种思路,我下次会更早开。
因为它解决的是主干表达问题,不是末期外挂问题。

3. 更严格地区分三类实验#

  • 保底线
  • 结构侦察线
  • 真正提交线

这三类线如果混在一起,后面很容易乱。

4. 更早把“hidden test 不吃什么”总结出来#

不是只记“哪个涨了”,也要更早总结:

  • 哪类结构线上会掉
  • 哪类看似合理的 recent bias 会翻车
  • 哪类 side branch 是离线虚高

这个负样本知识,其实很值钱。

这轮比赛对我最大的价值#

如果只按是否晋级来算,这轮当然是失败。

但从更长一点的视角看,它给我的价值很大:

  • 我第一次完整打完了一轮这种级别的广告/推荐比赛
  • 我第一次比较系统地把工程思维和算法实验方法结合起来
  • 我第一次认真验证了“AI 协作做比赛”到底能走到什么程度
  • 我第一次把“日志、实验、决策、复盘”做成了一个真正连续的过程

更重要的是,它让我知道了我现在到底差在哪。

这比“只知道自己没晋级”要有用得多。

我差的不是:

  • 会不会写训练脚本
  • 会不会跑平台
  • 会不会做 baseline 改造

我真正差的是:

  • 能不能更早找到对 hidden test 真正有效的主模型家族

这件事,下一轮再练。

最后#

Round 1 结束了,没晋级。

这篇文章不算庆功文,更像是一次认真存档。

我想把这段过程记下来,主要有两个原因:

  • 第一,给未来的自己留一个清晰版本,别以后只记得“当时好像打过一个比赛”
  • 第二,给和我类似背景的人一个参考:
    • 不是纯算法出身
    • 但想认真打一场比赛
    • 想看看 AI 到底能不能作为高强度协作者

我的答案是:

  • 但它帮你的是“更清楚地打”
  • 不是“直接替你赢”

这轮先到这里。


以上,AI总结与复盘结束。

补充#

AI:Codex / GPT 5.4