Skip to content

非独立同分布数据处理

Non-IID(非独立同分布)数据是联邦学习的核心挑战。各参与方的数据分布不同,导致模型收敛困难、性能下降。

Non-IID数据处理

Non-IID 类型

类型描述示例严重程度
标签偏斜标签分布不同医院A主要看内科,B主要看外科
特征偏斜特征分布不同不同相机拍的照片
概念偏斜同标签不同含义"spam"在不同邮箱含义不同
量级偏斜数据量差异大大医院 vs 小诊所

标签偏斜实验

python
def create_label_skew(dataset, num_clients, skew_degree=0.5):
    """创建标签偏斜的数据划分"""
    # Dirichlet 分布控制偏斜程度
    label_distribution = np.random.dirichlet(
        [skew_degree] * num_clients,
        size=len(dataset.classes)
    )

    client_data = [[] for _ in range(num_clients)]
    for label, proportions in enumerate(label_distribution):
        indices = [i for i, (_, y) in enumerate(dataset) if y == label]
        splits = np.split(indices, (proportions.cumsum() * len(indices)).astype(int))

        for client_id, split in enumerate(splits[:-1]):
            client_data[client_id].extend(split.tolist())

    return client_data

FedAvg 在 Non-IID 下的表现

偏斜程度Dir(0.1)Dir(0.5)Dir(1.0)IID
测试精度65%78%85%92%
收敛轮数500+20010050
客户端漂移严重中等轻微

解决方案

1. 算法改进(FedProx/SCAFFOLD)

python
# FedProx:添加近端正则项
loss = local_loss + (mu / 2) * ||w - w_global||^2

# SCAFFOLD:控制变量修正
corrected_grad = grad - c_local + c_global

2. 数据共享

python
class DataSharing:
    """服务端生成共享数据子集"""

    def __init__(self, sharing_ratio=0.1):
        self.sharing_ratio = sharing_ratio

    def generate_shared_data(self, global_model, num_samples=1000):
        """使用全局模型生成合成数据"""
        # 方法1:从公共数据集中采样
        # 方法2:使用数据蒸馏
        # 方法3:GAN 生成
        return synthetic_data

    def augment_local(self, local_data, shared_data):
        """混合本地数据和共享数据"""
        mixed = local_data + shared_data * self.sharing_ratio
        return mixed

3. 自适应聚合权重

python
class AdaptiveAggregation:
    """根据数据分布调整聚合权重"""

    def compute_weights(self, client_models, val_data):
        """基于验证集性能计算权重"""
        weights = []
        for model in client_models:
            accuracy = self.evaluate(model, val_data)
            weights.append(accuracy)

        # 归一化
        total = sum(weights)
        return [w / total for w in weights]

4. 聚类联邦

python
# 将相似分布的客户端聚类
# 每个聚类内训练一个模型
# 减少聚类内数据异构性
clusters = kmeans(client_data_distributions, k=3)
for cluster in clusters:
    train_federated(cluster.clients)

Non-IID 处理策略

  1. 优先评估 Non-IID 程度(用 KL 散度或 JS 散度)
  2. 轻度偏斜:FedAvg + 数据增强即可
  3. 中度偏斜:FedProx 或 SCAFFOLD
  4. 高度偏斜:聚类联邦 + 个性化
  5. 极端偏斜:考虑是否适合联邦学习

数据共享的隐私风险

服务端共享数据虽然能缓解 Non-IID,但可能泄露参与方信息。共享数据必须:1) 经过 DP 处理;2) 使用合成数据而非真实数据;3) 量尽可能少。

相关资源

最近更新