Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DiversityPartitioner中缺少lmbalance项 #41

Open
Lyy838354973 opened this issue Sep 15, 2023 · 9 comments
Open

DiversityPartitioner中缺少lmbalance项 #41

Lyy838354973 opened this issue Sep 15, 2023 · 9 comments

Comments

@Lyy838354973
Copy link

class DiversityPartitioner(BasicPartitioner):
"""`Partition the indices of samples in the original dataset according to numbers of types of a particular
attribute (e.g. label) . This way of partition is widely used by existing works in federated learning.

Args:
    num_clients (int, optional): the number of clients
    diversity (float, optional): the ratio of locally owned types of the attributes (i.e. the actual number=diversity * total_num_of_types)
    imbalance (float, optional): the degree of imbalance of the amounts of different local_movielens_recommendation data (0<=imbalance<=1)
    index_func (int, optional): the index of the distribution-dependent (i.e. label) attribute in each sample.
"""
def __init__(self, num_clients=100, diversity=1.0, index_func=lambda X:[xi[-1] for xi in X]):
    self.num_clients = num_clients
    self.diversity = diversity
    self.index_func = index_func

貌似imbalance项没有在调用里

@WwZzz
Copy link
Owner

WwZzz commented Sep 15, 2023

class DiversityPartitioner(BasicPartitioner): """`Partition the indices of samples in the original dataset according to numbers of types of a particular attribute (e.g. label) . This way of partition is widely used by existing works in federated learning.

Args:
    num_clients (int, optional): the number of clients
    diversity (float, optional): the ratio of locally owned types of the attributes (i.e. the actual number=diversity * total_num_of_types)
    imbalance (float, optional): the degree of imbalance of the amounts of different local_movielens_recommendation data (0<=imbalance<=1)
    index_func (int, optional): the index of the distribution-dependent (i.e. label) attribute in each sample.
"""
def __init__(self, num_clients=100, diversity=1.0, index_func=lambda X:[xi[-1] for xi in X]):
    self.num_clients = num_clients
    self.diversity = diversity
    self.index_func = index_func

貌似imbalance项没有在调用里

你好,找到一组数据分布同时满足diversity比例、用户数据量分布、数据集属性分布是个比较复杂的问题,即假设用户持有数据数量构成一个矩阵,其中每个元素是某用户持有某类数据的数量,整理一下可以发现找这个分布相当于优化一个非线性整数规划问题,需要调用求解器进行求解。我将在后续的更新中找到一个合适的方式将imbalance插入进去。

@Lyy838354973
Copy link
Author

类 DiversityPartitioner(BasicPartitioner):“”“'根据特定属性(例如标签)的类型数量对原始数据集中的样本索引进行分区。这种划分方式被联邦学习中的现有工作广泛使用。

Args:
    num_clients (int, optional): the number of clients
    diversity (float, optional): the ratio of locally owned types of the attributes (i.e. the actual number=diversity * total_num_of_types)
    imbalance (float, optional): the degree of imbalance of the amounts of different local_movielens_recommendation data (0<=imbalance<=1)
    index_func (int, optional): the index of the distribution-dependent (i.e. label) attribute in each sample.
