AIoT-MLSys-Lab / FedRolex

[NeurIPS 2022] "FedRolex: Model-Heterogeneous Federated Learning with Rolling Sub-Model Extraction" by Samiul Alam, Luyang Liu, Ming Yan, and Mi Zhang
Apache License 2.0
60 stars 15 forks source link

Bug for client optimizer #8

Open Sherrylife opened 1 year ago

Sherrylife commented 1 year ago

Hi, @samiul272 , After my careful debugging, I finally found the problem. I have found that if I take the repository code directly and run the default command in README.md: python main_resnet.py --data_name CIFAR10 \ --model_name resnet18 \ --control_name 1_100_0.1_non-iid-2_dynamic_a1-b1-c1-d1-e1_bn_1_1 \ --exp_name roll_test \ --algo roll \ --g_epoch 3200 \ --l_epoch 1 \ --lr 2e-4 \ --schedule 1200 \ --seed 31 \ --num_experiments 3 \ --devices 0 1 2 then each client locally uses the Adam optimizer instead of the SGD optimizer!

I guess the reason for this is that your default optimizer in config.yml is Adam. Although you changed the value of cfg['optimizer_name'] in the process_control function in the utils.py file, this change is only valid for the main process. However, the ray framework runs in parallel, assigning a different process to each client, so when the client declares a new optimizer in step function, all the parameters it gets from cfg are still parameters in the config.yml file, which means that the client is actually running the Adam optimizer. To test this, we print out the information for the optimizer on the client side, as shown below. image Then, ① set optimizer_name to Adam in the config.yml file (which is also the default setting in your code), run the command above and we can see the result as follow: image ② set optimizer_name to SGD in the config.yml file, run the command above and we can see that: image After testing, mode ① can achieve the effect of Table 3, while mode ② cannot be trained. That's why I ran out of practice in issue # 7.

samiul272 commented 1 year ago

Hi @Sherrylife, thanks for letting me know. I will review the issue. As far as I remember, the clients receive the config file from the main process during initialization. I think I put the config in main in Ray's shared memory using ray.put(cfg). I could be wrong. I will check what is actually being passed around.