ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

模型异构联邦学习落地:pFedES代理特征提取器机制与复现指南

模型异构联邦学习落地:pFedES代理特征提取器机制与复现指南

模型异构联邦学习这几年逐渐从论文里的"炫技"变成了落地时的刚需。做联邦的人应该都撞过同一堵墙:客户端设备五花八门,算力参差不齐,你想要性能好的设备用大模型,又想老旧设备跟它一起训练,经典联邦平均(FedAvg)那一套要求所有客户端用同一个模型结构,结果只能让高配设备陪着低配跑小模型,非常浪费。pFedES 这个方向就是在解决这个问题,全称很直观:Generalized Proxy Feature Extractor Sharing for Model Heterogeneous Personalized Federated Learning。简单说,它让结构不同的客户端共享一个轻量的"代理特征提取器"来交换知识,同时保留各自的本地模型和个性化头部,既绕开了模型异构,又照顾到了数据分布不同带来的个性化需求。

这篇文章我会从背景动机、核心机制、代码复现思路、实验评估到调参避坑一条线拆完。适合正在研究模型异构联邦、准备复现个性化联邦算法的同学,也适合被端侧模型不统一搞得头疼的工程朋友。读完你至少能回答三个问题:代理特征提取器到底在解决什么?它在服务端和客户端之间怎么流转?落地时最容易踩哪些坑?

1. 背景与动机:为什么一定要做模型异构个性化联邦

1.1 同构联邦的尴尬:算力差异被强制拉平

传统联邦学习的出发点很纯粹:数据不动模型动,客户端在本地算梯度,服务端汇总更新。FedAvg 能成立有一个隐藏前提——所有参与者使用结构完全一样的模型,这样权重才能逐层做平均。但真实场景里这个前提几乎不成立。某公司要在一批手机设备上做联邦学习,旗舰机的内存和算力足够跑一个 ResNet 级别的模型,老机型可能只带得动轻量 CNN。强行走同构,要么所有人都用最弱模型,性能天花板被拉低;要么老设备根本无法参与训练,可用数据量下降。

模型异构带来的第一个问题是权重无法对齐。两个网络中间的卷积核个数、隐藏层维度、归一化参数都不一样,参数张量形状不匹配,逐层平均根本没有数学意义。就算强行用一些小 trick 把维度补全,特征空间的语义也完全对不上。A 模型第 3 层学到的边缘纹理,和 B 模型第 3 层学到的语义概念,很可能不是一个东西,平均之后既不是 A 也不是 B。

1.2 更麻烦的是数据分布:Non-IID 下的个性化需求

模型异构之外还有第二重压力:每个客户端的数据分布不是独立同分布的。用术语讲叫 Non-IID,现实中表现为标签偏移、特征偏移、数量不平衡。不同客户端可能是不同地区门店的设备,记录的数据风格不同;也可能是不同个人使用的手机,产生的行为数据差异很大。

这种场景下,全局最优解往往不是每个客户端的最优解。你希望学到的是"大家都认可的公共知识",同时每个客户端在公共知识之上再做本地适应。这就是个性化联邦学习的意义。于是问题变成了:模型异构和个性化这两个需求同时放在一起,应该怎么设计方法?pFedES 给出的答案是:公共知识可以放在一个代理特征提取器上,个性化知识留在本地模型里。

1.3 现有技术路线的三条岔路与共同短板

过去几年,模型异构联邦的基本思路大致分成三路。

第一路是正则化与局部微调路线。FedProx 在 FedAvg 基础上加了客户端本地模型与全局模型的距离惩罚,Per-FedAvg 引入元学习的思想。问题在于它们大多还是假设或者弱化模型同构,真正完全异构时不好用。

第二路是知识蒸馏路线。FedMD、FedDistill 这类方法通过公共数据集或者代理数据,在客户端之间传递软标签知识。它们可以突破结构限制,因为蒸馏的是模型输出而不是参数。缺点是要么需要一个大家都能访问的公共数据集,这在隐私敏感场景里很难办到;要么软标签质量高度依赖公共数据与实际数据分布的相似程度,公共数据和真实业务数据差太远,蒸馏出来的知识就歪了。

第三路是表征空间对齐路线。想方设法让不同结构的模型将样本映射到一个共享向量空间,比如固定某一层的宽度或者设定一个公共投影头。这类方法对模型结构的自由度限制比较多,不算真正的"任意异构"。