"""
def __init__(self, num_clients=100, diversity=1.0, index_func=lambda X:[xi[-1] for xi in X]):
    self.num_clients = num_clients
    self.diversity = diversity
    self.index_func = index_func

貌似不平衡项没有在调用里

你好,找到一组数据分布同时满足diversity比例、用户数据量分布、数据集属性分布是个比较复杂的问题,即假设用户持有数据数量构成一个矩阵,其中每个元素是某用户持有某类数据的数量,整理一下可以发现找这个分布相当于优化一个非线性整数规划问题,需要调用求解器进行求解。我将在后续的更新中找到一个合适的方式将不平衡插入进去。

还想请问一下,现在的库能实现波动客户端集吗,就是初始化定义一开始的客户端,然后在需要新的客户端加入时,再进行数据的分配,并将其加入训练过程,如果目前不能实现的话,我是否能够改动实现这一效果

@WwZzz
Copy link
Owner

WwZzz commented Sep 17, 2023

定义一开始的客户端,然后在需要新的客户端加入时,再进行数据的分配,并将其加入训练过程,如果目前不能实现的话,我是否能

你好,1)目前数据集的分配不能够动态地进行,每个task生成后用户的数据分布就是固定的了,这种设置也比较贴合实际情形;2)另一方面我不明确你所描述的波动的客户端的具体含义;如果是指部分用户对于服务器在训练早期不可见,而后期训练过程中动态加入的话,可以在Simulator中通过设置用户的活跃性实现,比如分别设置每个用户活跃的起点轮数,即从某一轮开始后变成始终活跃;这样服务器通过available_clients属性可以访问每一轮活跃的用户,从而无法在早期接触到没加入的用户;如果指的是服务器主动增添新的客户端的话,我认为可以不对用户做修改,通过设置服务器的行为实现相同的效果,比如一开始只与self.clients中的前10个用户交互,后面逐步扩充交互用户的规模

@Lyy838354973
Copy link
Author

定义一开始的客户端,然后在需要新的客户端加入时,再进行数据的分配,并将其加入训练过程,如果目前不能实现的话,我是否能

你好,1)目前数据集的分配不能够动态地进行,每个task生成后用户的数据分布就是固定的了,这种设置也比较贴合实际情形;2)另一方面我不明确你所描述的波动的客户端的具体含义;如果是指部分用户对于服务器在训练早期不可见,而后期训练过程中动态加入的话,可以在Simulator中通过设置用户的活跃性实现,比如分别设置每个用户活跃的起点轮数,即从某一轮开始后变成始终活跃;这样服务器通过available_clients属性可以访问每一轮活跃的用户,从而无法在早期接触到没加入的用户;如果指的是服务器主动增添新的客户端的话,我认为可以不对用户做修改,通过设置服务器的行为实现相同的效果,比如一开始只与self.clients中的前10个用户交互,后面逐步扩充交互用户的规模

集合波动性就是可用的客户可能在不同的时间发生变化,并且可能有新的客户加入培训。我所设想的理想情况是能够在初始化是先设定一批客户端,在随后的训练过程需要有新的客户端集加入时,独立的进行数据分配并将其加入系统中,如果现在没有办法解决,我会考虑您所说的解决方案,您也可以考虑一下这方面的代码,我认为以后的联邦学习可能也会从波动性入手

@WwZzz
Copy link
Owner

WwZzz commented Sep 18, 2023

定义一开始的客户端,然后在需要新的客户端加入时,再进行数据的分配,并将其加入训练过程,如果目前不能实现的话,我是否能

你好,1)目前数据集的分配不能够动态地进行,每个task生成后用户的数据分布就是固定的了,这种设置也比较贴合实际情形;2)另一方面我不明确你所描述的波动的客户端的具体含义;如果是指部分用户对于服务器在训练早期不可见,而后期训练过程中动态加入的话,可以在Simulator中通过设置用户的活跃性实现,比如分别设置每个用户活跃的起点轮数,即从某一轮开始后变成始终活跃;这样服务器通过available_clients属性可以访问每一轮活跃的用户,从而无法在早期接触到没加入的用户;如果指的是服务器主动增添新的客户端的话,我认为可以不对用户做修改,通过设置服务器的行为实现相同的效果,比如一开始只与self.clients中的前10个用户交互,后面逐步扩充交互用户的规模

集合波动性就是可用的客户可能在不同的时间发生变化,并且可能有新的客户加入培训。我所设想的理想情况是能够在初始化是先设定一批客户端,在随后的训练过程需要有新的客户端集加入时,独立的进行数据分配并将其加入系统中,如果现在没有办法解决,我会考虑您所说的解决方案,您也可以考虑一下这方面的代码,我认为以后的联邦学习可能也会从波动性入手

你好,可用的用户可能在不同的时间发生变化这个概念在FL里现有工作一般称作Intermittent Client Availability,具体论文包括MIFA、F3AST等。有新的用户加入训练有一篇忘了名字的ICML论文称作Flexiable Participation。如果是实现Client Availability的话,我想这个tutorials可以帮到你https://flgo-xmu.github.io/Tutorials/4_Simulator_Customization/4.1_Client_Availability/ ,此外我觉得从Client Availability角度去模拟Flexiable Participation也是可行的。

@Lyy838354973
Copy link
Author

1695124692243

请问我设置了self.roundwise_fixed_availability = True,为什么每轮可用设备还随着被选择客户端数量减少

@WwZzz
Copy link
Owner

WwZzz commented Sep 19, 2023

轮可用设备还随着被选择客户端数量减少

你好,这个变量的含义是:在同一个聚合轮次内,用户的availability是否会随着时间变化。我贴了一个例子来解释这件事:这里simulator1是roundwise_fixed_availability=True, simulator2是False(后面简称该变量为rfa)。然后我稍微修改了下fedavg算法,让服务器在每个iterate里通过self.gv.clock.step(1)让时间强制流逝1个时间单位。此时若rfa为True,则用户的availability在下次模型聚合之前,不会随着时间变化而变化;若rfa为False,则用户的availability会随着时间变化而变化,与聚合轮次无关。

import flgo
import flgo.algorithm.fedavg as fedavg
import flgo.simulator.base as fsb
import random

class MySimulator1(fsb.BasicSimulator):
    def update_client_availability(self):
        if self.gv.clock.current_time==0:
            self.set_variable(self.all_clients, 'prob_available', [1 for _ in self.clients])
            self.set_variable(self.all_clients, 'prob_unavailable', [int(random.random() >= 0.5) for _ in self.clients])
            return
        pa = [0.1 for _ in self.clients]
        pua = [0.1 for _ in self.clients]
        self.set_variable(self.all_clients, 'prob_available', pa)
        self.set_variable(self.all_clients, 'prob_unavailable', pua)
        self.roundwise_fixed_availability = True

class MySimulator2(fsb.BasicSimulator):
    def update_client_availability(self):
        if self.gv.clock.current_time==0:
            self.set_variable(self.all_clients, 'prob_available', [1 for _ in self.clients])
            self.set_variable(self.all_clients, 'prob_unavailable', [int(random.random() >= 0.5) for _ in self.clients])
            return
        pa = [0.1 for _ in self.clients]
        pua = [0.1 for _ in self.clients]
        self.set_variable(self.all_clients, 'prob_available', pa)
        self.set_variable(self.all_clients, 'prob_unavailable', pua)
        self.roundwise_fixed_availability = False

class Server(fedavg.Server):
    def iterate(self):
        print("The number of currently available clients: {}".format(len(self.available_clients)))
        print("The availability of clients being selected at last round: {}".format([(cid in self.available_clients) for cid in self.selected_clients]))
        self.gv.clock.step(1) # 等待1个时间单位
        print('After a time unit...')
        print("The number of currently available clients: {}".format(len(self.available_clients)))
        print("The availability of clients being selected at last round after a second: {}".format([(cid in self.available_clients) for cid in self.selected_clients]))
        self.selected_clients = self.sample()
        models = self.communicate(self.selected_clients)['model']
        self.model = self.aggregate(models)
        return True

class MyFedavg:
    Server = Server
    Client = fedavg.Client

if __name__=='__main__':
    task = 'my_task'
    flgo.init(task, MyFedavg, option={'gpu':0, 'num_steps':1, 'sample':'uniform_available', 'num_rounds':5}, Simulator=MySimulator1).run()
    flgo.init(task, MyFedavg, option={'gpu': 0, 'num_steps': 1, 'sample': 'uniform_available', 'num_rounds': 5}, Simulator=MySimulator2).run()

运行这段代码后,可以看到屏幕上的输出为:

# Simulator1-rfa=True的情形
2023-09-19 11:00:46,006 fedbase.py run [line:253] INFO Eval Time Cost:               1.4580s
The number of currently available clients: 34
The availability of clients being selected at last round: [False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False]
After a time unit...
The number of currently available clients: 34
The availability of clients being selected at last round after a second: [False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False

可以看到在一个时间单位后用户的活跃分布不发生改变。

# Simulator2-rfa=False的情形
The number of currently available clients: 33
The availability of clients being selected at last round: [False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False]
After a time unit...
The number of currently available clients: 35
The availability of clients being selected at last round after a second: [False, False, False, False, False, False, False, True, False, False, False, True, False, False, True, True, False, False, False, False]

可以看到用户的活跃分布在1个时间单位后刷新了。
至于为什么选择用户后活跃用户会变少,我不明确你具体运行的代码;但是被选择的用户的状态将从被选择那一刻开始由idle转为working,working用户在训练完之前不被认作是可以被再次采样的用户(即非“活跃”用户)。

@Lyy838354973
Copy link
Author

请问,在cifar10数据集中,我使用DiversityPartitioner将客户端只塞入了一种标签的数据,设置了100个客户端,每轮选择10个客户端,测试精度出现多个0.1000是什么原因
下面是我的设置:
option = {'proportion':0.1,'num_rounds':50, 'gpu':0,'learning_rate':0.01, 'batch_size':40, 'num_epochs':3}

1697511388808

@WwZzz
Copy link
Owner

WwZzz commented Oct 17, 2023

请问,在cifar10数据集中,我使用DiversityPartitioner将客户端只塞入了一种标签的数据,设置了100个客户端,每轮选择10个客户端,测试精度出现多个0.1000是什么原因 下面是我的设置: option = {'proportion':0.1,'num_rounds':50, 'gpu':0,'learning_rate':0.01, 'batch_size':40, 'num_epochs':3}

1697511388808

你好,这种情况是因为noniid程度太极端,同时local epoch过大,导致模型收敛极慢甚至无法收敛;此时需要调小local epoch(或直接设置num_steps替代num_epochs)或是调小learning_rate,才能观察到数十个round内损失稳定下降;或是用使用一些针对niid问题进行了优化的算法替代fedavg;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants