├── LICENSE ├── requirements.txt ├── environment.yml ├── README.md ├── fl_utils └── construct_models.py ├── FashionMNIST ├── fashion_byz_attack.py ├── fashion_byz_median.py ├── fashion_byz_trimmed.py ├── fashion_lf_attack.py ├── fashion_lf_median.py ├── fashion_lf_trimmed.py ├── fashion_partial_knowledge_attack.py ├── fashion_partial_knowledge_median.py ├── fashion_partial_knowledge_trimmed.py ├── fashion_byz_barfed.py ├── fashion_lf_barfed.py └── fashion_partial_knowledge_arfed.py ├── MNIST ├── mnist_byz_attack.py ├── mnist_lf_attack.py ├── mnist_lf_median.py ├── mnist_byz_median.py ├── mnist_lf_trimmed.py ├── mnist_byz_trimmed.py ├── mnist_partial_knowledge_attack.py ├── mnist_partial_knowledge_median.py ├── mnist_partial_knowledge_trimmed.py ├── mnist_byz_arfed.py └── mnist_lf_arfed.py └── CIFAR ├── cifar_byz_attack.py ├── cifar_byz_median.py ├── cifar_lf_attack.py ├── cifar_lf_median.py ├── cifar_byz_barfed.py └── cifar_lf_barfed.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 eceisik 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # This file may be used to create an environment using: 2 | # $ conda create --name --file 3 | # platform: linux-64 4 | _libgcc_mutex=0.1=main 5 | blas=1.0=mkl 6 | bzip2=1.0.8=h7b6447c_0 7 | ca-certificates=2020.10.14=0 8 | certifi=2020.6.20=py38_0 9 | chardet=4.0.0=pypi_0 10 | click=7.1.2=pypi_0 11 | configparser=5.0.2=pypi_0 12 | cudatoolkit=11.1.74=h6bb024c_0 13 | cycler=0.10.0=py_2 14 | dbus=1.13.18=hb2f20db_0 15 | docker-pycreds=0.4.0=pypi_0 16 | expat=2.2.10=he6710b0_2 17 | ffmpeg=4.3=hf484d3e_0 18 | fontconfig=2.13.1=he4413a7_1000 19 | freetype=2.10.4=h5ab3b9f_0 20 | gitdb=4.0.6=pypi_0 21 | gitpython=3.1.14=pypi_0 22 | glib=2.68.0=h36276a3_0 23 | gmp=6.2.1=h2531618_2 24 | gnutls=3.6.5=h71b1129_1002 25 | gst-plugins-base=1.14.0=hbbd80ab_1 26 | gstreamer=1.14.0=h28cd5cc_2 27 | icu=58.2=hf484d3e_1000 28 | idna=2.10=pypi_0 29 | intel-openmp=2020.2=254 30 | jpeg=9b=h024ee3a_2 31 | kiwisolver=1.3.1=py38h82cb98a_0 32 | lame=3.100=h7b6447c_0 33 | lcms2=2.11=h396b838_0 34 | ld_impl_linux-64=2.33.1=h53a641e_7 35 | libffi=3.3=he6710b0_2 36 | libgcc-ng=9.1.0=hdf63c60_0 37 | libgfortran-ng=7.3.0=hdf63c60_0 38 | libiconv=1.15=h63c8f33_5 39 | libpng=1.6.37=hbc83047_0 40 | libstdcxx-ng=9.1.0=hdf63c60_0 41 | libtiff=4.2.0=h85742a9_0 42 | libuuid=2.32.1=h14c3975_1000 43 | libuv=1.40.0=h7b6447c_0 44 | libwebp-base=1.2.0=h27cfd23_0 45 | libxcb=1.13=h14c3975_1002 46 | libxml2=2.9.10=hb55368b_3 47 | lz4-c=1.9.3=h2531618_0 48 | matplotlib=3.3.4=py38h578d9bd_0 49 | matplotlib-base=3.3.4=py38h62a2d02_0 50 | mkl=2020.2=256 51 | mkl-service=2.3.0=py38he904b0f_0 52 | mkl_fft=1.3.0=py38h54f3939_0 53 | mkl_random=1.1.1=py38h0573a6f_0 54 | ncurses=6.2=he6710b0_1 55 | nettle=3.4.1=hbb512f6_0 56 | ninja=1.10.2=py38hff7bd54_0 57 | numpy=1.19.2=py38h54aff64_0 58 | numpy-base=1.19.2=py38hfa32c7d_0 59 | olefile=0.46=py_0 60 | opencv-python=4.5.1.48=pypi_0 61 | openh264=2.1.0=hd408876_0 62 | openssl=1.1.1l=h7f8727e_0 63 | pandas=1.2.3=py38ha9443f7_0 64 | pathtools=0.1.2=pypi_0 65 | pcre=8.44=he1b5a44_0 66 | pillow=8.1.2=py38he98fc37_0 67 | pip=21.0.1=py38h06a4308_0 68 | promise=2.3=pypi_0 69 | protobuf=3.15.6=pypi_0 70 | psutil=5.8.0=pypi_0 71 | pthread-stubs=0.4=h36c2ea0_1001 72 | pyparsing=2.4.7=pyh9f0ad1d_0 73 | pyqt=5.9.2=py38h05f1152_4 74 | python=3.8.8=hdb3f193_4 75 | python-dateutil=2.8.1=pyhd3eb1b0_0 76 | python_abi=3.8=1_cp38 77 | pytorch=1.9.1=py3.8_cuda11.1_cudnn8.0.5_0 78 | pytz=2021.1=pyhd3eb1b0_0 79 | pyyaml=5.4.1=pypi_0 80 | qt=5.9.7=h5867ecd_1 81 | readline=8.1=h27cfd23_0 82 | requests=2.25.1=pypi_0 83 | scipy=1.6.2=py38h91f5cce_0 84 | seaborn=0.11.1=pyhd3eb1b0_0 85 | sentry-sdk=1.0.0=pypi_0 86 | setuptools=52.0.0=py38h06a4308_0 87 | shortuuid=1.0.1=pypi_0 88 | sip=4.19.13=py38he6710b0_0 89 | six=1.15.0=py38h06a4308_0 90 | smmap=3.0.5=pypi_0 91 | sqlite=3.35.2=hdfb4753_0 92 | subprocess32=3.5.4=pypi_0 93 | tk=8.6.10=hbc83047_0 94 | torchaudio=0.9.1=py38 95 | torchvision=0.10.1=py38_cu111 96 | tornado=6.1=py38h25fe258_0 97 | typing_extensions=3.7.4.3=pyha847dfd_0 98 | urllib3=1.26.4=pypi_0 99 | wandb=0.10.30=pypi_0 100 | wheel=0.36.2=pyhd3eb1b0_0 101 | xorg-libxau=1.0.9=h14c3975_0 102 | xorg-libxdmcp=1.1.3=h516909a_0 103 | xz=5.2.5=h7b6447c_0 104 | zlib=1.2.11=h7b6447c_3 105 | zstd=1.4.5=h9ceee32_0 106 | -------------------------------------------------------------------------------- /environment.yml: -------------------------------------------------------------------------------- 1 | name: fl_env 2 | channels: 3 | - pytorch 4 | - conda-forge 5 | - nvidia 6 | - anaconda 7 | - defaults 8 | dependencies: 9 | - _libgcc_mutex=0.1=main 10 | - blas=1.0=mkl 11 | - bzip2=1.0.8=h7b6447c_0 12 | - ca-certificates=2020.10.14=0 13 | - certifi=2020.6.20=py38_0 14 | - cudatoolkit=11.1.74=h6bb024c_0 15 | - cycler=0.10.0=py_2 16 | - dbus=1.13.18=hb2f20db_0 17 | - expat=2.2.10=he6710b0_2 18 | - ffmpeg=4.3=hf484d3e_0 19 | - fontconfig=2.13.1=he4413a7_1000 20 | - freetype=2.10.4=h5ab3b9f_0 21 | - glib=2.68.0=h36276a3_0 22 | - gmp=6.2.1=h2531618_2 23 | - gnutls=3.6.5=h71b1129_1002 24 | - gst-plugins-base=1.14.0=hbbd80ab_1 25 | - gstreamer=1.14.0=h28cd5cc_2 26 | - icu=58.2=hf484d3e_1000 27 | - intel-openmp=2020.2=254 28 | - jpeg=9b=h024ee3a_2 29 | - kiwisolver=1.3.1=py38h82cb98a_0 30 | - lame=3.100=h7b6447c_0 31 | - lcms2=2.11=h396b838_0 32 | - ld_impl_linux-64=2.33.1=h53a641e_7 33 | - libffi=3.3=he6710b0_2 34 | - libgcc-ng=9.1.0=hdf63c60_0 35 | - libgfortran-ng=7.3.0=hdf63c60_0 36 | - libiconv=1.15=h63c8f33_5 37 | - libpng=1.6.37=hbc83047_0 38 | - libstdcxx-ng=9.1.0=hdf63c60_0 39 | - libtiff=4.2.0=h85742a9_0 40 | - libuuid=2.32.1=h14c3975_1000 41 | - libuv=1.40.0=h7b6447c_0 42 | - libwebp-base=1.2.0=h27cfd23_0 43 | - libxcb=1.13=h14c3975_1002 44 | - libxml2=2.9.10=hb55368b_3 45 | - lz4-c=1.9.3=h2531618_0 46 | - matplotlib=3.3.4=py38h578d9bd_0 47 | - matplotlib-base=3.3.4=py38h62a2d02_0 48 | - mkl=2020.2=256 49 | - mkl-service=2.3.0=py38he904b0f_0 50 | - mkl_fft=1.3.0=py38h54f3939_0 51 | - mkl_random=1.1.1=py38h0573a6f_0 52 | - ncurses=6.2=he6710b0_1 53 | - nettle=3.4.1=hbb512f6_0 54 | - ninja=1.10.2=py38hff7bd54_0 55 | - numpy=1.19.2=py38h54aff64_0 56 | - numpy-base=1.19.2=py38hfa32c7d_0 57 | - olefile=0.46=py_0 58 | - openh264=2.1.0=hd408876_0 59 | - openssl=1.1.1l=h7f8727e_0 60 | - pandas=1.2.3=py38ha9443f7_0 61 | - pcre=8.44=he1b5a44_0 62 | - pillow=8.1.2=py38he98fc37_0 63 | - pip=21.0.1=py38h06a4308_0 64 | - pthread-stubs=0.4=h36c2ea0_1001 65 | - pyparsing=2.4.7=pyh9f0ad1d_0 66 | - pyqt=5.9.2=py38h05f1152_4 67 | - python=3.8.8=hdb3f193_4 68 | - python-dateutil=2.8.1=pyhd3eb1b0_0 69 | - python_abi=3.8=1_cp38 70 | - pytorch=1.9.1=py3.8_cuda11.1_cudnn8.0.5_0 71 | - pytz=2021.1=pyhd3eb1b0_0 72 | - qt=5.9.7=h5867ecd_1 73 | - readline=8.1=h27cfd23_0 74 | - scipy=1.6.2=py38h91f5cce_0 75 | - seaborn=0.11.1=pyhd3eb1b0_0 76 | - setuptools=52.0.0=py38h06a4308_0 77 | - sip=4.19.13=py38he6710b0_0 78 | - six=1.15.0=py38h06a4308_0 79 | - sqlite=3.35.2=hdfb4753_0 80 | - tk=8.6.10=hbc83047_0 81 | - torchaudio=0.9.1=py38 82 | - torchvision=0.10.1=py38_cu111 83 | - tornado=6.1=py38h25fe258_0 84 | - typing_extensions=3.7.4.3=pyha847dfd_0 85 | - wheel=0.36.2=pyhd3eb1b0_0 86 | - xorg-libxau=1.0.9=h14c3975_0 87 | - xorg-libxdmcp=1.1.3=h516909a_0 88 | - xz=5.2.5=h7b6447c_0 89 | - zlib=1.2.11=h7b6447c_3 90 | - zstd=1.4.5=h9ceee32_0 91 | - pip: 92 | - chardet==4.0.0 93 | - click==7.1.2 94 | - configparser==5.0.2 95 | - docker-pycreds==0.4.0 96 | - gitdb==4.0.6 97 | - gitpython==3.1.14 98 | - idna==2.10 99 | - opencv-python==4.5.1.48 100 | - pathtools==0.1.2 101 | - promise==2.3 102 | - protobuf==3.15.6 103 | - psutil==5.8.0 104 | - pyyaml==5.4.1 105 | - requests==2.25.1 106 | - sentry-sdk==1.0.0 107 | - shortuuid==1.0.1 108 | - smmap==3.0.5 109 | - subprocess32==3.5.4 110 | - urllib3==1.26.4 111 | - wandb==0.10.30 112 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ARFED: Attack Resistant Federated Averaging Based on Outlier Elimination 2 | 3 | This repository is the official implementation of __*ARFED: Attack Resistant Federated Averaging Based on Outlier Elimination*__. 4 | The framework and full methodology are detailed in [our manuscript](https://www.sciencedirect.com/science/article/abs/pii/S0167739X22004083). 5 | 6 | ## Install required packages 7 | 8 | ``` 9 | pip install -r requirements.txt 10 | ``` 11 | for pip environment. OR 12 | 13 | ``` 14 | conda env create -f environment.yml 15 | ``` 16 | 17 | To create a conda virtual environment from an environment.yml file. Please see [here](https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#creating-an-environment-from-an-environment-yml-file) for more details. 18 | 19 | 20 | ## How to run 21 | 22 | We performed the experiments for label flipping and Byzantine attacks on MNIST, Fashion MNIST, and CIFAR10 datasets. We compared our results with the median method. The file name list for each data set is as follows. The default setting of experiments is NON-IID organized with a 20% malicious participant ratio. 23 | 24 | | Dataset | Attack Type | Method | File Name | 25 | | ---------------| ------------------ |---------------- | --------------------- | 26 | | MNIST | Byzantine | ARFED | mnist_byz_barfed.py | 27 | | MNIST | Byzantine | Median | mnist_byz_median.py | 28 | | MNIST | Byzantine | Trimmed Mean | mnist_byz_trimmed.py | 29 | | MNIST | Byzantine | No Defense | mnist_byz_attack.py | 30 | | MNIST | Label Flipping | ARFED | mnist_lf_barfed.py | 31 | | MNIST | Label Flipping | Median | mnist_lf_median.py | 32 | | MNIST | Label Flipping | Trimmed Mean | mnist_lf_trimmed.py | 33 | | MNIST | Label Flipping | No Defense | mnist_byz_attack.py | 34 | | MNIST | Partial Knowledge | ARFED | mnist_partial_knowledge_barfed.py | 35 | | MNIST | Partial Knowledge | Median | mnist_partial_knowledge_median.py | 36 | | MNIST | Partial Knowledge | Trimmed Mean | mnist_partial_knowledge_trimmed.py | 37 | | MNIST | Partial Knowledge | No Defense | mnist_partial_knowledge_attack.py | 38 | | Fashion MNIST | Byzantine | ARFED | fashion_byz_barfed.py | 39 | | Fashion MNIST | Byzantine | Median | fashion_byz_median.py | 40 | | Fashion MNIST | Byzantine | Trimmed Mean | fashion_byz_trimmed.py| 41 | | Fashion MNIST | Byzantine | No Defense | fashion_byz_attack.py | 42 | | Fashion MNIST | Label Flipping | ARFED | fashion_lf_barfed.py | 43 | | Fashion MNIST | Label Flipping | Median | fashion_lf_median.py | 44 | | Fashion MNIST | Label Flipping | Trimmed Mean | fashion_lf_trimmed.py | 45 | | Fashion MNIST | Label Flipping | No Defense | fashion_lf_attack.py | 46 | | Fashion MNIST | Partial Knowledge | ARFED | fashion_partial_knowledge_barfed.py | 47 | | Fashion MNIST | Partial Knowledge | Median | fashion_partial_knowledge_median.py | 48 | | Fashion MNIST | Partial Knowledge | Trimmed Mean | fashion_partial_knowledge_trimmed.py | 49 | | Fashion MNIST | Partial Knowledge | No Defense | fashion_partial_knowledge_attack.py | 50 | | CIFAR10 | Byzantine | ARFED | cifar_byz_barfed.py | 51 | | CIFAR10 | Byzantine | Median | cifar_byz_median.py | 52 | | CIFAR10 | Byzantine | Trimmed Mean | cifar_byz_trimmed.py | 53 | | CIFAR10 | Byzantine | No Defense | cifar_byz_attack.py | 54 | | CIFAR10 | Label Flipping | ARFED | cifar_lf_barfed.py | 55 | | CIFAR10 | Label Flipping | Median | cifar_lf_median.py | 56 | | CIFAR10 | Label Flipping | Trimmed Mean | cifar_lf_trimmed.py | 57 | | CIFAR10 | Label Flipping | No Defense | cifar_lf_attack.py | 58 | | CIFAR10 | Partial Knowledge | ARFED | cifar_partial_knowledge_barfed.py | 59 | | CIFAR10 | Partial Knowledge | Median | cifar_partial_knowledge_median.py | 60 | | CIFAR10 | Partial Knowledge | Trimmed Mean | cifar_partial_knowledge_trimmed.py | 61 | | CIFAR10 | Partial Knowledge | No Defense | cifar_partial_knowledge_attack.py | 62 | 63 | ## Citation 64 | Please use the following BibTeX entry for citation: 65 | ```BibTeX 66 | @article{ISIKPOLAT2023626, 67 | title = {ARFED: Attack-Resistant Federated averaging based on outlier elimination}, 68 | journal = {Future Generation Computer Systems}, 69 | volume = {141}, 70 | pages = {626-650}, 71 | year = {2023}, 72 | issn = {0167-739X}, 73 | doi = {https://doi.org/10.1016/j.future.2022.12.003}, 74 | url = {https://www.sciencedirect.com/science/article/pii/S0167739X22004083}, 75 | author = {Ece Isik-Polat and Gorkem Polat and Altan Kocyigit} 76 | } 77 | ``` 78 | -------------------------------------------------------------------------------- /fl_utils/construct_models.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn.functional as F 3 | from torch import nn 4 | from torch import optim 5 | import torchvision 6 | import torchvision.transforms as transforms 7 | from torch.utils.data import TensorDataset 8 | from torch.utils.data import DataLoader 9 | 10 | 11 | 12 | def weights_init(model, torch_manual_seed=2304): 13 | torch.manual_seed(torch_manual_seed) 14 | torch.cuda.manual_seed_all(torch_manual_seed) 15 | torch.backends.cudnn.deterministic = True 16 | torch.backends.cudnn.benchmark = False 17 | 18 | for m in model.modules(): 19 | if isinstance(m, nn.Conv2d): 20 | nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu') 21 | elif isinstance(m,nn.Linear): 22 | nn.init.xavier_normal_(m.weight) 23 | nn.init.constant_(m.bias, 0) 24 | elif isinstance(m, nn.BatchNorm2d): 25 | nn.init.constant_(m.weight, 1) 26 | nn.init.constant_(m.bias, 0) 27 | 28 | 29 | def learning_rate_decay(optimizer_dict, decay_rate): 30 | for i in range(len(optimizer_dict)): 31 | optimizer_name = "optimizer" + str(i) 32 | old_lr = optimizer_dict[optimizer_name].param_groups[0]["lr"] 33 | optimizer_dict[optimizer_name].param_groups[0]["lr"] = old_lr * decay_rate 34 | return optimizer_dict 35 | 36 | def update_learning_rate_decay(optimizer_dict, new_lr): 37 | for i in range(len(optimizer_dict)): 38 | optimizer_name = "optimizer" + str(i) 39 | optimizer_dict[optimizer_name].param_groups[0]["lr"] = new_lr 40 | return optimizer_dict 41 | 42 | 43 | class Net2nn(nn.Module): 44 | def __init__(self): 45 | super(Net2nn, self).__init__() 46 | self.fc1 = nn.Linear(784, 200) 47 | self.fc2 = nn.Linear(200, 200) 48 | self.fc3 = nn.Linear(200, 10) 49 | 50 | def forward(self, x): 51 | x = F.relu(self.fc1(x)) 52 | x = F.relu(self.fc2(x)) 53 | x = self.fc3(x) 54 | return x 55 | 56 | 57 | class Netcnn(nn.Module): 58 | def __init__(self): 59 | super(Netcnn, self).__init__() 60 | self.conv1 = nn.Conv2d(1, 32, 5) 61 | self.conv2 = nn.Conv2d(32, 64, 5) 62 | self.fc1 = nn.Linear(64 * 4 * 4, 512) 63 | self.fc2 = nn.Linear(512, 10) 64 | 65 | def forward(self, x): 66 | x = F.relu(self.conv1(x)) 67 | x = F.max_pool2d(x, 2) 68 | x = F.relu(self.conv2(x)) 69 | x = F.max_pool2d(x, 2) 70 | x = x.view(-1, 64 * 4 * 4) 71 | x = F.relu(self.fc1(x)) 72 | x = self.fc2(x) 73 | 74 | return x 75 | 76 | 77 | 78 | class Netcnn_cifar(nn.Module): 79 | def __init__(self): 80 | super(Netcnn_cifar, self).__init__() 81 | self.conv1 = nn.Conv2d(3, 32, 3) 82 | self.conv2 = nn.Conv2d(32, 64, 3) 83 | self.conv3 = nn.Conv2d(64, 64, 3) 84 | self.fc1 = nn.Linear(64 * 4 * 4, 64) 85 | self.fc2 = nn.Linear(64, 10) 86 | 87 | def forward(self, x): 88 | x = F.relu(self.conv1(x)) 89 | x = F.max_pool2d(x, 2) 90 | x = F.relu(self.conv2(x)) 91 | x = F.max_pool2d(x, 2) 92 | x = F.relu(self.conv3(x)) 93 | x = x.view(-1, 64 * 4 * 4) 94 | x = F.relu(self.fc1(x)) 95 | x = self.fc2(x) 96 | 97 | return x 98 | 99 | 100 | class Cifar10CNN(nn.Module): 101 | 102 | def __init__(self): 103 | super(Cifar10CNN, self).__init__() 104 | 105 | self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1) 106 | self.conv2 = nn.Conv2d(32, 32, kernel_size=3, padding=1) 107 | 108 | 109 | self.conv3 = nn.Conv2d(32, 64, kernel_size=3, padding=1) 110 | self.conv4 = nn.Conv2d(64, 64, kernel_size=3, padding=1) 111 | 112 | 113 | self.conv5 = nn.Conv2d(64, 128, kernel_size=3, padding=1) 114 | self.conv6 = nn.Conv2d(128, 128, kernel_size=3, padding=1) 115 | 116 | 117 | self.fc1 = nn.Linear(128 * 4 * 4, 128) 118 | # self.dropout1 = nn.Dropout() 119 | self.fc2 = nn.Linear(128, 10) 120 | 121 | def forward(self, x): 122 | x = F.relu(self.conv1(x)) 123 | x = F.relu(self.conv2(x)) 124 | x = F.max_pool2d(x, 2) 125 | 126 | 127 | x = F.relu(self.conv3(x)) 128 | x = F.relu(self.conv4(x)) 129 | x = F.max_pool2d(x, 2) 130 | 131 | x = F.relu(self.conv5(x)) 132 | x = F.relu(self.conv6(x)) 133 | x = F.max_pool2d(x, 2) 134 | 135 | x = x.view(-1, 128 * 4 * 4) 136 | x = F.relu(self.fc1(x)) 137 | # x = self.dropout1(x) 138 | x = self.fc2(x) 139 | return x 140 | 141 | 142 | class Net_fashion(nn.Module): 143 | def __init__(self): 144 | super(Net_fashion, self).__init__() 145 | self.conv1 = nn.Conv2d(1, 32, kernel_size=5, padding=2) 146 | self.conv2 = nn.Conv2d(32, 64, kernel_size=5, padding=2) 147 | self.fc1 = nn.Linear(64 * 7 * 7, 500) 148 | self.fc2 = nn.Linear(500, 10) 149 | 150 | 151 | def forward(self, x): 152 | x = F.relu(self.conv1(x)) 153 | x = F.max_pool2d(x, 2) 154 | x = F.relu(self.conv2(x)) 155 | x = F.max_pool2d(x, 2) 156 | x = x.view(-1, 64 * 7 * 7) 157 | x = F.relu(self.fc1(x)) 158 | x = self.fc2(x) 159 | 160 | return x 161 | 162 | 163 | -------------------------------------------------------------------------------- /FashionMNIST/fashion_byz_attack.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | 10 | 11 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 12 | print("device: ", device) 13 | 14 | number_of_samples = 100 # number of participants 15 | 16 | is_noniid = True 17 | if is_noniid: 18 | n = 2 19 | min_n_each_node = 2 20 | else: 21 | n = 10 22 | min_n_each_node = 10 23 | 24 | is_organized = True 25 | hostile_node_percentage = 0.20 # malicious participant ratio 26 | byzantine_mean = 0 27 | byzantine_std = 1 28 | 29 | iteration_num = 200 # number of communication rounds 30 | learning_rate = 0.0020 31 | 32 | weight_decay = 0.0001 33 | numEpoch = 10 34 | batch_size = 25 35 | momentum = 0.9 36 | 37 | seed = 6 38 | use_seed = 13 39 | hostility_seed = 210 40 | converters_seed = 42 41 | byzantine_seed = 83 42 | factor = 1.5 43 | 44 | train_amount = 6000 45 | test_amount = 1000 46 | 47 | x_train, y_train, x_test, y_test = dd.load_fashion_mnist_data() 48 | dd.show_grid_fashion_mnist(x_train, y_train, 6, 6) 49 | 50 | ##train 51 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 52 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 53 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 54 | 55 | x_train_dict, y_train_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_train, 56 | amount=train_amount, 57 | number_of_samples=number_of_samples, 58 | n=n, x_data=x_train, 59 | y_data=y_train, 60 | node_label_info=node_label_info_train, 61 | amount_info_table=amount_info_table_train, 62 | x_name="x_train", 63 | y_name="y_train") 64 | 65 | ## test 66 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 67 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 68 | number_of_samples=number_of_samples, 69 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 70 | x_test_dict, y_test_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_test, 71 | amount=test_amount, 72 | number_of_samples=number_of_samples, 73 | n=n, x_data=x_test, 74 | y_data=y_test, 75 | node_label_info=node_label_info_test, 76 | amount_info_table=amount_info_table_test, 77 | x_name="x_test", 78 | y_name="y_test") 79 | 80 | x_train = x_train.view(-1, 1, 28, 28) 81 | x_test = x_test.view(-1, 1, 28, 28) 82 | 83 | train_ds = TensorDataset(x_train, y_train) 84 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 85 | 86 | test_ds = TensorDataset(x_test, y_test) 87 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 88 | 89 | main_model = cm.Net_fashion() 90 | main_model = main_model.to(device) 91 | cm.weights_init(main_model) 92 | 93 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, 94 | weight_decay=weight_decay) 95 | main_criterion = nn.CrossEntropyLoss() 96 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_fashion_mnist( 97 | number_of_samples, learning_rate, 98 | momentum, device, weight_decay) 99 | 100 | test_accuracies_of_each_iteration = np.array([], dtype=float) 101 | byzantine_node_list = dd.get_byzantine_node_list(hostile_node_percentage, number_of_samples, hostility_seed) 102 | np.random.seed(byzantine_seed) 103 | byzantine_seeds_array = np.random.choice(5000, size=iteration_num, replace=False) 104 | 105 | for iteration in range(iteration_num): 106 | 107 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 108 | number_of_samples) 109 | 110 | if is_organized: 111 | iteration_byzantine_seed = byzantine_seeds_array[iteration] 112 | else: 113 | iteration_byzantine_seed = None 114 | 115 | tn.start_train_end_node_process_byzantine(number_of_samples, x_train_dict, y_train_dict, x_test_dict, y_test_dict, 116 | batch_size, model_dict, criterion_dict, optimizer_dict, 117 | numEpoch, byzantine_node_list, byzantine_mean, byzantine_std, 118 | device, iteration_byzantine_seed) 119 | 120 | 121 | main_model = tn.set_averaged_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, device) 122 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 123 | 124 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 125 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 126 | -------------------------------------------------------------------------------- /FashionMNIST/fashion_byz_median.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | 10 | 11 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 12 | print("device: ", device) 13 | 14 | number_of_samples = 100 # number of participants 15 | 16 | is_noniid = True 17 | if is_noniid: 18 | n = 2 19 | min_n_each_node = 2 20 | else: 21 | n = 10 22 | min_n_each_node = 10 23 | 24 | is_organized = True 25 | hostile_node_percentage = 0.20 # malicious participant ratio 26 | byzantine_mean = 0 27 | byzantine_std = 1 28 | 29 | iteration_num = 200 # number of communication rounds 30 | learning_rate = 0.0020 31 | 32 | weight_decay = 0.0001 33 | numEpoch = 10 34 | batch_size = 25 35 | momentum = 0.9 36 | 37 | seed = 6 38 | use_seed = 13 39 | hostility_seed = 210 40 | converters_seed = 42 41 | byzantine_seed = 83 42 | factor = 1.5 43 | 44 | train_amount = 6000 45 | test_amount = 1000 46 | 47 | x_train, y_train, x_test, y_test = dd.load_fashion_mnist_data() 48 | dd.show_grid_fashion_mnist(x_train, y_train, 6, 6) 49 | 50 | ##train 51 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 52 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 53 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 54 | 55 | x_train_dict, y_train_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_train, 56 | amount=train_amount, 57 | number_of_samples=number_of_samples, 58 | n=n, x_data=x_train, 59 | y_data=y_train, 60 | node_label_info=node_label_info_train, 61 | amount_info_table=amount_info_table_train, 62 | x_name="x_train", 63 | y_name="y_train") 64 | 65 | ## test 66 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 67 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 68 | number_of_samples=number_of_samples, 69 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 70 | x_test_dict, y_test_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_test, 71 | amount=test_amount, 72 | number_of_samples=number_of_samples, 73 | n=n, x_data=x_test, 74 | y_data=y_test, 75 | node_label_info=node_label_info_test, 76 | amount_info_table=amount_info_table_test, 77 | x_name="x_test", 78 | y_name="y_test") 79 | 80 | x_train = x_train.view(-1, 1, 28, 28) 81 | x_test = x_test.view(-1, 1, 28, 28) 82 | 83 | train_ds = TensorDataset(x_train, y_train) 84 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 85 | 86 | test_ds = TensorDataset(x_test, y_test) 87 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 88 | 89 | main_model = cm.Net_fashion() 90 | main_model = main_model.to(device) 91 | cm.weights_init(main_model) 92 | 93 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, 94 | weight_decay=weight_decay) 95 | main_criterion = nn.CrossEntropyLoss() 96 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_fashion_mnist( 97 | number_of_samples, learning_rate, 98 | momentum, device, weight_decay) 99 | 100 | test_accuracies_of_each_iteration = np.array([], dtype=float) 101 | 102 | 103 | byzantine_node_list = dd.get_byzantine_node_list(hostile_node_percentage, number_of_samples, hostility_seed) 104 | np.random.seed(byzantine_seed) 105 | byzantine_seeds_array = np.random.choice(5000, size=iteration_num, replace=False) 106 | 107 | 108 | for iteration in range(iteration_num): 109 | 110 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 111 | number_of_samples) 112 | 113 | if is_organized: 114 | iteration_byzantine_seed = byzantine_seeds_array[iteration] 115 | else: 116 | iteration_byzantine_seed = None 117 | 118 | tn.start_train_end_node_process_byzantine(number_of_samples, x_train_dict, y_train_dict, x_test_dict, y_test_dict, 119 | batch_size, model_dict, criterion_dict, optimizer_dict, 120 | numEpoch, byzantine_node_list, byzantine_mean, byzantine_std, 121 | device, iteration_byzantine_seed) 122 | 123 | 124 | main_model = tn.set_coordinatewise_med_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, device) 125 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 126 | 127 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 128 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 129 | -------------------------------------------------------------------------------- /FashionMNIST/fashion_byz_trimmed.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | 10 | 11 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 12 | print("device: ", device) 13 | 14 | number_of_samples = 100 # number of participants 15 | 16 | is_noniid = True 17 | if is_noniid: 18 | n = 2 19 | min_n_each_node = 2 20 | else: 21 | n = 10 22 | min_n_each_node = 10 23 | 24 | is_organized = True 25 | hostile_node_percentage = 0.20 # malicious participant ratio 26 | byzantine_mean = 0 27 | byzantine_std = 1 28 | 29 | iteration_num = 200 # number of communication rounds 30 | learning_rate = 0.0020 31 | 32 | weight_decay = 0.0001 33 | numEpoch = 10 34 | batch_size = 25 35 | momentum = 0.9 36 | 37 | seed = 6 38 | use_seed = 13 39 | hostility_seed = 210 40 | converters_seed = 42 41 | byzantine_seed = 83 42 | factor = 1.5 43 | 44 | train_amount = 6000 45 | test_amount = 1000 46 | 47 | x_train, y_train, x_test, y_test = dd.load_fashion_mnist_data() 48 | dd.show_grid_fashion_mnist(x_train, y_train, 6, 6) 49 | 50 | ##train 51 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 52 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 53 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 54 | 55 | x_train_dict, y_train_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_train, 56 | amount=train_amount, 57 | number_of_samples=number_of_samples, 58 | n=n, x_data=x_train, 59 | y_data=y_train, 60 | node_label_info=node_label_info_train, 61 | amount_info_table=amount_info_table_train, 62 | x_name="x_train", 63 | y_name="y_train") 64 | 65 | ## test 66 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 67 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 68 | number_of_samples=number_of_samples, 69 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 70 | x_test_dict, y_test_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_test, 71 | amount=test_amount, 72 | number_of_samples=number_of_samples, 73 | n=n, x_data=x_test, 74 | y_data=y_test, 75 | node_label_info=node_label_info_test, 76 | amount_info_table=amount_info_table_test, 77 | x_name="x_test", 78 | y_name="y_test") 79 | 80 | x_train = x_train.view(-1, 1, 28, 28) 81 | x_test = x_test.view(-1, 1, 28, 28) 82 | 83 | train_ds = TensorDataset(x_train, y_train) 84 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 85 | 86 | test_ds = TensorDataset(x_test, y_test) 87 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 88 | 89 | main_model = cm.Net_fashion() 90 | main_model = main_model.to(device) 91 | cm.weights_init(main_model) 92 | 93 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, 94 | weight_decay=weight_decay) 95 | main_criterion = nn.CrossEntropyLoss() 96 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_fashion_mnist( 97 | number_of_samples, learning_rate, 98 | momentum, device, weight_decay) 99 | 100 | test_accuracies_of_each_iteration = np.array([], dtype=float) 101 | 102 | 103 | byzantine_node_list = dd.get_byzantine_node_list(hostile_node_percentage, number_of_samples, hostility_seed) 104 | np.random.seed(byzantine_seed) 105 | byzantine_seeds_array = np.random.choice(5000, size=iteration_num, replace=False) 106 | 107 | 108 | for iteration in range(iteration_num): 109 | 110 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 111 | number_of_samples) 112 | 113 | if is_organized: 114 | iteration_byzantine_seed = byzantine_seeds_array[iteration] 115 | else: 116 | iteration_byzantine_seed = None 117 | 118 | tn.start_train_end_node_process_byzantine(number_of_samples, x_train_dict, y_train_dict, x_test_dict, y_test_dict, 119 | batch_size, model_dict, criterion_dict, optimizer_dict, 120 | numEpoch, byzantine_node_list, byzantine_mean, byzantine_std, 121 | device, iteration_byzantine_seed) 122 | 123 | 124 | main_model = tn.set_trimmed_mean_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, hostile_node_percentage, device) 125 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 126 | 127 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 128 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 129 | -------------------------------------------------------------------------------- /FashionMNIST/fashion_lf_attack.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | 10 | 11 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 12 | print("device: ", device) 13 | 14 | number_of_samples = 100 # number of participants 15 | 16 | is_noniid = True 17 | if is_noniid: 18 | n = 2 19 | min_n_each_node = 2 20 | else: 21 | n = 10 22 | min_n_each_node = 10 23 | 24 | is_organized = True 25 | hostile_node_percentage = 0.20 # malicious node ratio 26 | 27 | iteration_num = 200 # number of communication rounds 28 | learning_rate = 0.0020 29 | 30 | weight_decay = 0.0001 31 | numEpoch = 10 32 | batch_size = 25 33 | momentum = 0.9 34 | 35 | seed = 5 36 | use_seed = 71 37 | hostility_seed = 89 38 | converters_seed = 41 39 | 40 | train_amount = 6000 41 | test_amount = 1000 42 | 43 | x_train, y_train, x_test, y_test = dd.load_fashion_mnist_data() 44 | dd.show_grid_fashion_mnist(x_train, y_train, 6, 6) 45 | 46 | ##train 47 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 48 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 49 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 50 | 51 | x_train_dict, y_train_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_train, 52 | amount=train_amount, 53 | number_of_samples=number_of_samples, 54 | n=n, x_data=x_train, 55 | y_data=y_train, 56 | node_label_info=node_label_info_train, 57 | amount_info_table=amount_info_table_train, 58 | x_name="x_train", 59 | y_name="y_train") 60 | 61 | nodes_list = dd.choose_nodes_randomly_to_convert_hostile(hostile_node_percentage, number_of_samples, hostility_seed) 62 | print("hostile_nodes:", nodes_list) 63 | 64 | if is_organized: 65 | y_train_dict = dd.convert_nodes_to_hostile(y_train_dict, nodes_list, 66 | converter_dict={0: 6, 1: 3, 2: 4, 67 | 3: 1, 4: 2, 5: 7, 6: 0, 68 | 7: 9, 8: 5, 9: 7}) 69 | else: 70 | y_train_dict = dd.convert_nodes_to_hostile_with_different_converters(y_train_dict, nodes_list, 71 | converters_seed=converters_seed) 72 | 73 | ## test 74 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 75 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 76 | number_of_samples=number_of_samples, 77 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 78 | x_test_dict, y_test_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_test, 79 | amount=test_amount, 80 | number_of_samples=number_of_samples, 81 | n=n, x_data=x_test, 82 | y_data=y_test, 83 | node_label_info=node_label_info_test, 84 | amount_info_table=amount_info_table_test, 85 | x_name="x_test", 86 | y_name="y_test") 87 | 88 | x_train = x_train.view(-1, 1, 28, 28) 89 | x_test = x_test.view(-1, 1, 28, 28) 90 | 91 | train_ds = TensorDataset(x_train, y_train) 92 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 93 | 94 | test_ds = TensorDataset(x_test, y_test) 95 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 96 | 97 | main_model = cm.Net_fashion() 98 | main_model = main_model.to(device) 99 | cm.weights_init(main_model) 100 | 101 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, 102 | weight_decay=weight_decay) 103 | main_criterion = nn.CrossEntropyLoss() 104 | 105 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_fashion_mnist( 106 | number_of_samples, learning_rate, 107 | momentum, device, weight_decay) 108 | 109 | test_accuracies_of_each_iteration = np.array([], dtype=float) 110 | 111 | for iteration in range(iteration_num): 112 | 113 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 114 | number_of_samples) 115 | 116 | tn.start_train_end_node_process_without_print(number_of_samples, x_train_dict, y_train_dict, x_test_dict, 117 | y_test_dict, 118 | batch_size, model_dict, criterion_dict, optimizer_dict, numEpoch, 119 | device) 120 | 121 | 122 | main_model = tn.set_averaged_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, device) 123 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 124 | 125 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 126 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 127 | -------------------------------------------------------------------------------- /FashionMNIST/fashion_lf_median.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | 10 | 11 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 12 | print("device: ", device) 13 | 14 | number_of_samples = 100 # number of participants 15 | 16 | is_noniid = True 17 | if is_noniid: 18 | n = 2 19 | min_n_each_node = 2 20 | else: 21 | n = 10 22 | min_n_each_node = 10 23 | 24 | is_organized = True 25 | hostile_node_percentage = 0.20 # malicious node ratio 26 | 27 | iteration_num = 200 # number of communication rounds 28 | learning_rate = 0.0020 29 | 30 | weight_decay = 0.0001 31 | numEpoch = 10 32 | batch_size = 25 33 | momentum = 0.9 34 | 35 | seed = 5 36 | use_seed = 71 37 | hostility_seed = 89 38 | converters_seed = 41 39 | 40 | train_amount = 6000 41 | test_amount = 1000 42 | 43 | x_train, y_train, x_test, y_test = dd.load_fashion_mnist_data() 44 | dd.show_grid_fashion_mnist(x_train, y_train, 6, 6) 45 | 46 | ##train 47 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 48 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 49 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 50 | 51 | x_train_dict, y_train_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_train, 52 | amount=train_amount, 53 | number_of_samples=number_of_samples, 54 | n=n, x_data=x_train, 55 | y_data=y_train, 56 | node_label_info=node_label_info_train, 57 | amount_info_table=amount_info_table_train, 58 | x_name="x_train", 59 | y_name="y_train") 60 | 61 | nodes_list = dd.choose_nodes_randomly_to_convert_hostile(hostile_node_percentage, number_of_samples, hostility_seed) 62 | print("hostile_nodes:", nodes_list) 63 | 64 | if is_organized: 65 | y_train_dict = dd.convert_nodes_to_hostile(y_train_dict, nodes_list, 66 | converter_dict={0: 6, 1: 3, 2: 4, 67 | 3: 1, 4: 2, 5: 7, 6: 0, 68 | 7: 9, 8: 5, 9: 7}) 69 | else: 70 | y_train_dict = dd.convert_nodes_to_hostile_with_different_converters(y_train_dict, nodes_list, 71 | converters_seed=converters_seed) 72 | 73 | ## test 74 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 75 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 76 | number_of_samples=number_of_samples, 77 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 78 | x_test_dict, y_test_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_test, 79 | amount=test_amount, 80 | number_of_samples=number_of_samples, 81 | n=n, x_data=x_test, 82 | y_data=y_test, 83 | node_label_info=node_label_info_test, 84 | amount_info_table=amount_info_table_test, 85 | x_name="x_test", 86 | y_name="y_test") 87 | 88 | x_train = x_train.view(-1, 1, 28, 28) 89 | x_test = x_test.view(-1, 1, 28, 28) 90 | 91 | train_ds = TensorDataset(x_train, y_train) 92 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 93 | 94 | test_ds = TensorDataset(x_test, y_test) 95 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 96 | 97 | main_model = cm.Net_fashion() 98 | main_model = main_model.to(device) 99 | cm.weights_init(main_model) 100 | 101 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, 102 | weight_decay=weight_decay) 103 | main_criterion = nn.CrossEntropyLoss() 104 | 105 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_fashion_mnist( 106 | number_of_samples, learning_rate, 107 | momentum, device, weight_decay) 108 | 109 | test_accuracies_of_each_iteration = np.array([], dtype=float) 110 | 111 | for iteration in range(iteration_num): 112 | 113 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 114 | number_of_samples) 115 | 116 | tn.start_train_end_node_process_without_print(number_of_samples, x_train_dict, y_train_dict, x_test_dict, 117 | y_test_dict, 118 | batch_size, model_dict, criterion_dict, optimizer_dict, numEpoch, 119 | device) 120 | 121 | 122 | main_model = tn.set_coordinatewise_med_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, device) 123 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 124 | 125 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 126 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 127 | -------------------------------------------------------------------------------- /FashionMNIST/fashion_lf_trimmed.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | 10 | 11 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 12 | print("device: ", device) 13 | 14 | number_of_samples = 100 # number of participants 15 | 16 | is_noniid = True 17 | if is_noniid: 18 | n = 2 19 | min_n_each_node = 2 20 | else: 21 | n = 10 22 | min_n_each_node = 10 23 | 24 | is_organized = True 25 | hostile_node_percentage = 0.20 # malicious node ratio 26 | 27 | iteration_num = 200 # number of communication rounds 28 | learning_rate = 0.0020 29 | 30 | weight_decay = 0.0001 31 | numEpoch = 10 32 | batch_size = 25 33 | momentum = 0.9 34 | 35 | seed = 5 36 | use_seed = 71 37 | hostility_seed = 89 38 | converters_seed = 41 39 | 40 | train_amount = 6000 41 | test_amount = 1000 42 | 43 | x_train, y_train, x_test, y_test = dd.load_fashion_mnist_data() 44 | dd.show_grid_fashion_mnist(x_train, y_train, 6, 6) 45 | 46 | ##train 47 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 48 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 49 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 50 | 51 | x_train_dict, y_train_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_train, 52 | amount=train_amount, 53 | number_of_samples=number_of_samples, 54 | n=n, x_data=x_train, 55 | y_data=y_train, 56 | node_label_info=node_label_info_train, 57 | amount_info_table=amount_info_table_train, 58 | x_name="x_train", 59 | y_name="y_train") 60 | 61 | nodes_list = dd.choose_nodes_randomly_to_convert_hostile(hostile_node_percentage, number_of_samples, hostility_seed) 62 | print("hostile_nodes:", nodes_list) 63 | 64 | if is_organized: 65 | y_train_dict = dd.convert_nodes_to_hostile(y_train_dict, nodes_list, 66 | converter_dict={0: 6, 1: 3, 2: 4, 67 | 3: 1, 4: 2, 5: 7, 6: 0, 68 | 7: 9, 8: 5, 9: 7}) 69 | else: 70 | y_train_dict = dd.convert_nodes_to_hostile_with_different_converters(y_train_dict, nodes_list, 71 | converters_seed=converters_seed) 72 | 73 | ## test 74 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 75 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 76 | number_of_samples=number_of_samples, 77 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 78 | x_test_dict, y_test_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_test, 79 | amount=test_amount, 80 | number_of_samples=number_of_samples, 81 | n=n, x_data=x_test, 82 | y_data=y_test, 83 | node_label_info=node_label_info_test, 84 | amount_info_table=amount_info_table_test, 85 | x_name="x_test", 86 | y_name="y_test") 87 | 88 | x_train = x_train.view(-1, 1, 28, 28) 89 | x_test = x_test.view(-1, 1, 28, 28) 90 | 91 | train_ds = TensorDataset(x_train, y_train) 92 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 93 | 94 | test_ds = TensorDataset(x_test, y_test) 95 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 96 | 97 | main_model = cm.Net_fashion() 98 | main_model = main_model.to(device) 99 | cm.weights_init(main_model) 100 | 101 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, 102 | weight_decay=weight_decay) 103 | main_criterion = nn.CrossEntropyLoss() 104 | 105 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_fashion_mnist( 106 | number_of_samples, learning_rate, 107 | momentum, device, weight_decay) 108 | 109 | test_accuracies_of_each_iteration = np.array([], dtype=float) 110 | 111 | for iteration in range(iteration_num): 112 | 113 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 114 | number_of_samples) 115 | 116 | tn.start_train_end_node_process_without_print(number_of_samples, x_train_dict, y_train_dict, x_test_dict, 117 | y_test_dict, 118 | batch_size, model_dict, criterion_dict, optimizer_dict, numEpoch, 119 | device) 120 | 121 | 122 | main_model = tn.set_trimmed_mean_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, hostile_node_percentage, device) 123 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 124 | 125 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 126 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 127 | -------------------------------------------------------------------------------- /FashionMNIST/fashion_partial_knowledge_attack.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | 10 | 11 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 12 | print("device: ", device) 13 | 14 | number_of_samples = 100 # number of participants 15 | 16 | is_noniid = True 17 | if is_noniid: 18 | n = 2 19 | min_n_each_node = 2 20 | else: 21 | n = 10 22 | min_n_each_node = 10 23 | 24 | is_organized = True 25 | hostile_node_percentage = 0.20 # malicious participant ratio 26 | byzantine_mean = 0 27 | byzantine_std = 1 28 | 29 | iteration_num = 200 # number of communication rounds 30 | learning_rate = 0.0020 31 | 32 | weight_decay = 0.0001 33 | numEpoch = 10 34 | batch_size = 25 35 | momentum = 0.9 36 | is_clipping =True 37 | 38 | seed = 6 39 | use_seed = 13 40 | hostility_seed = 210 41 | converters_seed = 42 42 | byzantine_seed = 83 43 | factor = 1.5 44 | 45 | train_amount = 6000 46 | test_amount = 1000 47 | 48 | x_train, y_train, x_test, y_test = dd.load_fashion_mnist_data() 49 | dd.show_grid_fashion_mnist(x_train, y_train, 6, 6) 50 | 51 | ##train 52 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 53 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 54 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 55 | 56 | x_train_dict, y_train_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_train, 57 | amount=train_amount, 58 | number_of_samples=number_of_samples, 59 | n=n, x_data=x_train, 60 | y_data=y_train, 61 | node_label_info=node_label_info_train, 62 | amount_info_table=amount_info_table_train, 63 | x_name="x_train", 64 | y_name="y_train") 65 | 66 | ## test 67 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 68 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 69 | number_of_samples=number_of_samples, 70 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 71 | x_test_dict, y_test_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_test, 72 | amount=test_amount, 73 | number_of_samples=number_of_samples, 74 | n=n, x_data=x_test, 75 | y_data=y_test, 76 | node_label_info=node_label_info_test, 77 | amount_info_table=amount_info_table_test, 78 | x_name="x_test", 79 | y_name="y_test") 80 | 81 | x_train = x_train.view(-1, 1, 28, 28) 82 | x_test = x_test.view(-1, 1, 28, 28) 83 | 84 | train_ds = TensorDataset(x_train, y_train) 85 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 86 | 87 | test_ds = TensorDataset(x_test, y_test) 88 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 89 | 90 | main_model = cm.Net_fashion() 91 | main_model = main_model.to(device) 92 | cm.weights_init(main_model) 93 | 94 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, 95 | weight_decay=weight_decay) 96 | main_criterion = nn.CrossEntropyLoss() 97 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_fashion_mnist( 98 | number_of_samples, learning_rate, 99 | momentum, device, weight_decay) 100 | 101 | test_accuracies_of_each_iteration = np.array([], dtype=float) 102 | byzantine_node_list = dd.get_byzantine_node_list(hostile_node_percentage, number_of_samples, hostility_seed) 103 | np.random.seed(byzantine_seed) 104 | byzantine_seeds_array = np.random.choice(5000, size=iteration_num, replace=False) 105 | 106 | for iteration in range(iteration_num): 107 | 108 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 109 | number_of_samples) 110 | 111 | tn.start_train_end_node_process_with_clipping(number_of_samples, x_train_dict, y_train_dict, x_test_dict, 112 | y_test_dict, batch_size, model_dict, criterion_dict, optimizer_dict, numEpoch, 113 | device, clipping=is_clipping, clipping_threshold=5) 114 | 115 | if is_organized: 116 | iteration_byzantine_seed = byzantine_seeds_array[iteration] 117 | model_dict = tn.partial_knowledge_fang_org(main_model, model_dict, byzantine_node_list, 118 | iteration_byzantine_seed, device) 119 | else: 120 | iteration_byzantine_seed = None 121 | model_dict = tn.partial_knowledge_fang_ind(main_model, model_dict, byzantine_node_list, 122 | iteration_byzantine_seed, device) 123 | 124 | main_model = tn.set_averaged_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, device) 125 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 126 | 127 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 128 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 129 | -------------------------------------------------------------------------------- /FashionMNIST/fashion_partial_knowledge_median.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | 10 | 11 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 12 | print("device: ", device) 13 | 14 | number_of_samples = 100 # number of participants 15 | 16 | is_noniid = True 17 | if is_noniid: 18 | n = 2 19 | min_n_each_node = 2 20 | else: 21 | n = 10 22 | min_n_each_node = 10 23 | 24 | is_organized = True 25 | hostile_node_percentage = 0.20 # malicious participant ratio 26 | byzantine_mean = 0 27 | byzantine_std = 1 28 | 29 | iteration_num = 200 # number of communication rounds 30 | learning_rate = 0.0020 31 | 32 | weight_decay = 0.0001 33 | numEpoch = 10 34 | batch_size = 25 35 | momentum = 0.9 36 | is_clipping =True 37 | 38 | seed = 6 39 | use_seed = 13 40 | hostility_seed = 210 41 | converters_seed = 42 42 | byzantine_seed = 83 43 | factor = 1.5 44 | 45 | train_amount = 6000 46 | test_amount = 1000 47 | 48 | x_train, y_train, x_test, y_test = dd.load_fashion_mnist_data() 49 | dd.show_grid_fashion_mnist(x_train, y_train, 6, 6) 50 | 51 | ##train 52 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 53 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 54 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 55 | 56 | x_train_dict, y_train_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_train, 57 | amount=train_amount, 58 | number_of_samples=number_of_samples, 59 | n=n, x_data=x_train, 60 | y_data=y_train, 61 | node_label_info=node_label_info_train, 62 | amount_info_table=amount_info_table_train, 63 | x_name="x_train", 64 | y_name="y_train") 65 | 66 | ## test 67 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 68 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 69 | number_of_samples=number_of_samples, 70 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 71 | x_test_dict, y_test_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_test, 72 | amount=test_amount, 73 | number_of_samples=number_of_samples, 74 | n=n, x_data=x_test, 75 | y_data=y_test, 76 | node_label_info=node_label_info_test, 77 | amount_info_table=amount_info_table_test, 78 | x_name="x_test", 79 | y_name="y_test") 80 | 81 | x_train = x_train.view(-1, 1, 28, 28) 82 | x_test = x_test.view(-1, 1, 28, 28) 83 | 84 | train_ds = TensorDataset(x_train, y_train) 85 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 86 | 87 | test_ds = TensorDataset(x_test, y_test) 88 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 89 | 90 | main_model = cm.Net_fashion() 91 | main_model = main_model.to(device) 92 | cm.weights_init(main_model) 93 | 94 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, 95 | weight_decay=weight_decay) 96 | main_criterion = nn.CrossEntropyLoss() 97 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_fashion_mnist( 98 | number_of_samples, learning_rate, 99 | momentum, device, weight_decay) 100 | 101 | test_accuracies_of_each_iteration = np.array([], dtype=float) 102 | byzantine_node_list = dd.get_byzantine_node_list(hostile_node_percentage, number_of_samples, hostility_seed) 103 | np.random.seed(byzantine_seed) 104 | byzantine_seeds_array = np.random.choice(5000, size=iteration_num, replace=False) 105 | 106 | for iteration in range(iteration_num): 107 | 108 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 109 | number_of_samples) 110 | 111 | tn.start_train_end_node_process_with_clipping(number_of_samples, x_train_dict, y_train_dict, x_test_dict, 112 | y_test_dict, batch_size, model_dict, criterion_dict, optimizer_dict, numEpoch, 113 | device, clipping=is_clipping, clipping_threshold=5) 114 | 115 | if is_organized: 116 | iteration_byzantine_seed = byzantine_seeds_array[iteration] 117 | model_dict = tn.partial_knowledge_fang_org(main_model, model_dict, byzantine_node_list, 118 | iteration_byzantine_seed, device) 119 | else: 120 | iteration_byzantine_seed = None 121 | model_dict = tn.partial_knowledge_fang_ind(main_model, model_dict, byzantine_node_list, 122 | iteration_byzantine_seed, device) 123 | 124 | main_model = tn.set_coordinatewise_med_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, device) 125 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 126 | 127 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 128 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 129 | -------------------------------------------------------------------------------- /FashionMNIST/fashion_partial_knowledge_trimmed.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | 10 | 11 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 12 | print("device: ", device) 13 | 14 | number_of_samples = 100 # number of participants 15 | 16 | is_noniid = True 17 | if is_noniid: 18 | n = 2 19 | min_n_each_node = 2 20 | else: 21 | n = 10 22 | min_n_each_node = 10 23 | 24 | is_organized = True 25 | hostile_node_percentage = 0.20 # malicious participant ratio 26 | byzantine_mean = 0 27 | byzantine_std = 1 28 | 29 | iteration_num = 200 # number of communication rounds 30 | learning_rate = 0.0020 31 | 32 | weight_decay = 0.0001 33 | numEpoch = 10 34 | batch_size = 25 35 | momentum = 0.9 36 | is_clipping =True 37 | 38 | seed = 6 39 | use_seed = 13 40 | hostility_seed = 210 41 | converters_seed = 42 42 | byzantine_seed = 83 43 | factor = 1.5 44 | 45 | train_amount = 6000 46 | test_amount = 1000 47 | 48 | x_train, y_train, x_test, y_test = dd.load_fashion_mnist_data() 49 | dd.show_grid_fashion_mnist(x_train, y_train, 6, 6) 50 | 51 | ##train 52 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 53 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 54 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 55 | 56 | x_train_dict, y_train_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_train, 57 | amount=train_amount, 58 | number_of_samples=number_of_samples, 59 | n=n, x_data=x_train, 60 | y_data=y_train, 61 | node_label_info=node_label_info_train, 62 | amount_info_table=amount_info_table_train, 63 | x_name="x_train", 64 | y_name="y_train") 65 | 66 | ## test 67 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 68 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 69 | number_of_samples=number_of_samples, 70 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 71 | x_test_dict, y_test_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_test, 72 | amount=test_amount, 73 | number_of_samples=number_of_samples, 74 | n=n, x_data=x_test, 75 | y_data=y_test, 76 | node_label_info=node_label_info_test, 77 | amount_info_table=amount_info_table_test, 78 | x_name="x_test", 79 | y_name="y_test") 80 | 81 | x_train = x_train.view(-1, 1, 28, 28) 82 | x_test = x_test.view(-1, 1, 28, 28) 83 | 84 | train_ds = TensorDataset(x_train, y_train) 85 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 86 | 87 | test_ds = TensorDataset(x_test, y_test) 88 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 89 | 90 | main_model = cm.Net_fashion() 91 | main_model = main_model.to(device) 92 | cm.weights_init(main_model) 93 | 94 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, 95 | weight_decay=weight_decay) 96 | main_criterion = nn.CrossEntropyLoss() 97 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_fashion_mnist( 98 | number_of_samples, learning_rate, 99 | momentum, device, weight_decay) 100 | 101 | test_accuracies_of_each_iteration = np.array([], dtype=float) 102 | byzantine_node_list = dd.get_byzantine_node_list(hostile_node_percentage, number_of_samples, hostility_seed) 103 | np.random.seed(byzantine_seed) 104 | byzantine_seeds_array = np.random.choice(5000, size=iteration_num, replace=False) 105 | 106 | for iteration in range(iteration_num): 107 | 108 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 109 | number_of_samples) 110 | 111 | tn.start_train_end_node_process_with_clipping(number_of_samples, x_train_dict, y_train_dict, x_test_dict, 112 | y_test_dict, batch_size, model_dict, criterion_dict, optimizer_dict, numEpoch, 113 | device, clipping=is_clipping, clipping_threshold=5) 114 | 115 | if is_organized: 116 | iteration_byzantine_seed = byzantine_seeds_array[iteration] 117 | model_dict = tn.partial_knowledge_fang_org(main_model, model_dict, byzantine_node_list, 118 | iteration_byzantine_seed, device) 119 | else: 120 | iteration_byzantine_seed = None 121 | model_dict = tn.partial_knowledge_fang_ind(main_model, model_dict, byzantine_node_list, 122 | iteration_byzantine_seed, device) 123 | 124 | main_model = tn.set_trimmed_mean_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, hostile_node_percentage, device) 125 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 126 | 127 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 128 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 129 | -------------------------------------------------------------------------------- /FashionMNIST/fashion_byz_barfed.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import pandas as pd 6 | import numpy as np 7 | from fl_utils import distribute_data as dd 8 | from fl_utils import train_nodes as tn 9 | from fl_utils import construct_models as cm 10 | 11 | 12 | 13 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 14 | print("device: ", device) 15 | 16 | number_of_samples = 100 # number of participants 17 | 18 | is_noniid = True 19 | if is_noniid: 20 | n = 2 21 | min_n_each_node = 2 22 | else: 23 | n = 10 24 | min_n_each_node = 10 25 | 26 | is_organized = True 27 | hostile_node_percentage = 0.20 # malicious participant ratio 28 | byzantine_mean =0 29 | byzantine_std =1 30 | 31 | 32 | iteration_num = 200 # number of communication rounds 33 | learning_rate = 0.0020 34 | 35 | 36 | weight_decay = 0.0001 37 | numEpoch = 10 38 | batch_size = 25 39 | momentum = 0.9 40 | 41 | seed = 6 42 | use_seed = 13 43 | hostility_seed = 210 44 | converters_seed = 42 45 | byzantine_seed =83 46 | factor = 1.5 47 | 48 | train_amount = 6000 49 | test_amount = 1000 50 | 51 | x_train, y_train, x_test, y_test = dd.load_fashion_mnist_data() 52 | dd.show_grid_fashion_mnist(x_train, y_train, 6, 6) 53 | 54 | ##train 55 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 56 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 57 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 58 | 59 | x_train_dict, y_train_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_train, 60 | amount=train_amount, 61 | number_of_samples=number_of_samples, 62 | n=n, x_data=x_train, 63 | y_data=y_train, 64 | node_label_info=node_label_info_train, 65 | amount_info_table=amount_info_table_train, 66 | x_name="x_train", 67 | y_name="y_train") 68 | 69 | 70 | ## test 71 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 72 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 73 | number_of_samples=number_of_samples, 74 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 75 | x_test_dict, y_test_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_test, 76 | amount=test_amount, 77 | number_of_samples=number_of_samples, 78 | n=n, x_data=x_test, 79 | y_data=y_test, 80 | node_label_info=node_label_info_test, 81 | amount_info_table=amount_info_table_test, 82 | x_name="x_test", 83 | y_name="y_test") 84 | 85 | x_train = x_train.view(-1, 1, 28, 28) 86 | x_test = x_test.view(-1, 1, 28, 28) 87 | 88 | 89 | train_ds = TensorDataset(x_train, y_train) 90 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 91 | 92 | test_ds = TensorDataset(x_test, y_test) 93 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 94 | 95 | main_model = cm.Net_fashion() 96 | main_model = main_model.to(device) 97 | cm.weights_init(main_model) 98 | 99 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, weight_decay=weight_decay) 100 | main_criterion = nn.CrossEntropyLoss() 101 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_fashion_mnist(number_of_samples, learning_rate, 102 | momentum, device, weight_decay) 103 | 104 | 105 | test_accuracies_of_each_iteration = np.array([], dtype=float) 106 | its = np.array([], dtype=int) 107 | distances = pd.DataFrame() 108 | thresholds = pd.DataFrame() 109 | 110 | byzantine_node_list = dd.get_byzantine_node_list(hostile_node_percentage, number_of_samples, hostility_seed) 111 | 112 | np.random.seed(byzantine_seed) 113 | byzantine_seeds_array = np.random.choice(5000, size=iteration_num, replace=False) 114 | 115 | 116 | for iteration in range(iteration_num): 117 | its = np.concatenate((its, np.ones(number_of_samples, dtype=int) * (iteration + 1))) 118 | 119 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 120 | number_of_samples) 121 | 122 | 123 | if is_organized: 124 | iteration_byzantine_seed = byzantine_seeds_array[iteration] 125 | else: 126 | iteration_byzantine_seed =None 127 | 128 | tn.start_train_end_node_process_byzantine(number_of_samples, x_train_dict, y_train_dict, x_test_dict, y_test_dict, 129 | batch_size, model_dict, criterion_dict, optimizer_dict, 130 | numEpoch, byzantine_node_list, byzantine_mean, byzantine_std, 131 | device, iteration_byzantine_seed) 132 | 133 | iteration_distance = tn.calculate_euclidean_distances(main_model, model_dict) 134 | iteration_distance, iteration_threshold = tn.get_outlier_situation_and_thresholds_for_layers( 135 | iteration_distance) 136 | 137 | thresholds = pd.concat([thresholds, iteration_threshold]) 138 | distances = pd.concat([distances, iteration_distance]) 139 | 140 | 141 | main_model = tn.strict_condition_without_outliers_set_averaged_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, iteration_distance, device) 142 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 143 | 144 | 145 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 146 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 147 | 148 | distances["iteration"] = its 149 | thresholds["iteration"] = np.arange(1, iteration_num + 1) 150 | -------------------------------------------------------------------------------- /MNIST/mnist_byz_attack.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | 10 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 11 | print("device: ", device) 12 | 13 | number_of_samples = 100 # number of participants 14 | 15 | is_noniid = True 16 | if is_noniid: 17 | n = 2 18 | min_n_each_node = 2 19 | else: 20 | n = 10 21 | min_n_each_node = 10 22 | 23 | is_cnn = False 24 | is_organized = True 25 | hostile_node_percentage = 0.20 #malicious participant ratio 26 | byzantine_mean =0 27 | byzantine_std =1 28 | 29 | iteration_num = 200 # number of communication rounds 30 | learning_rate = 0.01 31 | 32 | weight_decay = 0.0001 33 | numEpoch = 10 34 | batch_size = 32 35 | momentum = 0.9 36 | 37 | seed = 1 38 | use_seed = 23 39 | hostility_seed = 88 40 | converters_seed = 121 41 | byzantine_seed =25 42 | factor = 1.5 43 | 44 | train_amount = 4000 45 | valid_amount = 900 46 | test_amount = 890 47 | print_amount = 3 48 | 49 | 50 | x_train, y_train, x_valid, y_valid, x_test, y_test = dd.load_mnist_data() 51 | x_test, y_test = dd.get_equal_size_test_data_from_each_label(x_test, y_test, min_amount=test_amount) 52 | 53 | x_train, y_train, x_valid, y_valid, x_test, y_test = map(torch.tensor, 54 | (x_train, y_train, x_valid, y_valid, x_test, y_test)) 55 | 56 | ##train 57 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 58 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 59 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 60 | 61 | x_train_dict, y_train_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_train, 62 | amount=train_amount, 63 | number_of_samples=number_of_samples, 64 | n=n, x_data=x_train, 65 | y_data=y_train, 66 | node_label_info=node_label_info_train, 67 | amount_info_table=amount_info_table_train, 68 | x_name="x_train", 69 | y_name="y_train", 70 | is_cnn=is_cnn) 71 | 72 | ## test 73 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 74 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 75 | number_of_samples=number_of_samples, 76 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 77 | x_test_dict, y_test_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_test, 78 | amount=test_amount, 79 | number_of_samples=number_of_samples, 80 | n=n, x_data=x_test, 81 | y_data=y_test, 82 | node_label_info=node_label_info_test, 83 | amount_info_table=amount_info_table_test, 84 | x_name="x_test", 85 | y_name="y_test", is_cnn=is_cnn) 86 | 87 | if is_cnn: 88 | reshape_size = int(np.sqrt(x_train.shape[1])) 89 | x_train = x_train.view(-1, 1, reshape_size, reshape_size) 90 | x_valid = x_valid.view(-1, 1, reshape_size, reshape_size) 91 | x_test = x_test.view(-1, 1, reshape_size, reshape_size) 92 | 93 | train_ds = TensorDataset(x_train, y_train) 94 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 95 | 96 | test_ds = TensorDataset(x_test, y_test) 97 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 98 | 99 | if is_cnn: 100 | main_model = cm.Netcnn() 101 | else: 102 | main_model = cm.Net2nn() 103 | 104 | main_model = main_model.to(device) 105 | cm.weights_init(main_model) 106 | 107 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, weight_decay=weight_decay) 108 | main_criterion = nn.CrossEntropyLoss() 109 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_mnist(number_of_samples, learning_rate, 110 | momentum, device, is_cnn) 111 | 112 | 113 | test_accuracies_of_each_iteration = np.array([], dtype=float) 114 | 115 | byzantine_node_list = dd.get_byzantine_node_list(hostile_node_percentage, number_of_samples, hostility_seed) 116 | np.random.seed(byzantine_seed) 117 | byzantine_seeds_array = np.random.choice(5000, size=iteration_num, replace=False) 118 | 119 | for iteration in range(iteration_num): 120 | 121 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 122 | number_of_samples) 123 | 124 | 125 | if is_organized: 126 | iteration_byzantine_seed = byzantine_seeds_array[iteration] 127 | else: 128 | iteration_byzantine_seed =None 129 | 130 | tn.start_train_end_node_process_byzantine(number_of_samples, x_train_dict, y_train_dict, x_test_dict, y_test_dict, 131 | batch_size, model_dict, criterion_dict, optimizer_dict, 132 | numEpoch, byzantine_node_list, byzantine_mean, byzantine_std, 133 | device, iteration_byzantine_seed) 134 | 135 | main_model = tn.set_averaged_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, device) 136 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 137 | 138 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 139 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 140 | -------------------------------------------------------------------------------- /MNIST/mnist_lf_attack.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | 10 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 11 | print("device: ", device) 12 | 13 | number_of_samples = 100 # number of participants 14 | is_noniid = True 15 | 16 | if is_noniid: 17 | n = 2 18 | min_n_each_node = 2 19 | else: 20 | n = 10 21 | min_n_each_node = 10 22 | 23 | is_cnn = False 24 | is_organized = True 25 | 26 | hostile_node_percentage = 0.20 # malicious participant ratio 27 | 28 | iteration_num = 200 ## number of communication rounds 29 | 30 | learning_rate = 0.01 31 | numEpoch = 10 32 | batch_size = 32 33 | momentum = 0.9 34 | 35 | seed = 1 36 | use_seed = 23 37 | hostility_seed = 77 38 | converters_seed = 51 39 | 40 | train_amount = 4000 41 | valid_amount = 900 42 | test_amount = 890 43 | print_amount = 3 44 | 45 | x_train, y_train, x_valid, y_valid, x_test, y_test = dd.load_mnist_data() 46 | x_test, y_test = dd.get_equal_size_test_data_from_each_label(x_test, y_test, min_amount=test_amount) 47 | 48 | x_train, y_train, x_valid, y_valid, x_test, y_test = map(torch.tensor, 49 | (x_train, y_train, x_valid, y_valid, x_test, y_test)) 50 | 51 | ##train 52 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 53 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 54 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 55 | 56 | x_train_dict, y_train_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_train, 57 | amount=train_amount, 58 | number_of_samples=number_of_samples, 59 | n=n, x_data=x_train, 60 | y_data=y_train, 61 | node_label_info=node_label_info_train, 62 | amount_info_table=amount_info_table_train, 63 | x_name="x_train", 64 | y_name="y_train", 65 | is_cnn=is_cnn) 66 | 67 | 68 | nodes_list = dd.choose_nodes_randomly_to_convert_hostile(hostile_node_percentage, number_of_samples, hostility_seed) 69 | print("hostile_nodes:", nodes_list) 70 | 71 | 72 | if is_organized: 73 | y_train_dict = dd.convert_nodes_to_hostile(y_train_dict, nodes_list, 74 | converter_dict={0: 9, 1: 7, 2: 5, 3: 8, 4: 6, 5: 2, 6: 4, 7: 1, 8: 3, 75 | 9: 0}) 76 | else: 77 | y_train_dict = dd.convert_nodes_to_hostile_with_different_converters(y_train_dict, nodes_list, 78 | converters_seed=converters_seed) 79 | 80 | 81 | ## test 82 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 83 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 84 | number_of_samples=number_of_samples, 85 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 86 | x_test_dict, y_test_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_test, 87 | amount=test_amount, 88 | number_of_samples=number_of_samples, 89 | n=n, x_data=x_test, 90 | y_data=y_test, 91 | node_label_info=node_label_info_test, 92 | amount_info_table=amount_info_table_test, 93 | x_name="x_test", 94 | y_name="y_test", is_cnn=is_cnn) 95 | 96 | if is_cnn: 97 | reshape_size = int(np.sqrt(x_train.shape[1])) 98 | x_train = x_train.view(-1, 1, reshape_size, reshape_size) 99 | x_valid = x_valid.view(-1, 1, reshape_size, reshape_size) 100 | x_test = x_test.view(-1, 1, reshape_size, reshape_size) 101 | 102 | train_ds = TensorDataset(x_train, y_train) 103 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 104 | 105 | test_ds = TensorDataset(x_test, y_test) 106 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 107 | 108 | if is_cnn: 109 | main_model = cm.Netcnn() 110 | else: 111 | main_model = cm.Net2nn() 112 | 113 | cm.weights_init(main_model) 114 | main_model = main_model.to(device) 115 | 116 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=0.9) 117 | main_criterion = nn.CrossEntropyLoss() 118 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_mnist(number_of_samples, learning_rate, 119 | momentum, device, is_cnn) 120 | 121 | test_accuracies_of_each_iteration = np.array([], dtype=float) 122 | 123 | 124 | for iteration in range(iteration_num): 125 | 126 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 127 | number_of_samples) 128 | 129 | tn.start_train_end_node_process_without_print(number_of_samples, x_train_dict, y_train_dict, x_test_dict, y_test_dict, 130 | batch_size, model_dict, criterion_dict, optimizer_dict, numEpoch, device) 131 | 132 | 133 | main_model = tn.set_averaged_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, device) 134 | 135 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 136 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 137 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 138 | 139 | -------------------------------------------------------------------------------- /MNIST/mnist_lf_median.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | 10 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 11 | print("device: ", device) 12 | 13 | number_of_samples = 100 # number of participants 14 | is_noniid = True 15 | 16 | if is_noniid: 17 | n = 2 18 | min_n_each_node = 2 19 | else: 20 | n = 10 21 | min_n_each_node = 10 22 | 23 | is_cnn = False 24 | is_organized = True 25 | 26 | hostile_node_percentage = 0.20 # malicious participant ratio 27 | 28 | iteration_num = 200 ## number of communication rounds 29 | 30 | learning_rate = 0.01 31 | numEpoch = 10 32 | batch_size = 32 33 | momentum = 0.9 34 | 35 | seed = 1 36 | use_seed = 23 37 | hostility_seed = 77 38 | converters_seed = 51 39 | 40 | train_amount = 4000 41 | valid_amount = 900 42 | test_amount = 890 43 | print_amount = 3 44 | 45 | x_train, y_train, x_valid, y_valid, x_test, y_test = dd.load_mnist_data() 46 | x_test, y_test = dd.get_equal_size_test_data_from_each_label(x_test, y_test, min_amount=test_amount) 47 | 48 | x_train, y_train, x_valid, y_valid, x_test, y_test = map(torch.tensor, 49 | (x_train, y_train, x_valid, y_valid, x_test, y_test)) 50 | 51 | ##train 52 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 53 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 54 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 55 | 56 | x_train_dict, y_train_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_train, 57 | amount=train_amount, 58 | number_of_samples=number_of_samples, 59 | n=n, x_data=x_train, 60 | y_data=y_train, 61 | node_label_info=node_label_info_train, 62 | amount_info_table=amount_info_table_train, 63 | x_name="x_train", 64 | y_name="y_train", 65 | is_cnn=is_cnn) 66 | 67 | 68 | nodes_list = dd.choose_nodes_randomly_to_convert_hostile(hostile_node_percentage, number_of_samples, hostility_seed) 69 | print("hostile_nodes:", nodes_list) 70 | 71 | 72 | if is_organized: 73 | y_train_dict = dd.convert_nodes_to_hostile(y_train_dict, nodes_list, 74 | converter_dict={0: 9, 1: 7, 2: 5, 3: 8, 4: 6, 5: 2, 6: 4, 7: 1, 8: 3, 75 | 9: 0}) 76 | else: 77 | y_train_dict = dd.convert_nodes_to_hostile_with_different_converters(y_train_dict, nodes_list, 78 | converters_seed=converters_seed) 79 | 80 | 81 | ## test 82 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 83 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 84 | number_of_samples=number_of_samples, 85 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 86 | x_test_dict, y_test_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_test, 87 | amount=test_amount, 88 | number_of_samples=number_of_samples, 89 | n=n, x_data=x_test, 90 | y_data=y_test, 91 | node_label_info=node_label_info_test, 92 | amount_info_table=amount_info_table_test, 93 | x_name="x_test", 94 | y_name="y_test", is_cnn=is_cnn) 95 | 96 | if is_cnn: 97 | reshape_size = int(np.sqrt(x_train.shape[1])) 98 | x_train = x_train.view(-1, 1, reshape_size, reshape_size) 99 | x_valid = x_valid.view(-1, 1, reshape_size, reshape_size) 100 | x_test = x_test.view(-1, 1, reshape_size, reshape_size) 101 | 102 | train_ds = TensorDataset(x_train, y_train) 103 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 104 | 105 | test_ds = TensorDataset(x_test, y_test) 106 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 107 | 108 | if is_cnn: 109 | main_model = cm.Netcnn() 110 | else: 111 | main_model = cm.Net2nn() 112 | 113 | cm.weights_init(main_model) 114 | main_model = main_model.to(device) 115 | 116 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=0.9) 117 | main_criterion = nn.CrossEntropyLoss() 118 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_mnist(number_of_samples, learning_rate, 119 | momentum, device, is_cnn) 120 | 121 | 122 | test_accuracies_of_each_iteration = np.array([], dtype=float) 123 | 124 | for iteration in range(iteration_num): 125 | 126 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 127 | number_of_samples) 128 | 129 | tn.start_train_end_node_process_without_print(number_of_samples, x_train_dict, y_train_dict, x_test_dict, y_test_dict, 130 | batch_size, model_dict, criterion_dict, optimizer_dict, numEpoch, device) 131 | 132 | 133 | main_model = tn.set_coordinatewise_med_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, device) 134 | 135 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 136 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 137 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 138 | -------------------------------------------------------------------------------- /MNIST/mnist_byz_median.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | 10 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 11 | print("device: ", device) 12 | 13 | number_of_samples = 100 # number of participants 14 | 15 | is_noniid = True 16 | if is_noniid: 17 | n = 2 18 | min_n_each_node = 2 19 | else: 20 | n = 10 21 | min_n_each_node = 10 22 | 23 | is_cnn = False 24 | is_organized = True 25 | hostile_node_percentage = 0.20 #malicious participant ratio 26 | byzantine_mean =0 27 | byzantine_std =1 28 | 29 | iteration_num = 200 # number of communication rounds 30 | learning_rate = 0.01 31 | 32 | weight_decay = 0.0001 33 | numEpoch = 10 34 | batch_size = 32 35 | momentum = 0.9 36 | 37 | seed = 1 38 | use_seed = 23 39 | hostility_seed = 88 40 | converters_seed = 121 41 | byzantine_seed =25 42 | factor = 1.5 43 | 44 | train_amount = 4000 45 | valid_amount = 900 46 | test_amount = 890 47 | print_amount = 3 48 | 49 | 50 | x_train, y_train, x_valid, y_valid, x_test, y_test = dd.load_mnist_data() 51 | x_test, y_test = dd.get_equal_size_test_data_from_each_label(x_test, y_test, min_amount=test_amount) 52 | 53 | x_train, y_train, x_valid, y_valid, x_test, y_test = map(torch.tensor, 54 | (x_train, y_train, x_valid, y_valid, x_test, y_test)) 55 | 56 | ##train 57 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 58 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 59 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 60 | 61 | x_train_dict, y_train_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_train, 62 | amount=train_amount, 63 | number_of_samples=number_of_samples, 64 | n=n, x_data=x_train, 65 | y_data=y_train, 66 | node_label_info=node_label_info_train, 67 | amount_info_table=amount_info_table_train, 68 | x_name="x_train", 69 | y_name="y_train", 70 | is_cnn=is_cnn) 71 | 72 | ## test 73 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 74 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 75 | number_of_samples=number_of_samples, 76 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 77 | x_test_dict, y_test_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_test, 78 | amount=test_amount, 79 | number_of_samples=number_of_samples, 80 | n=n, x_data=x_test, 81 | y_data=y_test, 82 | node_label_info=node_label_info_test, 83 | amount_info_table=amount_info_table_test, 84 | x_name="x_test", 85 | y_name="y_test", is_cnn=is_cnn) 86 | 87 | if is_cnn: 88 | reshape_size = int(np.sqrt(x_train.shape[1])) 89 | x_train = x_train.view(-1, 1, reshape_size, reshape_size) 90 | x_valid = x_valid.view(-1, 1, reshape_size, reshape_size) 91 | x_test = x_test.view(-1, 1, reshape_size, reshape_size) 92 | 93 | train_ds = TensorDataset(x_train, y_train) 94 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 95 | 96 | test_ds = TensorDataset(x_test, y_test) 97 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 98 | 99 | if is_cnn: 100 | main_model = cm.Netcnn() 101 | else: 102 | main_model = cm.Net2nn() 103 | 104 | main_model = main_model.to(device) 105 | cm.weights_init(main_model) 106 | 107 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, weight_decay=weight_decay) 108 | main_criterion = nn.CrossEntropyLoss() 109 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_mnist(number_of_samples, learning_rate, 110 | momentum, device, is_cnn) 111 | 112 | 113 | test_accuracies_of_each_iteration = np.array([], dtype=float) 114 | 115 | byzantine_node_list = dd.get_byzantine_node_list(hostile_node_percentage, number_of_samples, hostility_seed) 116 | np.random.seed(byzantine_seed) 117 | byzantine_seeds_array = np.random.choice(5000, size=iteration_num, replace=False) 118 | 119 | 120 | for iteration in range(iteration_num): 121 | 122 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 123 | number_of_samples) 124 | 125 | 126 | if is_organized: 127 | iteration_byzantine_seed = byzantine_seeds_array[iteration] 128 | else: 129 | iteration_byzantine_seed =None 130 | 131 | tn.start_train_end_node_process_byzantine(number_of_samples, x_train_dict, y_train_dict, x_test_dict, y_test_dict, 132 | batch_size, model_dict, criterion_dict, optimizer_dict, 133 | numEpoch, byzantine_node_list, byzantine_mean, byzantine_std, 134 | device, iteration_byzantine_seed) 135 | 136 | 137 | main_model = tn.set_coordinatewise_med_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, device) 138 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 139 | 140 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 141 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 142 | 143 | 144 | -------------------------------------------------------------------------------- /MNIST/mnist_lf_trimmed.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | 10 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 11 | print("device: ", device) 12 | 13 | number_of_samples = 100 # number of participants 14 | is_noniid = True 15 | 16 | if is_noniid: 17 | n = 2 18 | min_n_each_node = 2 19 | else: 20 | n = 10 21 | min_n_each_node = 10 22 | 23 | is_cnn = False 24 | is_organized = True 25 | 26 | hostile_node_percentage = 0.20 # malicious participant ratio 27 | 28 | iteration_num = 200 ## number of communication rounds 29 | 30 | learning_rate = 0.01 31 | numEpoch = 10 32 | batch_size = 32 33 | momentum = 0.9 34 | 35 | seed = 1 36 | use_seed = 23 37 | hostility_seed = 77 38 | converters_seed = 51 39 | 40 | train_amount = 4000 41 | valid_amount = 900 42 | test_amount = 890 43 | print_amount = 3 44 | 45 | x_train, y_train, x_valid, y_valid, x_test, y_test = dd.load_mnist_data() 46 | x_test, y_test = dd.get_equal_size_test_data_from_each_label(x_test, y_test, min_amount=test_amount) 47 | 48 | x_train, y_train, x_valid, y_valid, x_test, y_test = map(torch.tensor, 49 | (x_train, y_train, x_valid, y_valid, x_test, y_test)) 50 | 51 | ##train 52 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 53 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 54 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 55 | 56 | x_train_dict, y_train_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_train, 57 | amount=train_amount, 58 | number_of_samples=number_of_samples, 59 | n=n, x_data=x_train, 60 | y_data=y_train, 61 | node_label_info=node_label_info_train, 62 | amount_info_table=amount_info_table_train, 63 | x_name="x_train", 64 | y_name="y_train", 65 | is_cnn=is_cnn) 66 | 67 | 68 | nodes_list = dd.choose_nodes_randomly_to_convert_hostile(hostile_node_percentage, number_of_samples, hostility_seed) 69 | print("hostile_nodes:", nodes_list) 70 | 71 | 72 | if is_organized: 73 | y_train_dict = dd.convert_nodes_to_hostile(y_train_dict, nodes_list, 74 | converter_dict={0: 9, 1: 7, 2: 5, 3: 8, 4: 6, 5: 2, 6: 4, 7: 1, 8: 3, 75 | 9: 0}) 76 | else: 77 | y_train_dict = dd.convert_nodes_to_hostile_with_different_converters(y_train_dict, nodes_list, 78 | converters_seed=converters_seed) 79 | 80 | 81 | ## test 82 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 83 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 84 | number_of_samples=number_of_samples, 85 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 86 | x_test_dict, y_test_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_test, 87 | amount=test_amount, 88 | number_of_samples=number_of_samples, 89 | n=n, x_data=x_test, 90 | y_data=y_test, 91 | node_label_info=node_label_info_test, 92 | amount_info_table=amount_info_table_test, 93 | x_name="x_test", 94 | y_name="y_test", is_cnn=is_cnn) 95 | 96 | if is_cnn: 97 | reshape_size = int(np.sqrt(x_train.shape[1])) 98 | x_train = x_train.view(-1, 1, reshape_size, reshape_size) 99 | x_valid = x_valid.view(-1, 1, reshape_size, reshape_size) 100 | x_test = x_test.view(-1, 1, reshape_size, reshape_size) 101 | 102 | train_ds = TensorDataset(x_train, y_train) 103 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 104 | 105 | test_ds = TensorDataset(x_test, y_test) 106 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 107 | 108 | if is_cnn: 109 | main_model = cm.Netcnn() 110 | else: 111 | main_model = cm.Net2nn() 112 | 113 | cm.weights_init(main_model) 114 | main_model = main_model.to(device) 115 | 116 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=0.9) 117 | main_criterion = nn.CrossEntropyLoss() 118 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_mnist(number_of_samples, learning_rate, 119 | momentum, device, is_cnn) 120 | 121 | 122 | test_accuracies_of_each_iteration = np.array([], dtype=float) 123 | 124 | for iteration in range(iteration_num): 125 | 126 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 127 | number_of_samples) 128 | 129 | tn.start_train_end_node_process_without_print(number_of_samples, x_train_dict, y_train_dict, x_test_dict, y_test_dict, 130 | batch_size, model_dict, criterion_dict, optimizer_dict, numEpoch, device) 131 | 132 | 133 | main_model = tn.set_trimmed_mean_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, 134 | hostile_node_percentage,device) 135 | 136 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 137 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 138 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 139 | -------------------------------------------------------------------------------- /MNIST/mnist_byz_trimmed.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | 10 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 11 | print("device: ", device) 12 | 13 | number_of_samples = 100 # number of participants 14 | 15 | is_noniid = True 16 | if is_noniid: 17 | n = 2 18 | min_n_each_node = 2 19 | else: 20 | n = 10 21 | min_n_each_node = 10 22 | 23 | is_cnn = False 24 | is_organized = True 25 | hostile_node_percentage = 0.20 #malicious participant ratio 26 | byzantine_mean =0 27 | byzantine_std =1 28 | 29 | iteration_num = 200 # number of communication rounds 30 | learning_rate = 0.01 31 | 32 | weight_decay = 0.0001 33 | numEpoch = 10 34 | batch_size = 32 35 | momentum = 0.9 36 | 37 | seed = 1 38 | use_seed = 23 39 | hostility_seed = 88 40 | converters_seed = 121 41 | byzantine_seed =25 42 | factor = 1.5 43 | 44 | train_amount = 4000 45 | valid_amount = 900 46 | test_amount = 890 47 | print_amount = 3 48 | 49 | 50 | x_train, y_train, x_valid, y_valid, x_test, y_test = dd.load_mnist_data() 51 | x_test, y_test = dd.get_equal_size_test_data_from_each_label(x_test, y_test, min_amount=test_amount) 52 | 53 | x_train, y_train, x_valid, y_valid, x_test, y_test = map(torch.tensor, 54 | (x_train, y_train, x_valid, y_valid, x_test, y_test)) 55 | 56 | ##train 57 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 58 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 59 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 60 | 61 | x_train_dict, y_train_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_train, 62 | amount=train_amount, 63 | number_of_samples=number_of_samples, 64 | n=n, x_data=x_train, 65 | y_data=y_train, 66 | node_label_info=node_label_info_train, 67 | amount_info_table=amount_info_table_train, 68 | x_name="x_train", 69 | y_name="y_train", 70 | is_cnn=is_cnn) 71 | 72 | ## test 73 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 74 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 75 | number_of_samples=number_of_samples, 76 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 77 | x_test_dict, y_test_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_test, 78 | amount=test_amount, 79 | number_of_samples=number_of_samples, 80 | n=n, x_data=x_test, 81 | y_data=y_test, 82 | node_label_info=node_label_info_test, 83 | amount_info_table=amount_info_table_test, 84 | x_name="x_test", 85 | y_name="y_test", is_cnn=is_cnn) 86 | 87 | if is_cnn: 88 | reshape_size = int(np.sqrt(x_train.shape[1])) 89 | x_train = x_train.view(-1, 1, reshape_size, reshape_size) 90 | x_valid = x_valid.view(-1, 1, reshape_size, reshape_size) 91 | x_test = x_test.view(-1, 1, reshape_size, reshape_size) 92 | 93 | train_ds = TensorDataset(x_train, y_train) 94 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 95 | 96 | test_ds = TensorDataset(x_test, y_test) 97 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 98 | 99 | if is_cnn: 100 | main_model = cm.Netcnn() 101 | else: 102 | main_model = cm.Net2nn() 103 | 104 | main_model = main_model.to(device) 105 | cm.weights_init(main_model) 106 | 107 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, weight_decay=weight_decay) 108 | main_criterion = nn.CrossEntropyLoss() 109 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_mnist(number_of_samples, learning_rate, 110 | momentum, device, is_cnn) 111 | 112 | 113 | test_accuracies_of_each_iteration = np.array([], dtype=float) 114 | 115 | byzantine_node_list = dd.get_byzantine_node_list(hostile_node_percentage, number_of_samples, hostility_seed) 116 | np.random.seed(byzantine_seed) 117 | byzantine_seeds_array = np.random.choice(5000, size=iteration_num, replace=False) 118 | 119 | 120 | for iteration in range(iteration_num): 121 | 122 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 123 | number_of_samples) 124 | 125 | 126 | if is_organized: 127 | iteration_byzantine_seed = byzantine_seeds_array[iteration] 128 | else: 129 | iteration_byzantine_seed =None 130 | 131 | tn.start_train_end_node_process_byzantine(number_of_samples, x_train_dict, y_train_dict, x_test_dict, y_test_dict, 132 | batch_size, model_dict, criterion_dict, optimizer_dict, 133 | numEpoch, byzantine_node_list, byzantine_mean, byzantine_std, 134 | device, iteration_byzantine_seed) 135 | 136 | 137 | main_model = tn.set_trimmed_mean_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, number_of_samples, 138 | hostile_node_percentage, device) 139 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 140 | 141 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 142 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 143 | 144 | 145 | -------------------------------------------------------------------------------- /CIFAR/cifar_byz_attack.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | from torch.optim import lr_scheduler 10 | 11 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 12 | print("device: ", device) 13 | 14 | number_of_samples = 100 #number of participants 15 | 16 | is_noniid = True 17 | if is_noniid: 18 | n = 5 19 | min_n_each_node = 5 20 | else: 21 | n = 10 22 | min_n_each_node = 10 23 | 24 | is_organized = True 25 | hostile_node_percentage = 0.20 #malicious participant ratio 26 | byzantine_mean = 0 27 | byzantine_std = 1 28 | 29 | iteration_num = 500 #number of communication rounds 30 | learning_rate = 0.0015 31 | min_lr = 0.000010 32 | lr_scheduler_factor = 0.2 33 | best_threshold = 0.0001 34 | clipping = True 35 | clipping_threshold = 10 36 | 37 | weight_decay = 0.0001 38 | numEpoch = 10 39 | batch_size = 100 40 | momentum = 0.9 41 | 42 | seed = 7 43 | use_seed = 17 44 | hostility_seed = 33 45 | converters_seed = 221 46 | byzantine_seed = 96 47 | factor = 1.5 48 | 49 | train_amount = 5000 50 | test_amount = 1000 51 | 52 | 53 | x_train, y_train, x_test, y_test = dd.load_cifar_data() 54 | 55 | ##train 56 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 57 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 58 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 59 | 60 | x_train_dict, y_train_dict = dd.distribute_cifar_data_to_participants(label_dict=label_dict_train, 61 | amount=train_amount, 62 | number_of_samples=number_of_samples, 63 | n=n, x_data=x_train, 64 | y_data=y_train, 65 | node_label_info=node_label_info_train, 66 | amount_info_table=amount_info_table_train, 67 | x_name="x_train", 68 | y_name="y_train") 69 | 70 | ## test 71 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 72 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 73 | number_of_samples=number_of_samples, 74 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 75 | x_test_dict, y_test_dict = dd.distribute_cifar_data_to_participants(label_dict=label_dict_test, 76 | amount=test_amount, 77 | number_of_samples=number_of_samples, 78 | n=n, x_data=x_test, 79 | y_data=y_test, 80 | node_label_info=node_label_info_test, 81 | amount_info_table=amount_info_table_test, 82 | x_name="x_test", 83 | y_name="y_test") 84 | 85 | train_ds = TensorDataset(x_train, y_train) 86 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 87 | 88 | test_ds = TensorDataset(x_test, y_test) 89 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 90 | 91 | main_model = cm.Cifar10CNN() 92 | cm.weights_init(main_model) 93 | main_model = main_model.to(device) 94 | 95 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, 96 | weight_decay=weight_decay) 97 | main_criterion = nn.CrossEntropyLoss() 98 | scheduler = lr_scheduler.ReduceLROnPlateau(main_optimizer, mode="max", factor=lr_scheduler_factor, 99 | patience=10, threshold=best_threshold, verbose=True, min_lr=min_lr) 100 | 101 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_cifar_cnn(number_of_samples, 102 | learning_rate, 103 | momentum, device, 104 | weight_decay) 105 | 106 | test_accuracies_of_each_iteration = np.array([], dtype=float) 107 | 108 | byzantine_node_list = dd.get_byzantine_node_list(hostile_node_percentage, number_of_samples, hostility_seed) 109 | np.random.seed(byzantine_seed) 110 | byzantine_seeds_array = np.random.choice(5000, size=iteration_num, replace=False) 111 | 112 | for iteration in range(iteration_num): 113 | 114 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, number_of_samples) 115 | 116 | if is_organized: 117 | iteration_byzantine_seed = byzantine_seeds_array[iteration] 118 | else: 119 | iteration_byzantine_seed = None 120 | 121 | tn.start_train_end_node_process_byzantine_for_cifar_with_augmentation(number_of_samples, x_train_dict, y_train_dict, 122 | x_test_dict, y_test_dict, 123 | batch_size, model_dict, criterion_dict, 124 | optimizer_dict, 125 | numEpoch, byzantine_node_list, byzantine_mean, 126 | byzantine_std, 127 | device, clipping, clipping_threshold, 128 | iteration_byzantine_seed) 129 | 130 | 131 | main_model = tn.set_averaged_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, device) 132 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 133 | scheduler.step(test_accuracy) 134 | new_lr = main_optimizer.param_groups[0]["lr"] 135 | optimizer_dict = cm.update_learning_rate_decay(optimizer_dict, new_lr) 136 | 137 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 138 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /CIFAR/cifar_byz_median.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | from torch.optim import lr_scheduler 10 | 11 | 12 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 13 | print("device: ", device) 14 | 15 | number_of_samples = 100 #number of participants 16 | 17 | is_noniid = True 18 | if is_noniid: 19 | n = 5 20 | min_n_each_node = 5 21 | else: 22 | n = 10 23 | min_n_each_node = 10 24 | 25 | is_organized = True 26 | hostile_node_percentage = 0.20 #malicious participant ratio 27 | byzantine_mean = 0 28 | byzantine_std = 1 29 | 30 | iteration_num = 500 #number of communication rounds 31 | learning_rate = 0.0015 32 | min_lr = 0.000010 33 | lr_scheduler_factor = 0.2 34 | best_threshold = 0.0001 35 | clipping = True 36 | clipping_threshold = 10 37 | 38 | weight_decay = 0.0001 39 | numEpoch = 10 40 | batch_size = 100 41 | momentum = 0.9 42 | 43 | seed = 7 44 | use_seed = 17 45 | hostility_seed = 33 46 | converters_seed = 221 47 | byzantine_seed = 96 48 | factor = 1.5 49 | 50 | train_amount = 5000 51 | test_amount = 1000 52 | 53 | x_train, y_train, x_test, y_test = dd.load_cifar_data() 54 | 55 | ##train 56 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 57 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 58 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 59 | 60 | x_train_dict, y_train_dict = dd.distribute_cifar_data_to_participants(label_dict=label_dict_train, 61 | amount=train_amount, 62 | number_of_samples=number_of_samples, 63 | n=n, x_data=x_train, 64 | y_data=y_train, 65 | node_label_info=node_label_info_train, 66 | amount_info_table=amount_info_table_train, 67 | x_name="x_train", 68 | y_name="y_train") 69 | 70 | ## test 71 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 72 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 73 | number_of_samples=number_of_samples, 74 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 75 | x_test_dict, y_test_dict = dd.distribute_cifar_data_to_participants(label_dict=label_dict_test, 76 | amount=test_amount, 77 | number_of_samples=number_of_samples, 78 | n=n, x_data=x_test, 79 | y_data=y_test, 80 | node_label_info=node_label_info_test, 81 | amount_info_table=amount_info_table_test, 82 | x_name="x_test", 83 | y_name="y_test") 84 | 85 | train_ds = TensorDataset(x_train, y_train) 86 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 87 | 88 | test_ds = TensorDataset(x_test, y_test) 89 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 90 | 91 | main_model = cm.Cifar10CNN() 92 | cm.weights_init(main_model) 93 | main_model = main_model.to(device) 94 | 95 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, 96 | weight_decay=weight_decay) 97 | main_criterion = nn.CrossEntropyLoss() 98 | scheduler = lr_scheduler.ReduceLROnPlateau(main_optimizer, mode="max", factor=lr_scheduler_factor, 99 | patience=10, threshold=best_threshold, verbose=True, min_lr=min_lr) 100 | 101 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_cifar_cnn(number_of_samples, 102 | learning_rate, 103 | momentum, device, 104 | weight_decay) 105 | 106 | test_accuracies_of_each_iteration = np.array([], dtype=float) 107 | 108 | byzantine_node_list = dd.get_byzantine_node_list(hostile_node_percentage, number_of_samples, hostility_seed) 109 | np.random.seed(byzantine_seed) 110 | byzantine_seeds_array = np.random.choice(5000, size=iteration_num, replace=False) 111 | 112 | 113 | for iteration in range(iteration_num): 114 | 115 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, number_of_samples) 116 | 117 | if is_organized: 118 | iteration_byzantine_seed = byzantine_seeds_array[iteration] 119 | else: 120 | iteration_byzantine_seed = None 121 | 122 | tn.start_train_end_node_process_byzantine_for_cifar_with_augmentation(number_of_samples, x_train_dict, y_train_dict, 123 | x_test_dict, y_test_dict, 124 | batch_size, model_dict, criterion_dict, 125 | optimizer_dict, 126 | numEpoch, byzantine_node_list, byzantine_mean, 127 | byzantine_std, 128 | device, clipping, clipping_threshold, 129 | iteration_byzantine_seed) 130 | 131 | 132 | main_model = tn.set_coordinatewise_med_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, device) 133 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 134 | scheduler.step(test_accuracy) 135 | new_lr = main_optimizer.param_groups[0]["lr"] 136 | optimizer_dict = cm.update_learning_rate_decay(optimizer_dict, new_lr) 137 | 138 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 139 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 140 | 141 | 142 | -------------------------------------------------------------------------------- /CIFAR/cifar_lf_attack.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from torch.optim import lr_scheduler 7 | 8 | from fl_utils import distribute_data as dd 9 | from fl_utils import train_nodes as tn 10 | from fl_utils import construct_models as cm 11 | 12 | 13 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 14 | print("device: ", device) 15 | 16 | number_of_samples = 100 #number of participants 17 | 18 | is_noniid = True 19 | if is_noniid: 20 | n = 5 21 | min_n_each_node = 5 22 | else: 23 | n = 10 24 | min_n_each_node = 10 25 | 26 | is_organized = True 27 | hostile_node_percentage = 0.20 #malicious participant ratio 28 | 29 | iteration_num = 500 #number of communication rounds 30 | learning_rate = 0.0015 31 | min_lr = 0.000010 32 | lr_scheduler_factor =0.2 33 | best_threshold = 0.0001 34 | clipping=True 35 | clipping_threshold =10 36 | 37 | weight_decay = 0.0001 38 | numEpoch = 10 39 | batch_size = 100 40 | momentum = 0.9 41 | 42 | seed = 11 43 | use_seed = 8 44 | hostility_seed = 90 45 | converters_seed = 51 46 | 47 | train_amount = 5000 48 | test_amount = 1000 49 | 50 | 51 | 52 | 53 | x_train, y_train, x_test, y_test = dd.load_cifar_data() 54 | 55 | ##train 56 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 57 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 58 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 59 | 60 | x_train_dict, y_train_dict = dd.distribute_cifar_data_to_participants(label_dict=label_dict_train, 61 | amount=train_amount, 62 | number_of_samples=number_of_samples, 63 | n=n, x_data=x_train, 64 | y_data=y_train, 65 | node_label_info=node_label_info_train, 66 | amount_info_table=amount_info_table_train, 67 | x_name="x_train", 68 | y_name="y_train") 69 | 70 | nodes_list = dd.choose_nodes_randomly_to_convert_hostile(hostile_node_percentage, number_of_samples, hostility_seed) 71 | print("hostile_nodes:", nodes_list) 72 | 73 | if is_organized: 74 | y_train_dict = dd.convert_nodes_to_hostile(y_train_dict, nodes_list, 75 | converter_dict={0: 2, 76 | 1: 9, 77 | 2: 0, 78 | 3: 5, 79 | 4: 7, 80 | 5: 3, 81 | 6: 8, 82 | 7: 4, 83 | 8: 6, 84 | 9: 1}) 85 | else: 86 | y_train_dict = dd.convert_nodes_to_hostile_with_different_converters(y_train_dict, nodes_list, 87 | converters_seed=converters_seed) 88 | 89 | ## test 90 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 91 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 92 | number_of_samples=number_of_samples, 93 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 94 | x_test_dict, y_test_dict = dd.distribute_cifar_data_to_participants(label_dict=label_dict_test, 95 | amount=test_amount, 96 | number_of_samples=number_of_samples, 97 | n=n, x_data=x_test, 98 | y_data=y_test, 99 | node_label_info=node_label_info_test, 100 | amount_info_table=amount_info_table_test, 101 | x_name="x_test", 102 | y_name="y_test") 103 | 104 | train_ds = TensorDataset(x_train, y_train) 105 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 106 | 107 | test_ds = TensorDataset(x_test, y_test) 108 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 109 | 110 | main_model = cm.Cifar10CNN() 111 | cm.weights_init(main_model) 112 | main_model = main_model.to(device) 113 | 114 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, weight_decay=weight_decay) 115 | main_criterion = nn.CrossEntropyLoss() 116 | scheduler = lr_scheduler.ReduceLROnPlateau(main_optimizer, mode="max", factor=lr_scheduler_factor, 117 | patience=10, threshold=best_threshold, verbose=True, min_lr=min_lr) 118 | 119 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_cifar_cnn(number_of_samples, learning_rate, 120 | momentum, device, weight_decay) 121 | 122 | 123 | test_accuracies_of_each_iteration = np.array([], dtype=float) 124 | 125 | for iteration in range(iteration_num): 126 | 127 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 128 | number_of_samples) 129 | 130 | tn.start_train_end_node_process_cifar(number_of_samples, x_train_dict, y_train_dict, x_test_dict, 131 | y_test_dict, batch_size, model_dict, criterion_dict, 132 | optimizer_dict, numEpoch, device, clipping, clipping_threshold) 133 | 134 | 135 | 136 | main_model = tn.set_averaged_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, device) 137 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 138 | scheduler.step(test_accuracy) 139 | new_lr = main_optimizer.param_groups[0]["lr"] 140 | optimizer_dict = cm.update_learning_rate_decay(optimizer_dict, new_lr) 141 | 142 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 143 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 144 | -------------------------------------------------------------------------------- /CIFAR/cifar_lf_median.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from torch.optim import lr_scheduler 7 | from fl_utils import distribute_data as dd 8 | from fl_utils import train_nodes as tn 9 | from fl_utils import construct_models as cm 10 | 11 | 12 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 13 | print("device: ", device) 14 | 15 | number_of_samples = 100 #number of participants 16 | 17 | is_noniid = True 18 | if is_noniid: 19 | n = 5 20 | min_n_each_node = 5 21 | else: 22 | n = 10 23 | min_n_each_node = 10 24 | 25 | is_organized = True 26 | hostile_node_percentage = 0.20 #malicious participant ratio 27 | 28 | iteration_num = 500 #number of communication rounds 29 | learning_rate = 0.0015 30 | min_lr = 0.000010 31 | lr_scheduler_factor =0.2 32 | best_threshold = 0.0001 33 | clipping=True 34 | clipping_threshold =10 35 | 36 | weight_decay = 0.0001 37 | numEpoch = 10 38 | batch_size = 100 39 | momentum = 0.9 40 | 41 | seed = 11 42 | use_seed = 8 43 | hostility_seed = 90 44 | converters_seed = 51 45 | 46 | train_amount = 5000 47 | test_amount = 1000 48 | 49 | 50 | 51 | 52 | x_train, y_train, x_test, y_test = dd.load_cifar_data() 53 | 54 | ##train 55 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 56 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 57 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 58 | 59 | x_train_dict, y_train_dict = dd.distribute_cifar_data_to_participants(label_dict=label_dict_train, 60 | amount=train_amount, 61 | number_of_samples=number_of_samples, 62 | n=n, x_data=x_train, 63 | y_data=y_train, 64 | node_label_info=node_label_info_train, 65 | amount_info_table=amount_info_table_train, 66 | x_name="x_train", 67 | y_name="y_train") 68 | 69 | nodes_list = dd.choose_nodes_randomly_to_convert_hostile(hostile_node_percentage, number_of_samples, hostility_seed) 70 | print("hostile_nodes:", nodes_list) 71 | 72 | if is_organized: 73 | y_train_dict = dd.convert_nodes_to_hostile(y_train_dict, nodes_list, 74 | converter_dict={0: 2, 75 | 1: 9, 76 | 2: 0, 77 | 3: 5, 78 | 4: 7, 79 | 5: 3, 80 | 6: 8, 81 | 7: 4, 82 | 8: 6, 83 | 9: 1}) 84 | else: 85 | y_train_dict = dd.convert_nodes_to_hostile_with_different_converters(y_train_dict, nodes_list, 86 | converters_seed=converters_seed) 87 | 88 | ## test 89 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 90 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 91 | number_of_samples=number_of_samples, 92 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 93 | x_test_dict, y_test_dict = dd.distribute_cifar_data_to_participants(label_dict=label_dict_test, 94 | amount=test_amount, 95 | number_of_samples=number_of_samples, 96 | n=n, x_data=x_test, 97 | y_data=y_test, 98 | node_label_info=node_label_info_test, 99 | amount_info_table=amount_info_table_test, 100 | x_name="x_test", 101 | y_name="y_test") 102 | 103 | train_ds = TensorDataset(x_train, y_train) 104 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 105 | 106 | test_ds = TensorDataset(x_test, y_test) 107 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 108 | 109 | main_model = cm.Cifar10CNN() 110 | cm.weights_init(main_model) 111 | main_model = main_model.to(device) 112 | 113 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, weight_decay=weight_decay) 114 | main_criterion = nn.CrossEntropyLoss() 115 | scheduler = lr_scheduler.ReduceLROnPlateau(main_optimizer, mode="max", factor=lr_scheduler_factor, 116 | patience=10, threshold=best_threshold, verbose=True, min_lr=min_lr) 117 | 118 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_cifar_cnn(number_of_samples, learning_rate, 119 | momentum, device, weight_decay) 120 | 121 | 122 | test_accuracies_of_each_iteration = np.array([], dtype=float) 123 | 124 | for iteration in range(iteration_num): 125 | 126 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 127 | number_of_samples) 128 | 129 | tn.start_train_end_node_process_cifar(number_of_samples, x_train_dict, y_train_dict, x_test_dict, 130 | y_test_dict, batch_size, model_dict, criterion_dict, 131 | optimizer_dict, numEpoch, device, clipping, clipping_threshold) 132 | 133 | 134 | 135 | main_model = tn.set_coordinatewise_med_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, device) 136 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 137 | scheduler.step(test_accuracy) 138 | new_lr = main_optimizer.param_groups[0]["lr"] 139 | optimizer_dict = cm.update_learning_rate_decay(optimizer_dict, new_lr) 140 | 141 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 142 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 143 | -------------------------------------------------------------------------------- /MNIST/mnist_partial_knowledge_attack.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | 10 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 11 | print("device: ", device) 12 | 13 | number_of_samples = 100 # number of participants 14 | 15 | is_noniid = True 16 | if is_noniid: 17 | n = 2 18 | min_n_each_node = 2 19 | else: 20 | n = 10 21 | min_n_each_node = 10 22 | 23 | is_cnn = False 24 | is_organized = True 25 | hostile_node_percentage = 0.20 #malicious participant ratio 26 | byzantine_mean =0 27 | byzantine_std =1 28 | 29 | iteration_num = 200 # number of communication rounds 30 | learning_rate = 0.01 31 | 32 | weight_decay = 0.0001 33 | numEpoch = 10 34 | batch_size = 32 35 | momentum = 0.9 36 | is_clipping = True 37 | 38 | seed = 1 39 | use_seed = 23 40 | hostility_seed = 88 41 | converters_seed = 121 42 | byzantine_seed =25 43 | factor = 1.5 44 | 45 | train_amount = 4000 46 | valid_amount = 900 47 | test_amount = 890 48 | print_amount = 3 49 | 50 | 51 | x_train, y_train, x_valid, y_valid, x_test, y_test = dd.load_mnist_data() 52 | x_test, y_test = dd.get_equal_size_test_data_from_each_label(x_test, y_test, min_amount=test_amount) 53 | 54 | x_train, y_train, x_valid, y_valid, x_test, y_test = map(torch.tensor, 55 | (x_train, y_train, x_valid, y_valid, x_test, y_test)) 56 | 57 | ##train 58 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 59 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 60 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 61 | 62 | x_train_dict, y_train_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_train, 63 | amount=train_amount, 64 | number_of_samples=number_of_samples, 65 | n=n, x_data=x_train, 66 | y_data=y_train, 67 | node_label_info=node_label_info_train, 68 | amount_info_table=amount_info_table_train, 69 | x_name="x_train", 70 | y_name="y_train", 71 | is_cnn=is_cnn) 72 | 73 | ## test 74 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 75 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 76 | number_of_samples=number_of_samples, 77 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 78 | x_test_dict, y_test_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_test, 79 | amount=test_amount, 80 | number_of_samples=number_of_samples, 81 | n=n, x_data=x_test, 82 | y_data=y_test, 83 | node_label_info=node_label_info_test, 84 | amount_info_table=amount_info_table_test, 85 | x_name="x_test", 86 | y_name="y_test", is_cnn=is_cnn) 87 | 88 | if is_cnn: 89 | reshape_size = int(np.sqrt(x_train.shape[1])) 90 | x_train = x_train.view(-1, 1, reshape_size, reshape_size) 91 | x_valid = x_valid.view(-1, 1, reshape_size, reshape_size) 92 | x_test = x_test.view(-1, 1, reshape_size, reshape_size) 93 | 94 | train_ds = TensorDataset(x_train, y_train) 95 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 96 | 97 | test_ds = TensorDataset(x_test, y_test) 98 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 99 | 100 | if is_cnn: 101 | main_model = cm.Netcnn() 102 | else: 103 | main_model = cm.Net2nn() 104 | 105 | main_model = main_model.to(device) 106 | cm.weights_init(main_model) 107 | 108 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, weight_decay=weight_decay) 109 | main_criterion = nn.CrossEntropyLoss() 110 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_mnist(number_of_samples, learning_rate, 111 | momentum, device, is_cnn) 112 | 113 | 114 | test_accuracies_of_each_iteration = np.array([], dtype=float) 115 | 116 | byzantine_node_list = dd.get_byzantine_node_list(hostile_node_percentage, number_of_samples, hostility_seed) 117 | np.random.seed(byzantine_seed) 118 | byzantine_seeds_array = np.random.choice(5000, size=iteration_num, replace=False) 119 | 120 | for iteration in range(iteration_num): 121 | 122 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 123 | number_of_samples) 124 | 125 | tn.start_train_end_node_process_with_clipping(number_of_samples, x_train_dict, y_train_dict, x_test_dict, 126 | y_test_dict, 127 | batch_size, model_dict, criterion_dict, optimizer_dict, numEpoch, 128 | device, clipping=is_clipping, clipping_threshold=5) 129 | 130 | if is_organized: 131 | iteration_byzantine_seed = byzantine_seeds_array[iteration] 132 | model_dict = tn.partial_knowledge_fang_org(main_model, model_dict, byzantine_node_list, 133 | iteration_byzantine_seed, device) 134 | else: 135 | iteration_byzantine_seed = None 136 | model_dict = tn.partial_knowledge_fang_ind(main_model, model_dict, byzantine_node_list, 137 | iteration_byzantine_seed, device) 138 | 139 | main_model = tn.set_averaged_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, device) 140 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 141 | 142 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 143 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 144 | -------------------------------------------------------------------------------- /MNIST/mnist_partial_knowledge_median.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | 10 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 11 | print("device: ", device) 12 | 13 | number_of_samples = 100 # number of participants 14 | 15 | is_noniid = True 16 | if is_noniid: 17 | n = 2 18 | min_n_each_node = 2 19 | else: 20 | n = 10 21 | min_n_each_node = 10 22 | 23 | is_cnn = False 24 | is_organized = True 25 | hostile_node_percentage = 0.20 #malicious participant ratio 26 | byzantine_mean =0 27 | byzantine_std =1 28 | 29 | iteration_num = 200 # number of communication rounds 30 | learning_rate = 0.01 31 | 32 | weight_decay = 0.0001 33 | numEpoch = 10 34 | batch_size = 32 35 | momentum = 0.9 36 | is_clipping = True 37 | 38 | seed = 1 39 | use_seed = 23 40 | hostility_seed = 88 41 | converters_seed = 121 42 | byzantine_seed =25 43 | factor = 1.5 44 | 45 | train_amount = 4000 46 | valid_amount = 900 47 | test_amount = 890 48 | print_amount = 3 49 | 50 | 51 | x_train, y_train, x_valid, y_valid, x_test, y_test = dd.load_mnist_data() 52 | x_test, y_test = dd.get_equal_size_test_data_from_each_label(x_test, y_test, min_amount=test_amount) 53 | 54 | x_train, y_train, x_valid, y_valid, x_test, y_test = map(torch.tensor, 55 | (x_train, y_train, x_valid, y_valid, x_test, y_test)) 56 | 57 | ##train 58 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 59 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 60 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 61 | 62 | x_train_dict, y_train_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_train, 63 | amount=train_amount, 64 | number_of_samples=number_of_samples, 65 | n=n, x_data=x_train, 66 | y_data=y_train, 67 | node_label_info=node_label_info_train, 68 | amount_info_table=amount_info_table_train, 69 | x_name="x_train", 70 | y_name="y_train", 71 | is_cnn=is_cnn) 72 | 73 | ## test 74 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 75 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 76 | number_of_samples=number_of_samples, 77 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 78 | x_test_dict, y_test_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_test, 79 | amount=test_amount, 80 | number_of_samples=number_of_samples, 81 | n=n, x_data=x_test, 82 | y_data=y_test, 83 | node_label_info=node_label_info_test, 84 | amount_info_table=amount_info_table_test, 85 | x_name="x_test", 86 | y_name="y_test", is_cnn=is_cnn) 87 | 88 | if is_cnn: 89 | reshape_size = int(np.sqrt(x_train.shape[1])) 90 | x_train = x_train.view(-1, 1, reshape_size, reshape_size) 91 | x_valid = x_valid.view(-1, 1, reshape_size, reshape_size) 92 | x_test = x_test.view(-1, 1, reshape_size, reshape_size) 93 | 94 | train_ds = TensorDataset(x_train, y_train) 95 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 96 | 97 | test_ds = TensorDataset(x_test, y_test) 98 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 99 | 100 | if is_cnn: 101 | main_model = cm.Netcnn() 102 | else: 103 | main_model = cm.Net2nn() 104 | 105 | main_model = main_model.to(device) 106 | cm.weights_init(main_model) 107 | 108 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, weight_decay=weight_decay) 109 | main_criterion = nn.CrossEntropyLoss() 110 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_mnist(number_of_samples, learning_rate, 111 | momentum, device, is_cnn) 112 | 113 | 114 | test_accuracies_of_each_iteration = np.array([], dtype=float) 115 | 116 | byzantine_node_list = dd.get_byzantine_node_list(hostile_node_percentage, number_of_samples, hostility_seed) 117 | np.random.seed(byzantine_seed) 118 | byzantine_seeds_array = np.random.choice(5000, size=iteration_num, replace=False) 119 | 120 | for iteration in range(iteration_num): 121 | 122 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 123 | number_of_samples) 124 | 125 | tn.start_train_end_node_process_with_clipping(number_of_samples, x_train_dict, y_train_dict, x_test_dict, 126 | y_test_dict, 127 | batch_size, model_dict, criterion_dict, optimizer_dict, numEpoch, 128 | device, clipping=is_clipping, clipping_threshold=5) 129 | 130 | if is_organized: 131 | iteration_byzantine_seed = byzantine_seeds_array[iteration] 132 | model_dict = tn.partial_knowledge_fang_org(main_model, model_dict, byzantine_node_list, 133 | iteration_byzantine_seed, device) 134 | else: 135 | iteration_byzantine_seed = None 136 | model_dict = tn.partial_knowledge_fang_ind(main_model, model_dict, byzantine_node_list, 137 | iteration_byzantine_seed, device) 138 | 139 | main_model = tn.set_coordinatewise_med_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, device) 140 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 141 | 142 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 143 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 144 | -------------------------------------------------------------------------------- /MNIST/mnist_partial_knowledge_trimmed.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import numpy as np 6 | from fl_utils import distribute_data as dd 7 | from fl_utils import train_nodes as tn 8 | from fl_utils import construct_models as cm 9 | 10 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 11 | print("device: ", device) 12 | 13 | number_of_samples = 100 # number of participants 14 | 15 | is_noniid = True 16 | if is_noniid: 17 | n = 2 18 | min_n_each_node = 2 19 | else: 20 | n = 10 21 | min_n_each_node = 10 22 | 23 | is_cnn = False 24 | is_organized = True 25 | hostile_node_percentage = 0.20 #malicious participant ratio 26 | byzantine_mean =0 27 | byzantine_std =1 28 | 29 | iteration_num = 200 # number of communication rounds 30 | learning_rate = 0.01 31 | 32 | weight_decay = 0.0001 33 | numEpoch = 10 34 | batch_size = 32 35 | momentum = 0.9 36 | is_clipping = True 37 | 38 | seed = 1 39 | use_seed = 23 40 | hostility_seed = 88 41 | converters_seed = 121 42 | byzantine_seed =25 43 | factor = 1.5 44 | 45 | train_amount = 4000 46 | valid_amount = 900 47 | test_amount = 890 48 | print_amount = 3 49 | 50 | 51 | x_train, y_train, x_valid, y_valid, x_test, y_test = dd.load_mnist_data() 52 | x_test, y_test = dd.get_equal_size_test_data_from_each_label(x_test, y_test, min_amount=test_amount) 53 | 54 | x_train, y_train, x_valid, y_valid, x_test, y_test = map(torch.tensor, 55 | (x_train, y_train, x_valid, y_valid, x_test, y_test)) 56 | 57 | ##train 58 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 59 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 60 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 61 | 62 | x_train_dict, y_train_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_train, 63 | amount=train_amount, 64 | number_of_samples=number_of_samples, 65 | n=n, x_data=x_train, 66 | y_data=y_train, 67 | node_label_info=node_label_info_train, 68 | amount_info_table=amount_info_table_train, 69 | x_name="x_train", 70 | y_name="y_train", 71 | is_cnn=is_cnn) 72 | 73 | ## test 74 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 75 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 76 | number_of_samples=number_of_samples, 77 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 78 | x_test_dict, y_test_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_test, 79 | amount=test_amount, 80 | number_of_samples=number_of_samples, 81 | n=n, x_data=x_test, 82 | y_data=y_test, 83 | node_label_info=node_label_info_test, 84 | amount_info_table=amount_info_table_test, 85 | x_name="x_test", 86 | y_name="y_test", is_cnn=is_cnn) 87 | 88 | if is_cnn: 89 | reshape_size = int(np.sqrt(x_train.shape[1])) 90 | x_train = x_train.view(-1, 1, reshape_size, reshape_size) 91 | x_valid = x_valid.view(-1, 1, reshape_size, reshape_size) 92 | x_test = x_test.view(-1, 1, reshape_size, reshape_size) 93 | 94 | train_ds = TensorDataset(x_train, y_train) 95 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 96 | 97 | test_ds = TensorDataset(x_test, y_test) 98 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 99 | 100 | if is_cnn: 101 | main_model = cm.Netcnn() 102 | else: 103 | main_model = cm.Net2nn() 104 | 105 | main_model = main_model.to(device) 106 | cm.weights_init(main_model) 107 | 108 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, weight_decay=weight_decay) 109 | main_criterion = nn.CrossEntropyLoss() 110 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_mnist(number_of_samples, learning_rate, 111 | momentum, device, is_cnn) 112 | 113 | 114 | test_accuracies_of_each_iteration = np.array([], dtype=float) 115 | 116 | byzantine_node_list = dd.get_byzantine_node_list(hostile_node_percentage, number_of_samples, hostility_seed) 117 | np.random.seed(byzantine_seed) 118 | byzantine_seeds_array = np.random.choice(5000, size=iteration_num, replace=False) 119 | 120 | for iteration in range(iteration_num): 121 | 122 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 123 | number_of_samples) 124 | 125 | tn.start_train_end_node_process_with_clipping(number_of_samples, x_train_dict, y_train_dict, x_test_dict, 126 | y_test_dict, 127 | batch_size, model_dict, criterion_dict, optimizer_dict, numEpoch, 128 | device, clipping=is_clipping, clipping_threshold=5) 129 | 130 | if is_organized: 131 | iteration_byzantine_seed = byzantine_seeds_array[iteration] 132 | model_dict = tn.partial_knowledge_fang_org(main_model, model_dict, byzantine_node_list, 133 | iteration_byzantine_seed, device) 134 | else: 135 | iteration_byzantine_seed = None 136 | model_dict = tn.partial_knowledge_fang_ind(main_model, model_dict, byzantine_node_list, 137 | iteration_byzantine_seed, device) 138 | 139 | main_model = tn.set_trimmed_mean_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, hostile_node_percentage, device) 140 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 141 | 142 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 143 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 144 | -------------------------------------------------------------------------------- /FashionMNIST/fashion_lf_barfed.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import pandas as pd 6 | import numpy as np 7 | from fl_utils import distribute_data as dd 8 | from fl_utils import train_nodes as tn 9 | from fl_utils import construct_models as cm 10 | 11 | 12 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 13 | print("device: ", device) 14 | 15 | number_of_samples = 100 # number of participants 16 | 17 | is_noniid = True 18 | if is_noniid: 19 | n = 2 20 | min_n_each_node = 2 21 | else: 22 | n = 10 23 | min_n_each_node = 10 24 | 25 | is_organized=True 26 | hostile_node_percentage =0.20 #malicious node ratio 27 | 28 | iteration_num = 200 # number of communication rounds 29 | learning_rate = 0.0020 30 | 31 | weight_decay = 0.0001 32 | numEpoch = 10 33 | batch_size = 25 34 | momentum = 0.9 35 | 36 | seed = 5 37 | use_seed = 71 38 | hostility_seed =89 39 | converters_seed = 41 40 | 41 | train_amount = 6000 42 | test_amount = 1000 43 | 44 | 45 | x_train, y_train, x_test, y_test = dd.load_fashion_mnist_data() 46 | dd.show_grid_fashion_mnist(x_train, y_train, 6, 6) 47 | 48 | ##train 49 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 50 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 51 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 52 | 53 | x_train_dict, y_train_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_train, 54 | amount=train_amount, 55 | number_of_samples=number_of_samples, 56 | n=n, x_data=x_train, 57 | y_data=y_train, 58 | node_label_info=node_label_info_train, 59 | amount_info_table=amount_info_table_train, 60 | x_name="x_train", 61 | y_name="y_train") 62 | 63 | 64 | nodes_list = dd.choose_nodes_randomly_to_convert_hostile(hostile_node_percentage, number_of_samples, hostility_seed) 65 | print("hostile_nodes:", nodes_list) 66 | 67 | if is_organized: 68 | y_train_dict = dd.convert_nodes_to_hostile(y_train_dict, nodes_list, 69 | converter_dict={0: 6, 1: 3, 2: 4, 70 | 3: 1,4: 2, 5: 7,6: 0, 71 | 7: 9,8: 5,9: 7}) 72 | else: 73 | y_train_dict = dd.convert_nodes_to_hostile_with_different_converters(y_train_dict, nodes_list, 74 | converters_seed=converters_seed) 75 | 76 | 77 | ## test 78 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 79 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 80 | number_of_samples=number_of_samples, 81 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 82 | x_test_dict, y_test_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_test, 83 | amount=test_amount, 84 | number_of_samples=number_of_samples, 85 | n=n, x_data=x_test, 86 | y_data=y_test, 87 | node_label_info=node_label_info_test, 88 | amount_info_table=amount_info_table_test, 89 | x_name="x_test", 90 | y_name="y_test") 91 | 92 | x_train = x_train.view(-1, 1, 28, 28) 93 | x_test = x_test.view(-1, 1, 28, 28) 94 | 95 | 96 | train_ds = TensorDataset(x_train, y_train) 97 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 98 | 99 | test_ds = TensorDataset(x_test, y_test) 100 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 101 | 102 | 103 | main_model = cm.Net_fashion() 104 | main_model = main_model.to(device) 105 | cm.weights_init(main_model) 106 | 107 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, weight_decay=weight_decay) 108 | main_criterion = nn.CrossEntropyLoss() 109 | 110 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_fashion_mnist(number_of_samples, learning_rate, 111 | momentum, device, weight_decay) 112 | 113 | test_accuracies_of_each_iteration = np.array([], dtype=float) 114 | its = np.array([], dtype=int) 115 | distances = pd.DataFrame() 116 | thresholds = pd.DataFrame() 117 | 118 | 119 | for iteration in range(iteration_num): 120 | its = np.concatenate((its, np.ones(number_of_samples, dtype=int) * (iteration + 1))) 121 | 122 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 123 | number_of_samples) 124 | 125 | 126 | tn.start_train_end_node_process_without_print(number_of_samples, x_train_dict, y_train_dict, x_test_dict, 127 | y_test_dict, 128 | batch_size, model_dict, criterion_dict, optimizer_dict, numEpoch, 129 | device) 130 | 131 | iteration_distance = tn.calculate_euclidean_distances(main_model, model_dict) 132 | iteration_distance, iteration_threshold = tn.get_outlier_situation_and_thresholds_for_layers( 133 | iteration_distance) 134 | 135 | thresholds = pd.concat([thresholds, iteration_threshold]) 136 | distances = pd.concat([distances, iteration_distance]) 137 | 138 | 139 | main_model = tn.strict_condition_without_outliers_set_averaged_weights_as_main_model_weights_and_update_main_model( main_model, 140 | model_dict, iteration_distance, device) 141 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 142 | 143 | 144 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 145 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 146 | 147 | 148 | distances["iteration"] = its 149 | thresholds["iteration"] = np.arange(1, iteration_num + 1) 150 | -------------------------------------------------------------------------------- /FashionMNIST/fashion_partial_knowledge_arfed.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import pandas as pd 6 | import numpy as np 7 | from fl_utils import distribute_data as dd 8 | from fl_utils import train_nodes as tn 9 | from fl_utils import construct_models as cm 10 | 11 | 12 | 13 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 14 | print("device: ", device) 15 | 16 | number_of_samples = 100 # number of participants 17 | 18 | is_noniid = True 19 | if is_noniid: 20 | n = 2 21 | min_n_each_node = 2 22 | else: 23 | n = 10 24 | min_n_each_node = 10 25 | 26 | is_organized = True 27 | hostile_node_percentage = 0.20 # malicious participant ratio 28 | byzantine_mean =0 29 | byzantine_std =1 30 | 31 | 32 | iteration_num = 200 # number of communication rounds 33 | learning_rate = 0.0020 34 | 35 | 36 | weight_decay = 0.0001 37 | numEpoch = 10 38 | batch_size = 25 39 | momentum = 0.9 40 | is_clipping =True 41 | 42 | seed = 6 43 | use_seed = 13 44 | hostility_seed = 210 45 | converters_seed = 42 46 | byzantine_seed =83 47 | factor = 1.5 48 | 49 | train_amount = 6000 50 | test_amount = 1000 51 | 52 | x_train, y_train, x_test, y_test = dd.load_fashion_mnist_data() 53 | dd.show_grid_fashion_mnist(x_train, y_train, 6, 6) 54 | 55 | ##train 56 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 57 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 58 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 59 | 60 | x_train_dict, y_train_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_train, 61 | amount=train_amount, 62 | number_of_samples=number_of_samples, 63 | n=n, x_data=x_train, 64 | y_data=y_train, 65 | node_label_info=node_label_info_train, 66 | amount_info_table=amount_info_table_train, 67 | x_name="x_train", 68 | y_name="y_train") 69 | 70 | 71 | ## test 72 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 73 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 74 | number_of_samples=number_of_samples, 75 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 76 | x_test_dict, y_test_dict = dd.distribute_fashion_data_to_participants(label_dict=label_dict_test, 77 | amount=test_amount, 78 | number_of_samples=number_of_samples, 79 | n=n, x_data=x_test, 80 | y_data=y_test, 81 | node_label_info=node_label_info_test, 82 | amount_info_table=amount_info_table_test, 83 | x_name="x_test", 84 | y_name="y_test") 85 | 86 | x_train = x_train.view(-1, 1, 28, 28) 87 | x_test = x_test.view(-1, 1, 28, 28) 88 | 89 | 90 | train_ds = TensorDataset(x_train, y_train) 91 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 92 | 93 | test_ds = TensorDataset(x_test, y_test) 94 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 95 | 96 | main_model = cm.Net_fashion() 97 | main_model = main_model.to(device) 98 | cm.weights_init(main_model) 99 | 100 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, weight_decay=weight_decay) 101 | main_criterion = nn.CrossEntropyLoss() 102 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_fashion_mnist(number_of_samples, learning_rate, 103 | momentum, device, weight_decay) 104 | 105 | 106 | test_accuracies_of_each_iteration = np.array([], dtype=float) 107 | its = np.array([], dtype=int) 108 | distances = pd.DataFrame() 109 | thresholds = pd.DataFrame() 110 | 111 | byzantine_node_list = dd.get_byzantine_node_list(hostile_node_percentage, number_of_samples, hostility_seed) 112 | np.random.seed(byzantine_seed) 113 | byzantine_seeds_array = np.random.choice(5000, size=iteration_num, replace=False) 114 | 115 | 116 | for iteration in range(iteration_num): 117 | its = np.concatenate((its, np.ones(number_of_samples, dtype=int) * (iteration + 1))) 118 | 119 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 120 | number_of_samples) 121 | 122 | tn.start_train_end_node_process_with_clipping(number_of_samples, x_train_dict, y_train_dict, x_test_dict, 123 | y_test_dict, batch_size, model_dict, criterion_dict, optimizer_dict, 124 | numEpoch, device, clipping=is_clipping, clipping_threshold=10) 125 | 126 | if is_organized: 127 | iteration_byzantine_seed = byzantine_seeds_array[iteration] 128 | model_dict = tn.partial_knowledge_fang_org(main_model, model_dict, byzantine_node_list, 129 | iteration_byzantine_seed, device) 130 | else: 131 | iteration_byzantine_seed = None 132 | model_dict = tn.partial_knowledge_fang_ind(main_model, model_dict, byzantine_node_list, 133 | iteration_byzantine_seed, device) 134 | 135 | iteration_distance = tn.calculate_euclidean_distances(main_model, model_dict) 136 | iteration_distance, iteration_threshold = tn.get_outlier_situation_and_thresholds_for_layers( 137 | iteration_distance) 138 | 139 | thresholds = pd.concat([thresholds, iteration_threshold]) 140 | distances = pd.concat([distances, iteration_distance]) 141 | 142 | 143 | main_model = tn.strict_condition_without_outliers_set_averaged_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, iteration_distance, device) 144 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 145 | 146 | 147 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 148 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 149 | 150 | distances["iteration"] = its 151 | thresholds["iteration"] = np.arange(1, iteration_num + 1) 152 | 153 | print(test_accuracies_of_each_iteration) -------------------------------------------------------------------------------- /CIFAR/cifar_byz_barfed.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import pandas as pd 6 | import numpy as np 7 | from fl_utils import distribute_data as dd 8 | from fl_utils import train_nodes as tn 9 | from fl_utils import construct_models as cm 10 | from torch.optim import lr_scheduler 11 | 12 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 13 | print("device: ", device) 14 | 15 | number_of_samples = 100 #number of participants 16 | 17 | is_noniid = True 18 | if is_noniid: 19 | n = 5 20 | min_n_each_node = 5 21 | else: 22 | n = 10 23 | min_n_each_node = 10 24 | 25 | is_organized = True 26 | hostile_node_percentage = 0.20 #malicious participant ratio 27 | byzantine_mean =0 28 | byzantine_std =1 29 | 30 | iteration_num = 500 #number of communication rounds 31 | learning_rate = 0.0015 32 | min_lr = 0.000010 33 | lr_scheduler_factor =0.2 34 | best_threshold = 0.0001 35 | clipping=True 36 | clipping_threshold =10 37 | 38 | 39 | 40 | weight_decay = 0.0001 41 | numEpoch = 10 42 | batch_size = 100 43 | momentum = 0.9 44 | 45 | seed = 7 46 | use_seed = 17 47 | hostility_seed = 33 48 | converters_seed = 221 49 | byzantine_seed =96 50 | factor = 1.5 51 | 52 | train_amount = 5000 53 | test_amount = 1000 54 | 55 | x_train, y_train, x_test, y_test = dd.load_cifar_data() 56 | 57 | ##train 58 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 59 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 60 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 61 | 62 | x_train_dict, y_train_dict = dd.distribute_cifar_data_to_participants(label_dict=label_dict_train, 63 | amount=train_amount, 64 | number_of_samples=number_of_samples, 65 | n=n, x_data=x_train, 66 | y_data=y_train, 67 | node_label_info=node_label_info_train, 68 | amount_info_table=amount_info_table_train, 69 | x_name="x_train", 70 | y_name="y_train") 71 | 72 | 73 | 74 | ## test 75 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 76 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 77 | number_of_samples=number_of_samples, 78 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 79 | x_test_dict, y_test_dict = dd.distribute_cifar_data_to_participants(label_dict=label_dict_test, 80 | amount=test_amount, 81 | number_of_samples=number_of_samples, 82 | n=n, x_data=x_test, 83 | y_data=y_test, 84 | node_label_info=node_label_info_test, 85 | amount_info_table=amount_info_table_test, 86 | x_name="x_test", 87 | y_name="y_test") 88 | 89 | train_ds = TensorDataset(x_train, y_train) 90 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 91 | 92 | test_ds = TensorDataset(x_test, y_test) 93 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 94 | 95 | 96 | main_model = cm.Cifar10CNN() 97 | cm.weights_init(main_model) 98 | main_model = main_model.to(device) 99 | 100 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, weight_decay=weight_decay) 101 | main_criterion = nn.CrossEntropyLoss() 102 | scheduler = lr_scheduler.ReduceLROnPlateau(main_optimizer, mode="max", factor=lr_scheduler_factor, 103 | patience=10, threshold=best_threshold, verbose=True, min_lr=min_lr) 104 | 105 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_cifar_cnn(number_of_samples, learning_rate, 106 | momentum, device, weight_decay) 107 | 108 | 109 | test_accuracies_of_each_iteration = np.array([], dtype=float) 110 | its = np.array([], dtype=int) 111 | distances = pd.DataFrame() 112 | thresholds = pd.DataFrame() 113 | 114 | 115 | byzantine_node_list = dd.get_byzantine_node_list(hostile_node_percentage, number_of_samples, hostility_seed) 116 | np.random.seed(byzantine_seed) 117 | byzantine_seeds_array = np.random.choice(5000, size=iteration_num, replace=False) 118 | 119 | for iteration in range(iteration_num): 120 | its = np.concatenate((its, np.ones(number_of_samples, dtype=int) * (iteration + 1))) 121 | 122 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, number_of_samples) 123 | 124 | 125 | if is_organized: 126 | iteration_byzantine_seed = byzantine_seeds_array[iteration] 127 | else: 128 | iteration_byzantine_seed =None 129 | 130 | tn.start_train_end_node_process_byzantine_for_cifar_with_augmentation(number_of_samples, x_train_dict, y_train_dict, 131 | x_test_dict, y_test_dict, 132 | batch_size, model_dict, criterion_dict, 133 | optimizer_dict, 134 | numEpoch, byzantine_node_list, byzantine_mean, 135 | byzantine_std, 136 | device, clipping,clipping_threshold, iteration_byzantine_seed) 137 | 138 | 139 | 140 | iteration_distance = tn.calculate_euclidean_distances(main_model, model_dict) 141 | iteration_distance, iteration_threshold = tn.get_outlier_situation_and_thresholds_for_layers( 142 | iteration_distance) 143 | 144 | thresholds = pd.concat([thresholds, iteration_threshold]) 145 | distances = pd.concat([distances, iteration_distance]) 146 | 147 | main_model = tn.strict_condition_without_outliers_set_averaged_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, iteration_distance, device) 148 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 149 | scheduler.step(test_accuracy) 150 | new_lr = main_optimizer.param_groups[0]["lr"] 151 | optimizer_dict = cm.update_learning_rate_decay(optimizer_dict, new_lr) 152 | 153 | 154 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 155 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 156 | 157 | 158 | distances["iteration"] = its 159 | thresholds["iteration"] = np.arange(1, iteration_num + 1) 160 | -------------------------------------------------------------------------------- /MNIST/mnist_byz_arfed.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import pandas as pd 6 | import numpy as np 7 | from fl_utils import distribute_data as dd 8 | from fl_utils import train_nodes as tn 9 | from fl_utils import construct_models as cm 10 | 11 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 12 | print("device: ", device) 13 | 14 | number_of_samples = 100 # number of participants 15 | 16 | is_noniid = True 17 | if is_noniid: 18 | n = 2 19 | min_n_each_node = 2 20 | else: 21 | n = 10 22 | min_n_each_node = 10 23 | 24 | is_cnn = False 25 | is_organized = True 26 | hostile_node_percentage = 0.20 #malicious participant ratio 27 | byzantine_mean =0 28 | byzantine_std =1 29 | 30 | iteration_num = 200 # number of communication rounds 31 | learning_rate = 0.01 32 | 33 | weight_decay = 0.0001 34 | numEpoch = 10 35 | batch_size = 32 36 | momentum = 0.9 37 | 38 | seed = 1 39 | use_seed = 23 40 | hostility_seed = 88 41 | converters_seed = 121 42 | byzantine_seed =25 43 | factor = 1.5 44 | 45 | train_amount = 4000 46 | valid_amount = 900 47 | test_amount = 890 48 | print_amount = 3 49 | 50 | 51 | x_train, y_train, x_valid, y_valid, x_test, y_test = dd.load_mnist_data() 52 | x_test, y_test = dd.get_equal_size_test_data_from_each_label(x_test, y_test, min_amount=test_amount) 53 | 54 | x_train, y_train, x_valid, y_valid, x_test, y_test = map(torch.tensor, 55 | (x_train, y_train, x_valid, y_valid, x_test, y_test)) 56 | 57 | ##train 58 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 59 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 60 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 61 | 62 | x_train_dict, y_train_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_train, 63 | amount=train_amount, 64 | number_of_samples=number_of_samples, 65 | n=n, x_data=x_train, 66 | y_data=y_train, 67 | node_label_info=node_label_info_train, 68 | amount_info_table=amount_info_table_train, 69 | x_name="x_train", 70 | y_name="y_train", 71 | is_cnn=is_cnn) 72 | 73 | ## test 74 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 75 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 76 | number_of_samples=number_of_samples, 77 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 78 | x_test_dict, y_test_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_test, 79 | amount=test_amount, 80 | number_of_samples=number_of_samples, 81 | n=n, x_data=x_test, 82 | y_data=y_test, 83 | node_label_info=node_label_info_test, 84 | amount_info_table=amount_info_table_test, 85 | x_name="x_test", 86 | y_name="y_test", is_cnn=is_cnn) 87 | 88 | if is_cnn: 89 | reshape_size = int(np.sqrt(x_train.shape[1])) 90 | x_train = x_train.view(-1, 1, reshape_size, reshape_size) 91 | x_valid = x_valid.view(-1, 1, reshape_size, reshape_size) 92 | x_test = x_test.view(-1, 1, reshape_size, reshape_size) 93 | 94 | train_ds = TensorDataset(x_train, y_train) 95 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 96 | 97 | test_ds = TensorDataset(x_test, y_test) 98 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 99 | 100 | if is_cnn: 101 | main_model = cm.Netcnn() 102 | else: 103 | main_model = cm.Net2nn() 104 | 105 | main_model = main_model.to(device) 106 | cm.weights_init(main_model) 107 | 108 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, weight_decay=weight_decay) 109 | main_criterion = nn.CrossEntropyLoss() 110 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_mnist(number_of_samples, learning_rate, 111 | momentum, device, is_cnn) 112 | 113 | 114 | test_accuracies_of_each_iteration = np.array([], dtype=float) 115 | its = np.array([], dtype=int) 116 | distances = pd.DataFrame() 117 | thresholds = pd.DataFrame() 118 | 119 | byzantine_node_list = dd.get_byzantine_node_list(hostile_node_percentage, number_of_samples, hostility_seed) 120 | np.random.seed(byzantine_seed) 121 | byzantine_seeds_array = np.random.choice(5000, size=iteration_num, replace=False) 122 | 123 | for iteration in range(iteration_num): 124 | its = np.concatenate((its, np.ones(number_of_samples, dtype=int) * (iteration + 1))) 125 | 126 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 127 | number_of_samples) 128 | 129 | 130 | if is_organized: 131 | iteration_byzantine_seed = byzantine_seeds_array[iteration] 132 | else: 133 | iteration_byzantine_seed =None 134 | 135 | tn.start_train_end_node_process_byzantine(number_of_samples, x_train_dict, y_train_dict, x_test_dict, y_test_dict, 136 | batch_size, model_dict, criterion_dict, optimizer_dict, 137 | numEpoch, byzantine_node_list, byzantine_mean, byzantine_std, 138 | device, iteration_byzantine_seed) 139 | 140 | iteration_distance = tn.calculate_euclidean_distances(main_model, model_dict) 141 | iteration_distance, iteration_threshold = tn.get_outlier_situation_and_thresholds_for_layers( 142 | iteration_distance) 143 | 144 | thresholds = pd.concat([thresholds, iteration_threshold]) 145 | distances = pd.concat([distances, iteration_distance]) 146 | 147 | 148 | main_model = tn.strict_condition_without_outliers_set_averaged_weights_as_main_model_weights_and_update_main_model(main_model, model_dict, iteration_distance, device) 149 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 150 | 151 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 152 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 153 | 154 | 155 | distances["iteration"] = its 156 | thresholds["iteration"] = np.arange(1, iteration_num + 1) 157 | 158 | 159 | -------------------------------------------------------------------------------- /MNIST/mnist_lf_arfed.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import pandas as pd 6 | import numpy as np 7 | from fl_utils import distribute_data as dd 8 | from fl_utils import train_nodes as tn 9 | from fl_utils import construct_models as cm 10 | 11 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 12 | print("device: ", device) 13 | 14 | number_of_samples = 100 # number of participantss 15 | is_noniid = True 16 | 17 | if is_noniid: 18 | n = 2 19 | min_n_each_node = 2 20 | else: 21 | n = 10 22 | min_n_each_node = 10 23 | 24 | is_cnn = False 25 | is_organized = True 26 | 27 | hostile_node_percentage = 0.20 # malicious participant ratio 28 | 29 | iteration_num = 200 ## number of communication rounds 30 | 31 | learning_rate = 0.01 32 | numEpoch = 10 33 | batch_size = 32 34 | momentum = 0.9 35 | 36 | seed = 1 37 | use_seed = 23 38 | hostility_seed = 77 39 | converters_seed = 51 40 | 41 | train_amount = 4000 42 | valid_amount = 900 43 | test_amount = 890 44 | print_amount = 3 45 | 46 | x_train, y_train, x_valid, y_valid, x_test, y_test = dd.load_mnist_data() 47 | x_test, y_test = dd.get_equal_size_test_data_from_each_label(x_test, y_test, min_amount=test_amount) 48 | 49 | x_train, y_train, x_valid, y_valid, x_test, y_test = map(torch.tensor, 50 | (x_train, y_train, x_valid, y_valid, x_test, y_test)) 51 | 52 | ##train 53 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 54 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 55 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 56 | 57 | x_train_dict, y_train_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_train, 58 | amount=train_amount, 59 | number_of_samples=number_of_samples, 60 | n=n, x_data=x_train, 61 | y_data=y_train, 62 | node_label_info=node_label_info_train, 63 | amount_info_table=amount_info_table_train, 64 | x_name="x_train", 65 | y_name="y_train", 66 | is_cnn=is_cnn) 67 | 68 | 69 | nodes_list = dd.choose_nodes_randomly_to_convert_hostile(hostile_node_percentage, number_of_samples, hostility_seed) 70 | print("hostile_nodes:", nodes_list) 71 | 72 | 73 | if is_organized: 74 | y_train_dict = dd.convert_nodes_to_hostile(y_train_dict, nodes_list, 75 | converter_dict={0: 9, 1: 7, 2: 5, 3: 8, 4: 6, 5: 2, 6: 4, 7: 1, 8: 3, 76 | 9: 0}) 77 | else: 78 | y_train_dict = dd.convert_nodes_to_hostile_with_different_converters(y_train_dict, nodes_list, 79 | converters_seed=converters_seed) 80 | 81 | 82 | ## test 83 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 84 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 85 | number_of_samples=number_of_samples, 86 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 87 | x_test_dict, y_test_dict = dd.distribute_mnist_data_to_participants(label_dict=label_dict_test, 88 | amount=test_amount, 89 | number_of_samples=number_of_samples, 90 | n=n, x_data=x_test, 91 | y_data=y_test, 92 | node_label_info=node_label_info_test, 93 | amount_info_table=amount_info_table_test, 94 | x_name="x_test", 95 | y_name="y_test", is_cnn=is_cnn) 96 | 97 | if is_cnn: 98 | reshape_size = int(np.sqrt(x_train.shape[1])) 99 | x_train = x_train.view(-1, 1, reshape_size, reshape_size) 100 | x_valid = x_valid.view(-1, 1, reshape_size, reshape_size) 101 | x_test = x_test.view(-1, 1, reshape_size, reshape_size) 102 | 103 | train_ds = TensorDataset(x_train, y_train) 104 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 105 | 106 | test_ds = TensorDataset(x_test, y_test) 107 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 108 | 109 | if is_cnn: 110 | main_model = cm.Netcnn() 111 | else: 112 | main_model = cm.Net2nn() 113 | 114 | cm.weights_init(main_model) 115 | main_model = main_model.to(device) 116 | 117 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=0.9) 118 | main_criterion = nn.CrossEntropyLoss() 119 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_mnist(number_of_samples, learning_rate, 120 | momentum, device, is_cnn) 121 | 122 | 123 | test_accuracies_of_each_iteration = np.array([], dtype=float) 124 | its = np.array([], dtype=int) 125 | distances = pd.DataFrame() 126 | thresholds = pd.DataFrame() 127 | 128 | 129 | for iteration in range(iteration_num): 130 | its = np.concatenate((its, np.ones(number_of_samples, dtype=int) * (iteration + 1))) 131 | 132 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 133 | number_of_samples) 134 | 135 | tn.start_train_end_node_process_without_print(number_of_samples, x_train_dict, y_train_dict, x_test_dict, y_test_dict, 136 | batch_size, model_dict, criterion_dict, optimizer_dict, numEpoch, device) 137 | 138 | iteration_distance = tn.calculate_euclidean_distances(main_model, model_dict) 139 | iteration_distance, iteration_threshold = tn.get_outlier_situation_and_thresholds_for_layers( 140 | iteration_distance) 141 | 142 | thresholds = pd.concat([thresholds, iteration_threshold]) 143 | distances = pd.concat([distances, iteration_distance]) 144 | 145 | 146 | main_model = tn.strict_condition_without_outliers_set_averaged_weights_as_main_model_weights_and_update_main_model(main_model, 147 | model_dict, iteration_distance, device) 148 | 149 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 150 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 151 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 152 | 153 | 154 | distances["iteration"] = its 155 | thresholds["iteration"] = np.arange(1, iteration_num + 1) 156 | -------------------------------------------------------------------------------- /CIFAR/cifar_lf_barfed.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.utils.data import TensorDataset 4 | from torch.utils.data import DataLoader 5 | import pandas as pd 6 | import numpy as np 7 | from torch.optim import lr_scheduler 8 | from fl_utils import distribute_data as dd 9 | from fl_utils import train_nodes as tn 10 | from fl_utils import construct_models as cm 11 | 12 | enable_wandb = False 13 | 14 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 15 | print("device: ", device) 16 | 17 | number_of_samples = 100 #number of participants 18 | 19 | is_noniid = True 20 | if is_noniid: 21 | n = 5 22 | min_n_each_node = 5 23 | else: 24 | n = 10 25 | min_n_each_node = 10 26 | 27 | is_organized = True 28 | hostile_node_percentage = 0.20 #malicious participant ratio 29 | 30 | iteration_num = 500 #number of communication rounds 31 | learning_rate = 0.0015 32 | min_lr = 0.000010 33 | lr_scheduler_factor =0.2 34 | best_threshold = 0.0001 35 | clipping=True 36 | clipping_threshold =10 37 | 38 | weight_decay = 0.0001 39 | numEpoch = 10 40 | batch_size = 100 41 | momentum = 0.9 42 | 43 | seed = 11 44 | use_seed = 8 45 | hostility_seed = 90 46 | converters_seed = 51 47 | 48 | train_amount = 5000 49 | test_amount = 1000 50 | 51 | 52 | 53 | 54 | x_train, y_train, x_test, y_test = dd.load_cifar_data() 55 | 56 | ##train 57 | label_dict_train = dd.split_and_shuffle_labels(y_data=y_train, seed=seed, amount=train_amount) 58 | node_label_info_train, total_label_occurences_train, amount_info_table_train = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 59 | number_of_samples=number_of_samples, n=n, amount=train_amount, seed=use_seed, min_n_each_node=min_n_each_node) 60 | 61 | x_train_dict, y_train_dict = dd.distribute_cifar_data_to_participants(label_dict=label_dict_train, 62 | amount=train_amount, 63 | number_of_samples=number_of_samples, 64 | n=n, x_data=x_train, 65 | y_data=y_train, 66 | node_label_info=node_label_info_train, 67 | amount_info_table=amount_info_table_train, 68 | x_name="x_train", 69 | y_name="y_train") 70 | 71 | nodes_list = dd.choose_nodes_randomly_to_convert_hostile(hostile_node_percentage, number_of_samples, hostility_seed) 72 | print("hostile_nodes:", nodes_list) 73 | 74 | if is_organized: 75 | y_train_dict = dd.convert_nodes_to_hostile(y_train_dict, nodes_list, 76 | converter_dict={0: 2, 77 | 1: 9, 78 | 2: 0, 79 | 3: 5, 80 | 4: 7, 81 | 5: 3, 82 | 6: 8, 83 | 7: 4, 84 | 8: 6, 85 | 9: 1}) 86 | else: 87 | y_train_dict = dd.convert_nodes_to_hostile_with_different_converters(y_train_dict, nodes_list, 88 | converters_seed=converters_seed) 89 | 90 | ## test 91 | label_dict_test = dd.split_and_shuffle_labels(y_data=y_test, seed=seed, amount=test_amount) 92 | node_label_info_test, total_label_occurences_test, amount_info_table_test = dd.get_info_for_distribute_non_iid_with_different_n_and_amount( 93 | number_of_samples=number_of_samples, 94 | n=n, amount=test_amount, seed=use_seed, min_n_each_node=min_n_each_node) 95 | x_test_dict, y_test_dict = dd.distribute_cifar_data_to_participants(label_dict=label_dict_test, 96 | amount=test_amount, 97 | number_of_samples=number_of_samples, 98 | n=n, x_data=x_test, 99 | y_data=y_test, 100 | node_label_info=node_label_info_test, 101 | amount_info_table=amount_info_table_test, 102 | x_name="x_test", 103 | y_name="y_test") 104 | 105 | train_ds = TensorDataset(x_train, y_train) 106 | train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 107 | 108 | test_ds = TensorDataset(x_test, y_test) 109 | test_dl = DataLoader(test_ds, batch_size=batch_size * 2) 110 | 111 | main_model = cm.Cifar10CNN() 112 | cm.weights_init(main_model) 113 | main_model = main_model.to(device) 114 | 115 | main_optimizer = torch.optim.SGD(main_model.parameters(), lr=learning_rate, momentum=momentum, weight_decay=weight_decay) 116 | main_criterion = nn.CrossEntropyLoss() 117 | scheduler = lr_scheduler.ReduceLROnPlateau(main_optimizer, mode="max", factor=lr_scheduler_factor, 118 | patience=10, threshold=best_threshold, verbose=True, min_lr=min_lr) 119 | 120 | model_dict, optimizer_dict, criterion_dict = tn.create_model_optimizer_criterion_dict_for_cifar_cnn(number_of_samples, learning_rate, 121 | momentum, device, weight_decay) 122 | 123 | 124 | test_accuracies_of_each_iteration = np.array([], dtype=float) 125 | its = np.array([], dtype=int) 126 | distances = pd.DataFrame() 127 | thresholds = pd.DataFrame() 128 | 129 | for iteration in range(iteration_num): 130 | its = np.concatenate((its, np.ones(number_of_samples, dtype=int) * (iteration + 1))) 131 | 132 | model_dict = tn.send_main_model_to_nodes_and_update_model_dict(main_model, model_dict, 133 | number_of_samples) 134 | 135 | tn.start_train_end_node_process_cifar(number_of_samples, x_train_dict, y_train_dict, x_test_dict, 136 | y_test_dict, batch_size, model_dict, criterion_dict, 137 | optimizer_dict, numEpoch, device, clipping, clipping_threshold) 138 | 139 | iteration_distance = tn.calculate_euclidean_distances(main_model, model_dict) 140 | iteration_distance, iteration_threshold = tn.get_outlier_situation_and_thresholds_for_layers( 141 | iteration_distance) 142 | 143 | thresholds = pd.concat([thresholds, iteration_threshold]) 144 | distances = pd.concat([distances, iteration_distance]) 145 | 146 | main_model = tn.strict_condition_without_outliers_set_averaged_weights_as_main_model_weights_and_update_main_model( 147 | main_model, model_dict, iteration_distance, device) 148 | test_loss, test_accuracy = tn.validation(main_model, test_dl, main_criterion, device) 149 | scheduler.step(test_accuracy) 150 | new_lr = main_optimizer.param_groups[0]["lr"] 151 | optimizer_dict = cm.update_learning_rate_decay(optimizer_dict, new_lr) 152 | 153 | test_accuracies_of_each_iteration = np.append(test_accuracies_of_each_iteration, test_accuracy) 154 | print("Iteration", str(iteration + 1), ": main_model accuracy on all test data: {:7.4f}".format(test_accuracy)) 155 | 156 | 157 | distances["iteration"] = its 158 | thresholds["iteration"] = np.arange(1, iteration_num + 1) 159 | --------------------------------------------------------------------------------