这几路都各自有用,但共同短板是:没有把"共享什么"这件事做得既轻又通用。要么需要额外数据集,要么要求模型部分结构对齐,要么只适合窄范围的异构。pFedES 的思路是从"共享一个代理特征提取器"这个角度切入的。

1.4 pFedES 的切入点:共享"代理",保留个性

pFedES 的核心词汇是 Proxy Feature Extractor,代理特征提取器。你可以把它理解成一个轻量级的公共"翻译官网络"。它本身不需要与任何客户端模型结构一致,因为它的任务不是替客户端干活,而是承接所有客户端想要共享的知识。

具体到机制上:每个客户端在本地训练时,同时跑自己的本地模型和一个代理特征提取器。真实标签用来监督本地模型,代理特征提取器通过知识蒸馏的方式学习本地模型的输出分布。客户端之间不共享原始模型参数,只共享代理特征提取器的参数。服务端把各个客户端更新过的代理特征提取器做加权平均,再分发回去。这样一轮一轮下来,公共知识在代理提取器里越来越丰富,本地模型又始终保留个性化结构。标题里的"Generalized"我理解就是在强调:这个方法不对客户端结构做限定,不要求公共标签,也不依赖集中式代理数据集,扩展性比早期蒸馏方案强不少。

还有一个容易被忽略的细节:用户没有直接上传原始特征向量或者原始模型权重,而是上传一个经过蒸馏约束的轻量提取器,这在隐私表现上比裸传梯度要好一截。当然,说完全没泄露是骗人的,这一点后面我会专门谈。

2. 核心机制拆解:代理特征提取器是怎么共享的

2.1 先理解"特征空间对齐"的必要性

模型异构之所以难,核心在于特征空间不对齐。我说一个特别简单的类比:两个人分别用中文和英文写同一篇新闻,内容是一样的,但你不能把他们的句子逐字相加成一篇新文章。神经网络里的特征表示就好比"语言",每个模型的隐藏层有自己的"词汇表"和"语法",直接平均参数等于把中文句子和英文句子按字硬拼。

pFedES 的办法是引入一个统一编码的"翻译官"。所有客户端在本地都加载同一个代理特征提取器,输入同一批样本,输出一个固定维度的特征向量和对应的软标签。这个代理特征提取器就像约定好的通用语言,客户端之间通过它来对齐语义,而不是强行对齐网络权重。共享的不是结构,而是"对不同样本应该如何提取信息"的能力。

2.2 客户端本地更新的三段式结构

每一个参与训练的客户端,本地实际同时维护两个网络:任务模型(local model)和代理特征提取器(proxy)。任务模型的结构任意,可以是一个三层小 CNN,也可以是带残差连接的模型,服务端完全不关心。代理特征提取器是全局统一的,所有客户端从服务端拿到的都是同一份参数。

一次本地前向计算会走两条路径。第一条路径:样本输入本地模型,得到本地特征,再进本地分类头得到本地预测 logits,这个 logits 用真实标签做交叉熵监督。第二条路径:同样一批样本输入代理特征提取器,得到代理特征和代理 logits,代理 logits 的监督信号不是真实标签,而是"本地模型对这批样本的预测分布"。换句话说,代理特征提取器学的是"任务模型是怎么看这批数据的"。

这里面有一个很容易踩坑的细节:当代理 logits 在做知识蒸馏学习时,本地模型的 logits 应该被视为固定目标(stop-gradient),只让代理特征提取器的参数更新。如果不这样做,两个模型会互相追逐,训练目标一直在移动,很容易发散。实现上就是用 detach() 把本地 logits 从计算图里摘出来。

2.3 服务端聚合与分发:异构模型的关键解耦点

服务端做的事情非常干净:把各客户端返回的代理特征提取器做加权平均。权重一般用客户端本地样本数量,这和 FedAvg 的加权逻辑一致。因为唯一被聚合的结构是代理特征提取器,它的结构是全局统一的,所以平均操作是完全合法的。本地任务模型从头到尾不上传参数,服务端根本不知道也不关心客户端用的是什么结构。

这个设计把问题和方案做了一个漂亮的解耦:异构问题交给了"各管各的本地结构"来解决,协作问题交给了"公共代理提取器"来解决。这也是它在工程上很吸引人的原因——不需要客户端把自己的模型结构上报,更不需要为了对齐而改模型设计,老设备和强设备各跑各的,只在代理提取器层面汇合。

2.4 为什么用蒸馏而不是共享特征向量

有的方法会让客户端直接上传特征向量到服务端做全局对齐,乍看更直接,但有三个问题。第一,特征向量里可能残留身份信息和敏感信息,中间层的表征经常能反推出原始数据的一些属性,隐私风险不可控。第二,不同客户端的特征向量分布天然不同,服务端拿到一堆分布漂移很大的向量,很难统一处理。第三,原始特征向量是稠密的,通信开销比只传一个轻量模型还大。

蒸馏方案传递的是"类别关系"这种抽象知识。真实标签是硬目标,本地模型输出的软分布是软目标,软目标里包含了类间相似度的信息。比如一张猫的图片,模型可能认为它 80% 像猫、15% 像狗、5% 像兔子,这 15% 和 5% 恰恰是知识迁移的关键。代理提取器学到的就是这个细粒度的类间关系,而不是某个客户端的具体特征向量。

蒸馏温度 T 在这里起放大或压缩类间关系的作用。温度越高,输出分布越平滑,类间相对差异保留得越完整;温度越低,分布越接近 one-hot,知识越接近真实标签。联邦场景里我建议从 T=3 开始试,太低不行,太高会把噪声也放大。

2.5 关于"广义"的理解边界

标题里 Generalized 给我的信息是:它试图覆盖三种常见的异构限制。一是客户端模型结构异构,从卷积网络到多层感知机都能参与,不影响知识传递。二是标签空间异构,每个客户端即使只有部分类别的样本,代理提取器依然可以借助本地软标签把这些类别的判别知识带进公共体系。三是不依赖公共数据集,传统蒸馏联邦常常需要一个公共代理数据集来对齐,pFedES 把公共数据集这个外部依赖干掉,改成在客户端本地数据上做蒸馏,实际落地时省去很多隐私合规上的麻烦。

但"广义"不是无限广义。如果客户端之间的数据完全分布在不同的域,比如一个是医疗影像,一个是自然图像,类别又完全不重叠,任何知识蒸馏方法都很难传递有效信息。理解它的边界,比吹捧它的能力更重要。

3. 从论文到实现:我复现 pFedES 的方案与代码骨架

3.1 环境、数据切分与异构模型模拟

先说环境。我自己做复现时用的是 PyTorch,因为动态图和 detach 操作在实现蒸馏逻辑时很方便。数据方面,经典实验通常用 EMNIST 或 CIFAR-10/100。模拟联邦 Non-IID 最常见的手段是狄利克雷分布采样:为每个类别生成一个分布,每个客户端按这个分布抽取样本,参数 alpha 越小,每个客户端持有的类别越集中,Non-IID 程度越高。建议同时测 alpha=0.5 和 alpha=0.1 两个档位。

异构模型模拟要克制。不要一上来就给 20 个客户端各配一种结构,实验解释性会变得很差。我习惯把客户端分成三组:一组用两层小 CNN,一组用带残差的稍大 CNN,一组用 MLP。三组结构的特征维度可以完全不同,但最后分类的类别数必须一致,因为分类头输出的 logits 要参与蒸馏。分组的好处是能单独看每组模型的个性化提升幅度,而不是只看一个平均数字。

3.2 代理特征提取器的结构选择与初始化

代理特征提取器的参数量是第一个要平衡的点。它太大,低算力客户端每轮要多算一份前向和反向,负担重;它太小,承载不了异构模型蒸馏出来的知识,成为信息瓶颈。我用过的最省心的配置是一个轻量 CNN:两到三个卷积块加一个全局池化,然后接一个固定维度(比如 128 维)的嵌入层和一个全连接分类头。

下面是示意代码,只保留关键逻辑:

class ProxyExtractor(nn.Module): def __init__(self, in_channels, embed_dim=128, num_classes=10): super().__init__() self.encoder = nn.Sequential( nn.Conv2d(in_channels, 32, kernel_size=3, padding=1), nn.ReLU(), nn.MaxPool2d(2), nn.Conv2d(32, 64, kernel_size=3, padding=1), nn.ReLU(), nn.MaxPool2d(2), nn.AdaptiveAvgPool2d(1), ) self.embed = nn.Linear(64, embed_dim) self.head = nn.Linear(embed_dim, num_classes) def forward(self, x): feat = self.encoder(x) feat = feat.view(feat.size(0), -1) embed = self.embed(feat) logits = self.head(embed) return logits, embed

代理特征提取器要和客户端任务模型的输入大小匹配,数据是图像就用卷积,是表格或者文本就用 MLP 或 Transformer 的编码器,这个按场景换即可,核心结构不变。

客户端本地模型就不强制统一,只要能输出 logits 就行:

class LocalModel(nn.Module): def __init__(self, backbone, classifier): super().__init__() self.backbone = backbone self.classifier = classifier def forward(self, x): feat = self.backbone(x) return self.classifier(feat)

这里的 backbone 不同客户端各自定义,代码里不需要任何特殊处理。

3.3 一次通信轮次内的完整训练流程

一轮联邦训练的流程大概是五步。第一步,服务端向本轮选中的客户端分发当前全局代理特征提取器参数。第二步,客户端加载本地模型和代理提取器,在本地数据上训练若干个 epoch。第三步,客户端把更新后的代理提取器参数返回服务端,本地模型参数留在本地。第四步,服务端按样本量加权平均所有返回的代理提取器。第五步,重复下一轮。

客户端内部的优化目标是最关键的地方。我用一个总的 loss:

local_logits = local_model(x) proxy_logits, _ = proxy_model(x) soft_target = F.softmax(local_logits.detach() / T, dim=1) kd_loss = F.kl_div( F.log_softmax(proxy_logits / T, dim=1), soft_target, reduction="batchmean", ) * (T ** 2) ce_loss = F.cross_entropy(local_logits, y) total_loss = ce_loss + alpha * kd_loss

注意local_logits.detach()这一步,它保证了交叉熵只更新本地模型,KL 散度只更新代理提取器。两个模型虽然在同一条数据上训练,但监督信号的流向是完全分开的。这样设计的目的前面说过,是为了避免两个模型互相追逐导致的不收敛。

本地训练 epoch 数建议 1 到 5。epoch 太多,代理提取器在单个客户端上过拟合严重,服务端聚合后震荡;epoch 太少,软标签还没学好就交回去了,蒸馏质量差。我测下来 3 个 epoch 在多数基准上是个稳妥值。

3.4 服务端聚合、EMA 平滑与通信开销控制

服务端聚合不只是简单平均,我做了一个小改进:对代理特征提取器做指数滑动平均,让全局代理参数的更新更平滑。

global_proxy = 0.9 * global_proxy + 0.1 * aggregated_proxy

这个 EMA 阻尼在客户端数据分布差异很大的时候很有用。直白点说,如果这一轮碰巧都是 Non-IID 程度极高的用户,它们的代理提取器更新方向会很偏,EMA 能把这种偶然偏差稀释掉,不让全局参数剧烈抖动。

通信开销方面,因为上传下载的始终是同一个轻量代理提取器,而不是各种不同结构的客户端模型,所以开销是恒定可控的。你甚至可以提前算出来:代理提取器参数量乘以 4 字节再乘 2(上下行),就是单客户端单轮的理论通信量。对比一下 FedAvg 要传整个全局模型,在异构场景下这个优势特别明显。

3.5 评测方案:别只看一个平均准确率

评估个性化联邦学习最忌讳只报一个全局平均测试准确率。我建议至少看三个指标。

第一是"个性化准确率":每个客户端在本地保留的测试集上分别评估本地任务模型,然后取加权平均。这是衡量个性化的核心指标。

第二是"全局代理提取器准确率":拿代理提取器在服务端汇总测试集上评估。它可以反映公共知识的质量。如果代理提取器精度一直很低,说明蒸馏没有传递出有效信息,这时候去查软标签是否失真、温度是否合理。

第三是"异构友好度":对比各个模型组(小 CNN 组、大 CNN 组、MLP 组)的准确率差距。理想情况下,大模型组能保留容量优势,小模型组通过蒸馏从公共知识里受益,而不是被同构基线拖到一个水平线上。

还要加一个稳定性指标:多次随机种子实验的方差。模型异构 + Non-IID 的联邦实验,方差普遍比同构实验大,如果只跑一次就下结论,很容易被随机性欺骗。

4. 为什么有效:结果解读、收益边界与陷阱

4.1 三类典型实验结论的解读

从公开结果和我自己跑过的模拟实验看,pFedES 这种架构在三个维度上都有比较明显的收益。

第一个维度是个性化表现。由于每个客户端保留了自己的本地模型和本地分类头,模型可以针对本地数据分布做专门的调整,平均个性化准确率比强制同构 FedAvg 高是正常的。这个收益本质上是"模型结构自由 + 头部个性化"带来的,代理提取器在中间保证了大家不至于各学各的学到完全分裂。

第二个维度是通信效率。传统 FedAvg 每轮传输整个模型,模型异构场景下甚至要传输多个副本。pFedES 只传一个轻量代理提取器,通信量和客户端模型结构无关,预算容易控制。在端侧网络环境不稳定的场景里,这个优势往往是能不能落地的关键。

第三个维度是收敛稳定性。相比直接在异构特征空间上做匹配,蒸馏带来的软目标更平滑,梯度方向更稳定。我观察到的现象是:早期轮次代理提取器精度快速爬升,本地模型也随之受益;后期即使数据分布偏斜,也很少出现剧烈的精度来回震荡,前提是超参没有设坏。

4.2 收益来源的机理分析

为什么一个看起来简单的代理提取器能承担这么大的作用?我认为有三个机制在同时起作用。

第一,隐式公共特征空间的形成。所有客户端共享同一个代理提取器,它不断吸收各个客户端模型对数据的"看法",实际上是在异构结构之间建立了一个统一的中间表征空间。本地模型虽然结构各异,但都在通过蒸馏约束向这个空间靠拢,等于有了一条软性的对齐通道。

第二,蒸馏本身的正则效应。软标签提供了比 one-hot 标签更丰富的监督信息,它对本地模型的训练也有一定的正则作用。在客户端本地数据很少的时候,这种正则能明显减轻过拟合。这可以理解为:代理提取器把其他客户端的知识以"平滑约束"的形式传给了本地模型。

第三,容量错配下的知识补偿。大模型能从数据里学到更细腻的特征,这些特征通过软标签传给代理提取器,代理提取器再间接影响小模型。小模型因此获得了超出它自身容量限制的部分"学习经验",虽然不能完全复现大模型的能力,但比闭门造车强得多。

4.3 必须警惕的收益边界

再好的方法也有边界。代理提取器的容量是第一条边界:它太小时,所有异构模型的知识被压进一个狭窄的瓶颈,蒸馏出来的软标签信息严重降级;它太大时,低算力客户端训练负担加重,甚至不如直接跑完整模型。第二条边界是数据分布的偏移程度:如果客户端之间不仅标签分布不同,连输入域都不同,代理提取器很难同时讨好所有域,最终可能两头不讨好。第三条边界在隐私上。虽然上传的是代理提取器而非原始特征或本地模型,但代理提取器是在真实本地数据上训练的,理论上仍然可能编码部分数据分布信息。真要用于强隐私场景,需要配合差分隐私噪声、梯度裁剪或者安全聚合。

实践中最常见的三个误解,我也列一下:有人把代理提取器当成全局模型来用,拿它做服务端推理,这其实是误用,代理提取器的本职是知识传递,不是最终推理模型;有人以为实现起来就是普通蒸馏加联邦,忽略了 stop-gradient 和聚合频率这些细节,结果训练不稳定;还有人只在 CIFAR-10 这种简单数据集上看到提升就下结论,真实场景里模型异构往往伴随域偏移,必须单独做域偏移实验验证。

5. 实战中的坑与调参经验:给你一份避坑清单

5.1 精度不升反降时的排查顺序

模型异构联邦实验出现负优化的情况不少见,而且原因往往不是单一的。我把自己常用的排查顺序整理成了一张表。

现象可能原因排查与解决办法
本地模型精度和单机训练差不多代理提取器没起作用检查 kd_loss 是否真的在下降;去掉 detach 后是否发散;alpha 是否设得太小
代理提取器不收敛本地 epoch 过多或 T 过低减少本地 epoch;把温度升到 3 到 5;确认 soft_target 没有退化成 one-hot
全局聚合后精度震荡客户端数据 Non-IID 太重使用 EMA 平滑;提高参与率;对代理更新做梯度裁剪
小模型组没受益代理提取器容量不足增加 embed_dim 或卷积通道数;检查小模型输入分辨率和代理提取器是否匹配
大模型组反而掉点alpha 太大、蒸馏约束过强降低 alpha 到 0.1 档次;只让代理提取器学本地模型,不要让本地模型被反向影响

这里有一个我自己的经验:先让代理提取器在一个客户端上单独训练几个 epoch,如果它连单个客户端的数据分布都没法学出有区分度的特征,那问题很可能出在代理提取器结构或输入预处理上,先修这个再上联邦。

5.2 聚合与通信的精细化控制

服务端聚合策略可以做得更细。参与率方面,建议每轮至少采样 20% 的客户端,样本量太少的轮次,加权平均的方差会非常大。聚合权重方面,直接用样本量加权简单有效,但要注意:如果某个客户端本地样本数量特别大,它的代理提取器更新会在聚合里占主导,这时候可以做个权重上限截断,比如单个客户端权重不超过 0.3。

