☰
自监督表示学习如何赋能AI Agent:从对比学习到时序预测的实践指南
2026/10/22 21:07:55 网站建设 项目流程

1. 先说一个让我改观的项目复盘

去年我参与做一个室内漫游Agent,任务是让智能体从房间任意起点走到指定目标点,输入只有一帧一帧的视觉画面和里程计数据,动作输出是线速度和角速度。一开始我们用最直接的端到端方式,把观测丢进卷积网络,直接学策略,用的是当时很成熟的强化学习算法。跑了三百多万步后,成功率始终卡在六成上下,最让人崩溃的是学习曲线像过山车,今天还能绕开障碍物,明天换个光照条件就彻底迷失,仿佛前面学的东西全部清零。

某天我盯着tensorboard上那些发散的红线,突然意识到一个扎心的事实:Agent并不是在“理解”环境,它只是在逐帧硬背像素。策略网络背下的是训练集里见过的颜色分布、位置组合,一旦环境稍微变化,背下来的“经验”就失去意义。问题的根源不在强化学习算法本身,而在输入到策略网络之前的那个特征表示——像素空间表达出来的状态既不紧凑,也不具备因果结构,更谈不上对抗分布变化的能力。

那次之后我开始认真补课,接触到一个方向:AI Agent的自监督表示学习。简单说,让智能体在没有任何人工标注的前提下,从观察数据本身构造学习任务,先把“世界长什么样、什么和什么相关、什么在变化中保持不变”这套底层表示学出来,再拿去驱动策略、做记忆、做规划。这篇文章就把我这一年多摸索下来的理解、设计思路和踩过的坑完整讲一遍,希望给同样被“Agent学不动”困扰的人一点参考。

1.1 三种Agent形态,同一种“识字困难”

现在说AI Agent,其实至少有三条技术路线。第一种是感知-决策闭环型Agent,典型就是机器人导航、自动驾驶里的横纵向控制、灵巧手操作,核心是用强化学习或模仿学习直接从观测映射到动作。第二种是大模型编排型Agent,典型表现是会自己拆解任务、调用工具、读文档、写代码,慢慢规划并执行。第三种是混合形态,比如让视觉模型先把环境状态抽取出来,再交给语言模型做高层决策,低层再接一个运动控制模块。

这三类看着天差地别,但往下挖一层,它们全都依赖一件事:把原始输入转换成机器可以推理的向量,也就是representation。感知型Agent需要把图像编码成包含位置、障碍、目标信息的隐向量。编排型Agent需要把网页、工具说明、历史消息编码成能检索、能对齐语义的嵌入向量。混合形态更是如此,视觉encoder抽出的表示质量直接决定语言模型能不能看懂现场。表示学歪了,后面策略再好、推理再强都白搭。

1.2 为什么“标注+监督学习”在Agent场景里越来越不够用

我们过去做感知任务,鲁棒性能通过大量标注数据堆出来。但在Agent场景里,监督学习至少面临三个硬伤。

第一是标注成本。一个状态-动作对或者一帧关键场景,有没有意义、当前动作合不合理,往往要结合整条轨迹才能判断。标注员逐帧标动作、标语义,成本高而且一致率低。第二是奖励稀疏。Agent大部分时间并不知道自己做得对不对,一个目标可能在几百步之后才出现,期间没有任何监督信号。第三是分布漂移。Agent的探索策略会不断改变它看到的数据分布,今天学好的表示用来理解明天的新环境,天然就存在分布断层。监督学习对独立同分布数据的假设,在Agent这个场景里根本不成立。

自监督学习不一样。它不依赖外部标签,而是从数据里自己出题:拿一帧图像遮住一半,学着补全;拿同一时刻的不同视角,学着拉近;拿连续几帧画面,学着预测下一帧。没用标签,被迫去挖掘数据内在的结构。这个性质恰好对准了Agent的三个痛点:不需要人工标注、不依赖稀疏奖励、反而能在分布变化中抓住稳定结构。

2. 自监督表示学习的三种底层玩法及原理拆解

入坑之后我发现,自监督表示学习方法看着五花八门,核心套路其实就三大类:对比式、重建式、预测式。理解它们各自在“学什么”,比背一堆损失函数管用得多。

2.1 对比学习:拉近同类,推开异类

对比学习的思路是给模型一批样本对,让它学会“什么样的两个输入算同一件事”。具体做法一般这样:一张画面做两次随机增强,得到两个不同视角,视为正样本对;再拿这一批数据里其他样本当作负样本。模型的目标是把正样本对的表示拉近,把负样本对的表示推开。常用的损失函数是InfoNCE,核心形式类似:

# 示意:InfoNCE 对比损失 def info_nce_loss(query, positive_key, negative_keys, temperature=0.07): # query: [B, D] 当前样本的表示 # positive_key: [B, D] 正样本视角的表示 # negative_keys: [B, N, D] 一批随机负样本的表示 pos_logits = (query * positive_key).sum(dim=-1) / temperature # [B] neg_logits = torch.einsum('bd,bnd->bn', query, negative_keys) / temperature logits = torch.cat([pos_logits.unsqueeze(-1), neg_logits], dim=-1) labels = torch.zeros(logits.size(0), dtype=torch.long) return torch.nn.functional.cross_entropy(logits, labels)

温度系数\tau是这个损失里的灵魂。它控制着模型对负样本的“苛刻程度”,\tau越小,模型越倾向于只关注最难区分的负样本,表示容易变得碎片化;\tau太大,所有样本都差不多,表示又会失去判别力。实践里0.05到0.1之间是常见搜索区间。

Agent场景里有个更自然的正样本定义:时间一致性。同一段轨迹里相邻几帧画面的内容高度相关,把它们作为正样本对,让模型学到“时间上连续的状态在表示空间里也应该是邻近的”。这个思路不需要任何人工标注,只要Agent会随机走动就能产生海量轨迹数据。我后来做的项目里,正样本基本都来自时间近邻,负样本从经验池随机采样,效果比纯图像增强对比要好。

2.2 掩码重建:把世界当填空题做

重建式自监督的代表思路来自掩码图像建模。做法是给一张图随机遮掉大量区域,让模型根据“看见的部分”把“被遮的部分”补出来。最初这类方法的遮块比例通常高达75%,只让encoder看到少数可见patch,再用轻量decoder恢复被遮patch。这样设计的用意很明确:如果遮得太少,模型靠局部纹理就能瞎蒙,学不到全局关系;遮到只剩一丁点,模型必须理解物体的整体结构才能补全,逼出来的特征自然更高级。

在Agent里,我见过两种用法。一种是把掩码重建直接丢在视觉encoder上,让encoder从当前画面中恢复被遮挡的障碍物、道路、目标,学出来的表示天然包含环境的空间布局。另一种是把重建目标从像素空间换成隐空间:先让encoder把观测压成隐向量,再根据可见的时空上下文预测未来的隐向量。后者更像“世界模型”的做法,不纠结于逐像素还原,只要求隐状态预测得准。

这个范式最大的优点是不需要对正负样本做精心设计。缺点也比较明显:纯像素重建会把大量算力浪费在恢复墙壁纹理、草地颜色这类与决策无关的细节上。所以我自己做Agent表示时,通常会把重建目标从RGB像素换成特征层面,或者只用重建式方法做辅助损失,不做主损失。

2.3 时序预测:让表示学会“预见”

第三类是我个人最喜欢的,也是我认为跟Agent决策耦合最深的:预测式自监督。核心思想一句话——环境是时序的,好的表示应该能让模型预测未来。给定当前观测s_t和当前动作a_t,让模型去预测下一时刻的表示s_{t+1};预测得越准,说明表示里保留的环境动态信息越多。

这个方向有一个更理论化的框架叫联合嵌入预测架构(JEPA),它把“预测”和“表示学习”绑在一起:用encoder分别提取当前帧和未来帧的表示,再训练一个预测网络,从当前表示出发预测未来表示。未来帧encoder的梯度通常会截断,防止模型为了容易预测而把表示压缩得毫无信息。

时序预测在Agent里的另外一个变体是逆动力学预测:给出前后两个状态表示,去预测中间那个动作。这个任务迫使表示保留“与动作相关的状态变化”,丢掉光照、纹理这些跟决策无关的细节。我在做机器人操作相关实验时,逆动力学辅助损失经常比正向预测更稳定,因为正预测容易受环境随机性干扰,逆预测反而问了“什么导致了这个变化”,目标更聚焦。

这三种范式没有绝对好坏,它们的对比可以看下面这张表:

范式学习信号来源代表问题形式适合的Agent场景典型风险
对比学习正负样本对拉近正样本、推开负样本视觉导航、状态判别、跨域对齐负样本设计不当、表示坍缩
掩码重建可见与不可见部分用可见区域恢复被遮内容场景理解、像素级空间感知重建细节浪费容量
时序预测时间前后关系用当前预测未来表示世界模型、动态建模、操作规划随机环境难预测、梯度崩溃

3. 把自监督表示接进Agent决策链路:四种常见设计

学会了表示并不等于Agent变聪明了,关键还在于怎么把表示接入决策回路。这一步设计不好,之前训练得再漂亮都只是“屠龙之技”。我实践中尝试过几种接入方式,各有适用边界。

3.1 两阶段式:先学世界,再学走路

最直接的做法是两阶段。第一阶段,让Agent在环境里随机游走,用自监督任务把encoder训练好,然后冻结。第二阶段,把冻结后的encoder当作固定特征提取器,只训练策略网络。这种做法的好处是解耦:表示学习阶段不依赖奖励,完全自监督;策略学习阶段不用反向传播到庞大的encoder,训练稳定,样本效率高。

缺点也明显:自监督阶段的任务未必与下游决策对齐。很多项目里表示学习学到的特征是“聚类友好的”,但不是“控制友好的”。解决方法是预训练完之后做一次小规模下游任务微调,或者用强化学习损失对encoder做很轻量的继续更新,只调最后一两层。我自己的经验是,如果数据分布和环境类型比较明确,两阶段式最省心。

3.2 端到端辅助损失:边决策边“补课”

第二种方式是把自监督损失作为辅助损失,跟强化学习或监督学习的目标一起叠加在总损失里。比如策略网络用PPO更新,同时对话中额外要求encoder输出的表示具备时序一致性,保证同一轨迹的状态在表示空间平滑变化。这等于在每个训练步给表示一个“结构约束”,避免策略网络被稀疏奖励带偏。

实践中最大的问题是如何平衡两项损失。自监督损失的尺度跟策略损失完全不在一个量纲,权重设大了,模型专心搞表示,策略进展缓慢;设小了,约束形同虚设。我的做法是先让自监督损失预热跑几千步,统计它的量级,然后把两项损失做归一化,再给自监督权重一个比较小的系数。另外,辅助损失和主损失如果都在更新encoder,很容易为了满足辅助任务牺牲主任务特征,必要时可以对辅助分支使用stop-gradient。

3.3 世界模型:把自监督放到“想象”里

第三种思路更激进:不再把表示当作中间产物,而是把Agent的核心模型本身就构建成一个自监督预测系统。典型结构是:感知encoder把当前状态压缩成隐向量,世界模型根据向量和动作预测下一时刻隐向量,策略网络在隐空间中“想象”若干步之后的状态,再根据想象结果选择动作。

这种设计的好处是巨大的。Agent大部分决策不需要跟物理世界硬碰硬,而是在自己的隐空间里做推演,效率高很多,而且从预测误差里天然产生探索信号——如果世界模型在某段状态上预测不准,说明这里的环境还没学透,值得额外探索。这个信号本身就是一种自监督机制。我在模拟室内导航里尝试过,搭配对比性状态表示后的隐空间,比直接预测像素的版本稳定得多,训练速度也快一个量级。

3.4 大模型Agent:表示决定记忆检索与工具调用的上限

编排型Agent跟视觉Agent表面上是两个物种,但自监督表示在其中同样扎得深。我们可以把工具文档、网页内容、历史对话、API说明都编码成向量,Agent查询时拿当前目标去检索最相关的片段。这个检索过程能不能找对,完全取决于向量表示的质量;而绝大多数优质嵌入模型的训练,本质上就是用海量无标注文本做的自监督学习——语言模型预训练本身就可以视为掩码重建或对照预测式的自监督表示学习。

我的观察是,很多做Agent编排的团队把大量精力花在提示词工程上,却忽略了底层表示质量。同一个检索任务,换一个自监督预训练更充分的嵌入模型,工具调用的准确率可以非常明显地拉开差距。原因在于工具选择本质上是一个语义匹配问题,表示空间如果没能把意图和工具描述拉近,Agent就只能靠关键词硬碰。所以在调试大模型Agent时,遇到“工具选错”“记忆翻不到”这类问题,我建议先查表示,再查prompt。

4. 实操避坑记录:五个最容易翻车的地方

理论部分讲完,分享点实实在在的编号坑。这部分内容不是从论文里读来的,全是项目里栽过跟头后沉淀下来的检查清单。

4.1 表示坍缩:头号杀手,损失再低也没用

对比学习最经典的问题就是表示坍缩。模型懒得干活,直接把所有输入映射到同一个常数向量,损失轻松降到很低,但表示信息量趋近于零。Agent接上这个表示后,策略学到的全是噪声。

这类方法里防坍缩的手段多种多样:InfoNCE依赖充足的负样本和恰当的温度系数;BYOL这类方法靠预测器和stop-gradient来规避,还有方法在损失里加方差正则项等。在Agent项目里识别坍缩很重要。我的检查习惯是:每训练若干轮,把验证集表示的每个维度算一下标准差;如果大量维度标准差小于0.01,基本就是在坍缩的边缘。再做一个简单可视化,把表示投影到2D平面,正常应该呈现一些自然的簇结构,坍缩时你只会看到一团浆糊般的点云。

4.2 增强设计:别把CV三件套直接搬进Agent

做视觉自监督的人习惯用随机裁剪、颜色抖动、灰度化这些增强来构造正样本。这在图像分类任务里是对的,因为语义对颜色、位置有天然不变性。但Agent的观测空间里,位置和颜色往往携带关键决策信息:目标在画面左侧还是在右侧、红灯还是绿灯、门是开还是关,这些一旦被增强破坏,正样本对就名存实亡。

我在Agent实验里常用的增强组合是:小幅亮度扰动、少量随机噪声、轻度平移但不改变物体相对位置、时间维度上取相邻帧作正样本。核心原则是保证“决策语义不变”,不是“外观看起来差不多”。如果拿不准某个增强是否会破坏决策信息,做一个最简单的消融实验:用这个增强训练出的表示去做下游导航任务,对比不用的效果差异,比空想靠谱得多。

4.3 超参敏感性:温度、batch size、动量值一个都不能省

自监督表示训练的指标对超参相当敏感,尤其是以下几个。

温度系数\tau我前面提过,建议在0.05到0.2之间先做粗搜,再以小步长精调。batch size直接影响负样本数量,对比学习非常依赖负样本丰富度,batch size太小,负样本不够,表示质量断崖式下跌。我在导航项目里差不多保证单批次至少256对。动量编码器的更新速率也很关键,一般取0.99到0.999。更新太快,正负样本特征分布频繁变化,训练不稳;太慢,编码器跟不上当前数据的分布变化。

还有一个容易被忽略的细节是投影头。训练阶段通常在encoder后面接一个MLP投影头,把表示映射到对比空间;下游使用时丢投影头、只保留encoder的特征。这个设计不是可有可无,它让encoder不用为了对比任务牺牲“通用特征”。一开始我图省事没加投影头,结果下游任务性能明显打折。

4.4 非平稳分布:Agent探索过程中表示在悄悄漂移

这个问题是我临到最后才真正重视的。Agent不是静态数据集里的分类器,它会一边探索一边学习。早期策略只能看到某个区域的数据,这时学出的表示可能对这个区域过拟合;随着策略进步,Agent探索到新区域,新数据的分布跟旧表示训练的分布已经不同。如果不管漂移,表示会慢慢失真,最终拖累决策。

我在项目中试过几种应对方式。最简单的是维护一个大型经验回放池,让自监督训练数据尽量覆盖历史分布;进阶一点,可以用EMA版本的表示作为稳定目标,让在线表示不至于突变;再激进一些,对encoder靠后的层做周期性的重新初始化,让低层保留通用视觉特征,高层持续适应当前分布。判断表示是否漂移的方法也简单:维护一个线性探针,定期拿少量带标签状态测一下准确率,一旦开始掉点,就该考虑更新机制了。

4.5 怎么科学评估表示质量:别只看下游效果

下游任务的最终成功率当然重要,但它是个十分滞后的指标,不利于开发期快速迭代。我在项目里会同时维护几个更灵敏的评估指标:线性探针准确率、近邻检索准确率、时间平滑性和表示利用率。

线性探针的做法是冻结encoder,只训练一个线性分类器,用下游任务的部分标签预测,准确率越高说明表示里可线性分离的信息越丰富。近邻检索则直接测试表示是否具有语义相似性。时间平滑性用来衡量相邻状态在表示空间中的平均距离,值越小表示越符合时序一致性。表示利用率可以简单用特征维度的有效秩来估算,有效秩过低意味着大量维度冗余。这几个指标组合在一起,基本能在训练过程中实时判断表示是否走在正轨上。

5. 一个最小可复现的参考Demo:从随机游走到视觉导航

理论和方法都说太多了,来一个具体闹得动的实验设置。这个Demo在我的模拟环境里跑过,模型很小,单张消费级显卡几个小时就能完成,适合当作自监督表示学习接入Agent的起点。

5.1 任务设定与数据准备