梯度裁剪也值得加。客户端本地训练结束后,计算代理提取器参数的更新量,如果更新量的 L2 范数超过阈值(我常用 5.0),按比例缩放。理由是极端 Non-IID 客户端可能产生非常大的更新,不加裁剪会把全局代理提取器带偏。

本地步长和多轮聚合的配合也要留意。客户端本地训练 1 个 epoch 时,每轮通信可以很频繁,但服务端聚合不能太激进;本地训练 3 到 5 个 epoch 时,聚合间隔可以适当拉大。我通常的做法是:固定每轮客户端本地跑 3 个 epoch,然后每 5 轮做一次全局 EMA 更新,相当于给公共知识一个沉淀期。

5.3 隐私增强的方向

前面反复强调代理提取器不是绝对隐私安全。如果需要在敏感场景部署,我推荐从三个方向叠加防护。

第一,梯度裁剪配合噪声注入。客户端在返回代理提取器更新前,先裁剪更新范数,再加一定量的高斯噪声,这相当于在联邦学习里引入差分隐私的标准做法。代价是蒸馏软标签的信噪比下降,精度会有所损失,需要根据隐私预算重新调 alpha。

第二,安全聚合。服务端通过安全多方计算协议聚合所有客户端的代理更新,服务端只能拿到加总后的结果,看不到单个客户端的代理提取器。这解决的是"聚合过程"中的隐私泄露。

第三,只上传蒸馏统计量而不是完整代理参数。某些场景可以只传每个类别的平均 soft prediction,服务端用这些统计量做聚合和下发。这种做法的特征是更粗糙,知识传递效率会打折扣,但隐私保护更直观。实际选哪种,取决于合规要求甚至强于精度要求。

5.4 场景迁移的扩展思考

pFedES 这类架构扩展性很强,我在自己的模拟项目里试过几个方向,简单分享。

一个是跨域联邦。某医疗场景中,不同参与方的成像设备、扫描参数、病例分布都不一样,而且各方往往各有一套自己的诊断模型。把 pFedES 的代理提取器换成它们能统一加载的轻量编码器,再配合本地诊断头和蒸馏,是可以做到"资源不出本地,知识共同进步"的。这个方向我特别看好,因为它精准命中了"结构异构 + 数据私有 + 数据分布偏移"三个痛点。

另一个是端侧小模型与大模型协同。如果把云端大模型看作一个特殊客户端,它的软标签可以下发给代理提取器,端侧小模型又通过代理提取器间接受益,这等于建立了一条从大模型向小模型的知识传送带。在边缘设备算力受限、又要享受大模型表达力的场景里,这个思路比直接给端侧部署大模型可行性高得多。

还有一个偏前瞻的方向:把代理提取器和联邦半监督结合起来。现实中很多客户端只有少量有标签数据、大量无标签数据,代理提取器可以先用有标签数据学出一个基础表示,再利用无标签数据的伪标签参与蒸馏。这属于扩展研究,不是 pFedES 的原生能力,但设计空间是打开的,做研究的朋友可以往这个方向挖。

最后,说说我复现下来的真实体会

pFedES 不是那种惊艳到让你拍桌子的方法,但它是一个思路非常干净、工程上可落地的架构。我复现过不少模型异构联邦的方案,pFedES 最让我欣赏的一点是它把问题拆得足够清晰:协作的事交给代理提取器,个性的事交给本地模型,各司其职。

实际跑下来,我最深的体会是超参之间是耦合的。温度 T 影响软标签平滑度,alpha 控制蒸馏强度,代理提取器容量决定信息瓶颈,这三者必须一起调。我建议的起点是:T=4,alpha=0.1,代理提取器嵌入维度 128,本地 epoch=3,服务端 EMA 衰减 0.9。先跑通,再往两个方向探索:alpha 往上走观察大模型组是否被压制,代理容量往上走观察小模型组是否继续受益。另外,每轮记录代理提取器在服务端测试集上的精度,把它当作训练健康的晴雨表——它连续多轮不涨,说明知识传递出问题了,这时候优先查软标签和蒸馏梯度。

最后再分享一个小技巧:无论你最终的项目是什么,先在白盒环境里把每个客户端本地模型对同一批测试样本的 logits 分布打印出来,对比它们和代理提取器 logits 分布的 KL 距离。距离一直在减小,说明共享是真的发生了;距离纹丝不动,说明你的代理提取器只是在跟着本地模型瞎转,蒸馏没有真正建立联系。这个观察比任何指标都更能帮你判断架构是否搭对。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进