我用的模拟环境是一个2D栅格迷宫,Agent每次看到以自身为中心的84x84局部灰度图,地图上散布墙壁障碍物,随机位置放一个目标点。动作空间是上、下、左、右四向移动。任务是让Agent学会从任意位置走到目标点附近。

数据收集阶段完全不用人类参与:让Agent按随机策略在场景里走足够多步,并把每次移动前后的观测对保存下来。具体收集了约十万步数据,组成时间相邻的观测对。存储格式就是一个普通缓冲区,正样本是(s_t, s_{t+1}),负样本从缓冲区里随机抽取其他时刻的观测。

5.2 encoder与对比损失的简化实现

encoder我用一个四层卷积网络加全局平均池化,输出128维特征,再跟一个两层的MLP投影头,投影到64维。训练时对比损失用InfoNCE,核心伪代码在上面一节已经写过了。训练参数可以参考下面这组:

# 训练配置示例 batch_size = 256 temperature = 0.07 encoder_lr = 3e-4 projector_lr = 3e-4 momentum = 0.99 train_epochs = 50 # 每个step的流程 for obs_t, obs_next in dataloader: z_t = projector(encoder(obs_t)) z_next = projector_ema(encoder_ema(obs_next)) # 目标分支用动量encoder loss = info_nce(z_t, z_next, negative_keys=neg_keys) loss.backward() update(encoder, projector, lr=encoder_lr) update_ema(encoder_ema, encoder, momentum)

这里的关键设计是目标分支用了动量encoder,稳定性比单纯用同一encoder好很多。训练完成后,projector丢掉,只用encoder作为特征提取器。

5.3 策略训练与结论

预训练完成后,我冻结encoder,把它的输出接一个两层MLP策略头,用策略梯度算法训练导航策略。为了对照,我同时跑了两个对照组:一组是随机初始化的encoder直接接策略训练,另一组是预训练表示接策略。

在我那个小环境里,结果差异拉得相当开。随机初始化的策略最终成功率在六成左右,预训练表示策略的成功率稳定在九成上下。更值得注意的是训练曲线形态:随机初始化那组在训练中反复震荡,甚至几次出现几乎归零的重置;预训练那组曲线平滑很多,说明策略网络在起步阶段就站在一个相对合理的特征空间里,而不是边探索特征边学策略。另外还做了光照变化测试,预训练表示面对未见过的亮度水平,成功率衰减明显更小,这正是时序预测类自监督任务带来的泛化收益。

5.4 从Demo到真实项目,需要额外做的事

这个Demo虽然简单,但它验证了整条链路的可行性。真要把这套方案搬到复杂环境,我自己的体会是还要补三件事:一是把增强策略从“手动挑”换成“自动搜索”,把时序一致性和下游性能直接当作回报来选增犟;二是加入世界模型式的预测分支,让表示不仅反映过去,还能预测未来;三是对表示做周期性评估并记录指标曲线,保留好判断是否发生分布漂移的历史依据。

6. 我的一些判断和后续打算

做了一段时间自监督表示学习与Agent结合的项目后,我对这个方向的边界有了比较清楚的感受。它不会取代强化学习、也不会取代大模型推理,但它是所有这些上层能力的“地基”。没有好表示,Reward设计再好也容易变成对噪声的拟合;没有好表示,大模型Agent的检索和工具匹配就建立在一个松塌的语义空间上。真正值得投入的方向是让表示学习从“开训一次、用到结束”变成“终身更新”。Agent每进入一个新环境,最好都能快速调整自己的特征空间,而不是靠一个静态模型硬撑。

另一个让我着迷的方向是跨智能体共享表示。多个Agent协作时,如果能共享一套自监督训练的底层表示空间,每个Agent学到的新技能能转化成表示空间里的局部结构调整,那么其他Agent也能受益。这种“群体性的表征积累”很像人类社会的知识共享,想象空间很大。我还没有做得很成功,前期实验里最大的难题是不同Agent观测到的数据分布差异太大,共享表示在某一方发生过拟合后,会影响整体性能。

最后说一个特别实际的建议:如果你的Agent项目正卡在“训练不稳、泛化差、标注不够”这些问题上,可以先尝试两阶段接入方式,拿随机策略收集数据做自监督预训练,然后用最朴素的强化学习算法微调策略。这个组合未必是最终最优解,但它是性价比最高、最快让你看清问题本质的起手式。我自己就是从这样一个实验开始,逐步把表示学习变成Agent项目里不可跳过的一环。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询