├── .idea ├── FedAvg.iml ├── dictionaries │ └── Administrator.xml ├── inspectionProfiles │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── vcs.xml └── workspace.xml ├── LICENSE ├── README.md ├── __pycache__ ├── args.cpython-37.pyc └── models.cpython-37.pyc ├── algorithms ├── __pycache__ │ └── bp_nn.cpython-37.pyc ├── bp_nn.py ├── fedavg-numpy.py ├── fedavg-pytorch.py └── fedavg-tff.py ├── args.py ├── data └── Wind │ ├── Instructions.txt │ ├── Solution to Task 15 │ └── solution15_W.csv │ ├── Task 1 │ ├── Task1_W_Zone1_10.zip │ ├── Task1_W_Zone1_10 │ │ ├── Task1_W_Zone1.csv │ │ ├── Task1_W_Zone10.csv │ │ ├── Task1_W_Zone2.csv │ │ ├── Task1_W_Zone3.csv │ │ ├── Task1_W_Zone4.csv │ │ ├── Task1_W_Zone5.csv │ │ ├── Task1_W_Zone6.csv │ │ ├── Task1_W_Zone7.csv │ │ ├── Task1_W_Zone8.csv │ │ └── Task1_W_Zone9.csv │ ├── TaskExpVars1_W_Zone1_10.zip │ └── benchmark1_W.csv │ ├── Task 10 │ ├── Task10_W_Zone1_10.zip │ ├── TaskExpVars10_W_Zone1_10.zip │ └── benchmark10_W.csv │ ├── Task 11 │ ├── Task11_W_Zone1_10.zip │ ├── TaskExpVars11_W_Zone1_10.zip │ └── benchmark11_W.csv │ ├── Task 12 │ ├── Task12_W_Zone1_10.zip │ ├── TaskExpVars12_W_Zone1_10.zip │ └── benchmark12_W.csv │ ├── Task 13 │ ├── Task13_W_Zone1_10.zip │ ├── TaskExpVars13_W_Zone1_10.zip │ └── benchmark13_W.csv │ ├── Task 14 │ ├── Task14_W_Zone1_10.zip │ ├── TaskExpVars14_W_Zone1_10.zip │ └── benchmark14_W.csv │ ├── Task 15 │ ├── Task15_W_Zone1_10.zip │ ├── TaskExpVars15_W_Zone1_10.zip │ └── benchmark15_W.csv │ ├── Task 2 │ ├── Task2_W_Zone1_10.zip │ ├── TaskExpVars2_W_Zone1_10.zip │ └── benchmark2_W.csv │ ├── Task 3 │ ├── Task3_W_Zone1_10.zip │ ├── TaskExpVars3_W_Zone1_10.zip │ └── benchmark3_W.csv │ ├── Task 4 │ ├── Task4_W_Zone1_10.zip │ ├── TaskExpVars4_W_Zone1_10.zip │ └── benchmark4_W.csv │ ├── Task 5 │ ├── Task5_W_Zone1_10.zip │ ├── TaskExpVars5_W_Zone1_10.zip │ └── benchmark5_W.csv │ ├── Task 6 │ ├── Task6_W_Zone1_10.zip │ ├── TaskExpVars6_W_Zone1_10.zip │ └── benchmark6_W.csv │ ├── Task 7 │ ├── Task7_W_Zone1_10.zip │ ├── TaskExpVars7_W_Zone1_10.zip │ └── benchmark7_W.csv │ ├── Task 8 │ ├── Task8_W_Zone1_10.zip │ ├── TaskExpVars8_W_Zone1_10.zip │ └── benchmark8_W.csv │ └── Task 9 │ ├── Task9_W_Zone1_10.zip │ ├── TaskExpVars9_W_Zone1_10.zip │ └── benchmark9_W.csv └── models.py /.idea/FedAvg.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | -------------------------------------------------------------------------------- /.idea/dictionaries/Administrator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | fedavg 5 | pytorch 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 14 | 15 | 20 | 21 | 22 | 24 | 25 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 64 | 65 | 66 | 86 | 87 | 88 | 108 | 109 | 110 | 130 | 131 | 132 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 1646110310871 170 | 190 | 191 | 192 | 193 | 195 | 196 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 KI 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](https://img.shields.io/badge/FedAvg-numpy%2Bpytorch%2Btff-orange) 2 | # FedAvg-numpy-pytorch-tff 3 | Three implementations of FedAvg: numpy, pytorch and tensorflow federated. 4 | 5 | # Environment 6 | numpy==1.18.5 7 | 8 | pytorch==1.10.1+cu111 9 | 10 | tensorflow==2.3.4 11 | 12 | tensorflow-federated==0.17.0 13 | -------------------------------------------------------------------------------- /__pycache__/args.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/__pycache__/args.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/models.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/__pycache__/models.cpython-37.pyc -------------------------------------------------------------------------------- /algorithms/__pycache__/bp_nn.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/algorithms/__pycache__/bp_nn.cpython-37.pyc -------------------------------------------------------------------------------- /algorithms/bp_nn.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @Time : 2022/2/27 11:40 4 | @Author :KI 5 | @File :bp_nn.py 6 | @Motto:Hungry And Humble 7 | 8 | """ 9 | import copy 10 | import sys 11 | 12 | import numpy as np 13 | import pandas as pd 14 | from torch import nn 15 | from tqdm import tqdm 16 | 17 | sys.path.append('../') 18 | from sklearn.metrics import mean_absolute_error, mean_squared_error 19 | from itertools import chain 20 | from models import BP 21 | import os 22 | os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE" 23 | 24 | clients_wind = ['Task1_W_Zone' + str(i) for i in range(1, 11)] 25 | from args import args_parser 26 | 27 | 28 | def load_data(file_name): 29 | df = pd.read_csv(os.path.dirname(os.getcwd()) + '/data/Wind/Task 1/Task1_W_Zone1_10/' + file_name + '.csv', encoding='gbk') 30 | columns = df.columns 31 | df.fillna(df.mean(), inplace=True) 32 | for i in range(3, 7): 33 | MAX = np.max(df[columns[i]]) 34 | MIN = np.min(df[columns[i]]) 35 | df[columns[i]] = (df[columns[i]] - MIN) / (MAX - MIN) 36 | 37 | return df 38 | 39 | 40 | def nn_seq_wind(file_name, B): 41 | print('data processing...') 42 | dataset = load_data(file_name) 43 | # split 44 | train = dataset[:int(len(dataset) * 0.6)] 45 | val = dataset[int(len(dataset) * 0.6):int(len(dataset) * 0.8)] 46 | test = dataset[int(len(dataset) * 0.8):len(dataset)] 47 | 48 | def process(data): 49 | columns = data.columns 50 | wind = data[columns[2]] 51 | wind = wind.tolist() 52 | data = data.values.tolist() 53 | X, Y = [], [] 54 | for i in range(len(data) - 30): 55 | train_seq = [] 56 | train_label = [] 57 | for j in range(i, i + 24): 58 | train_seq.append(wind[j]) 59 | 60 | for c in range(3, 7): 61 | train_seq.append(data[i + 24][c]) 62 | train_label.append(wind[i + 24]) 63 | X.append(train_seq) 64 | Y.append(train_label) 65 | 66 | X, Y = np.array(X), np.array(Y) 67 | 68 | length = int(len(X) / B) * B 69 | X, Y = X[:length], Y[:length] 70 | 71 | return X, Y 72 | 73 | train_x, train_y = process(train) 74 | val_x, val_y = process(val) 75 | test_x, test_y = process(test) 76 | 77 | return [train_x, train_y], [val_x, val_y], [test_x, test_y] 78 | 79 | 80 | def get_val_loss(args, model, val_x, val_y): 81 | batch_size = args.B 82 | batch = int(len(val_x) / batch_size) 83 | val_loss = [] 84 | for i in range(batch): 85 | start = i * batch_size 86 | end = start + batch_size 87 | model.forward_prop(val_x[start:end], val_y[start:end]) 88 | model.backward_prop(val_y[start:end]) 89 | val_loss.append(np.mean(model.loss)) 90 | 91 | return np.mean(val_loss) 92 | 93 | 94 | def train(args, nn): 95 | print('training...') 96 | tr, val, te = nn_seq_wind(nn.file_name, args.B) 97 | train_x, train_y = tr[0], tr[1] 98 | val_x, val_y = val[0], val[1] 99 | nn.len = len(train_x) 100 | batch_size = args.B 101 | epochs = args.E 102 | batch = int(len(train_x) / batch_size) 103 | # training 104 | min_epochs = 10 105 | best_model = None 106 | min_val_loss = 5 107 | for epoch in tqdm(range(epochs)): 108 | train_loss = [] 109 | for i in range(batch): 110 | start = i * batch_size 111 | end = start + batch_size 112 | nn.forward_prop(train_x[start:end], train_y[start:end]) 113 | nn.backward_prop(train_y[start:end]) 114 | train_loss.append(np.mean(nn.loss)) 115 | # validation 116 | val_loss = get_val_loss(args, nn, val_x, val_y) 117 | if epoch + 1 >= min_epochs and val_loss < min_val_loss: 118 | min_val_loss = val_loss 119 | best_model = copy.deepcopy(nn) 120 | 121 | print('epoch {:03d} train_loss {:.8f} val_loss {:.8f}'.format(epoch, np.mean(train_loss), val_loss)) 122 | 123 | return best_model 124 | 125 | 126 | def get_mape(x, y): 127 | """ 128 | :param x: true value 129 | :param y: pred value 130 | :return: mape 131 | """ 132 | return np.mean(np.abs((x - y) / x)) 133 | 134 | 135 | def test(args, nn): 136 | tr, val, te = nn_seq_wind(nn.file_name, args.B) 137 | test_x, test_y = te[0], te[1] 138 | pred = [] 139 | batch = int(len(test_y) / args.B) 140 | for i in range(batch): 141 | start = i * args.B 142 | end = start + args.B 143 | res = nn.forward_prop(test_x[start:end], test_y[start:end]) 144 | res = res.tolist() 145 | res = list(chain.from_iterable(res)) 146 | # print('res=', res) 147 | pred.extend(res) 148 | pred = np.array(pred) 149 | print('mae:', mean_absolute_error(test_y.flatten(), pred), 'rmse:', 150 | np.sqrt(mean_squared_error(test_y.flatten(), pred))) 151 | 152 | 153 | def main(): 154 | args = args_parser() 155 | for client in clients_wind: 156 | nn = BP(args, client) 157 | nn = train(args, nn) 158 | test(args, nn) 159 | 160 | 161 | if __name__ == '__main__': 162 | main() 163 | -------------------------------------------------------------------------------- /algorithms/fedavg-numpy.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @Time : 2022/1/12 13:26 4 | @Author :KI 5 | @File :fedavg-numpy.py 6 | @Motto:Hungry And Humble 7 | 8 | """ 9 | import numpy as np 10 | import random 11 | import copy 12 | import sys 13 | 14 | sys.path.append('../') 15 | from algorithms.bp_nn import train, test 16 | from models import BP 17 | from args import args_parser 18 | 19 | clients_wind = ['Task1_W_Zone' + str(i) for i in range(1, 11)] 20 | 21 | 22 | # Implementation for FedAvg by numpy. 23 | class FedAvg: 24 | def __init__(self, args): 25 | self.args = args 26 | self.clients = args.clients 27 | self.nn = BP(args=args, file_name='server') 28 | self.nns = [] 29 | # distribution 30 | for i in range(self.args.K): 31 | s = copy.deepcopy(self.nn) 32 | s.file_name = self.clients[i] 33 | self.nns.append(s) 34 | 35 | def server(self): 36 | for t in range(self.args.r): 37 | print('round', t + 1, ':') 38 | m = np.max([int(self.args.C * self.args.K), 1]) 39 | # sampling 40 | index = random.sample(range(0, self.args.K), m) 41 | # dispatch 42 | self.dispatch(index) 43 | # local updating 44 | self.client_update(index) 45 | # aggregation 46 | self.aggregation(index) 47 | 48 | # return global model 49 | return self.nn 50 | 51 | def aggregation(self, index): 52 | # update w 53 | s = 0 54 | for j in index: 55 | # normal 56 | s += self.nns[j].len 57 | w1 = np.zeros_like(self.nn.w1) 58 | w2 = np.zeros_like(self.nn.w2) 59 | w3 = np.zeros_like(self.nn.w3) 60 | w4 = np.zeros_like(self.nn.w4) 61 | for j in index: 62 | # normal 63 | w1 += self.nns[j].w1 * (self.nns[j].len / s) 64 | w2 += self.nns[j].w2 * (self.nns[j].len / s) 65 | w3 += self.nns[j].w3 * (self.nns[j].len / s) 66 | w4 += self.nns[j].w4 * (self.nns[j].len / s) 67 | # update server 68 | self.nn.w1, self.nn.w2, self.nn.w3, self.nn.w4 = w1, w2, w3, w4 69 | 70 | def dispatch(self, index): 71 | # distribute 72 | for i in index: 73 | self.nns[i].w1, self.nns[i].w2, self.nns[i].w3, self.nns[ 74 | i].w4 = self.nn.w1, self.nn.w2, self.nn.w3, self.nn.w4 75 | 76 | def client_update(self, index): # update nn 77 | for k in index: 78 | self.nns[k] = train(self.args, self.nns[k]) 79 | 80 | def global_test(self): 81 | model = self.nn 82 | c = clients_wind 83 | for client in c: 84 | model.file_name = client 85 | test(self.args, model) 86 | 87 | 88 | def main(): 89 | args = args_parser() 90 | fed = FedAvg(args) 91 | fed.server() 92 | fed.global_test() 93 | 94 | 95 | if __name__ == '__main__': 96 | main() 97 | -------------------------------------------------------------------------------- /algorithms/fedavg-pytorch.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | """ 3 | @Time: 2022/02/14 12:11 4 | @Author: KI 5 | @File: fedavg-pytorch.py 6 | @Motto: Hungry And Humble 7 | """ 8 | import copy 9 | import random 10 | import sys 11 | from itertools import chain 12 | 13 | from tqdm import tqdm 14 | 15 | from args import args_parser 16 | import numpy as np 17 | import torch 18 | from torch.optim.lr_scheduler import StepLR 19 | 20 | sys.path.append('../') 21 | from sklearn.metrics import mean_absolute_error, mean_squared_error 22 | from models import ANN 23 | from torch import nn 24 | from torch.utils.data import Dataset, DataLoader 25 | from algorithms.bp_nn import load_data 26 | 27 | clients_wind = ['Task1_W_Zone' + str(i) for i in range(1, 11)] 28 | 29 | 30 | class MyDataset(Dataset): 31 | def __init__(self, data): 32 | self.data = data 33 | 34 | def __getitem__(self, item): 35 | return self.data[item] 36 | 37 | def __len__(self): 38 | return len(self.data) 39 | 40 | 41 | def nn_seq_wind(file_name, B): 42 | print('data processing...') 43 | dataset = load_data(file_name) 44 | # split 45 | train = dataset[:int(len(dataset) * 0.6)] 46 | val = dataset[int(len(dataset) * 0.6):int(len(dataset) * 0.8)] 47 | test = dataset[int(len(dataset) * 0.8):len(dataset)] 48 | 49 | def process(data): 50 | columns = data.columns 51 | wind = data[columns[2]] 52 | wind = wind.tolist() 53 | data = data.values.tolist() 54 | seq = [] 55 | for i in range(len(data) - 30): 56 | train_seq = [] 57 | train_label = [] 58 | for j in range(i, i + 24): 59 | train_seq.append(wind[j]) 60 | for c in range(3, 7): 61 | train_seq.append(data[i + 24][c]) 62 | train_label.append(wind[i + 24]) 63 | train_seq = torch.FloatTensor(train_seq).view(-1) 64 | train_label = torch.FloatTensor(train_label).view(-1) 65 | seq.append((train_seq, train_label)) 66 | 67 | seq = MyDataset(seq) 68 | 69 | seq = DataLoader(dataset=seq, batch_size=B, shuffle=False, num_workers=0) 70 | 71 | return seq 72 | 73 | Dtr = process(train) 74 | Val = process(val) 75 | Dte = process(test) 76 | 77 | return Dtr, Val, Dte 78 | 79 | 80 | class FedAvg: 81 | def __init__(self, args): 82 | self.args = args 83 | self.clients = args.clients 84 | self.nn = ANN(args, name='server').to(args.device) 85 | self.nns = [] 86 | for i in range(args.K): 87 | temp = copy.deepcopy(self.nn) 88 | temp.name = self.clients[i] 89 | self.nns.append(temp) 90 | 91 | def server(self): 92 | for t in tqdm(range(self.args.r)): 93 | print('round', t + 1, ':') 94 | # sampling 95 | m = np.max([int(self.args.C * self.args.K), 1]) 96 | index = random.sample(range(0, self.args.K), m) # st 97 | # dispatch 98 | self.dispatch(index) 99 | # local updating 100 | self.client_update(index) 101 | # aggregation 102 | self.aggregation(index) 103 | 104 | return self.nn 105 | 106 | def aggregation(self, index): 107 | s = 0 108 | for j in index: 109 | # normal 110 | s += self.nns[j].len 111 | 112 | params = {} 113 | for k, v in self.nns[0].named_parameters(): 114 | params[k] = torch.zeros_like(v.data) 115 | 116 | for j in index: 117 | for k, v in self.nns[j].named_parameters(): 118 | params[k] += v.data * (self.nns[j].len / s) 119 | 120 | for k, v in self.nn.named_parameters(): 121 | v.data = params[k].data.clone() 122 | 123 | def dispatch(self, index): 124 | for j in index: 125 | for old_params, new_params in zip(self.nns[j].parameters(), self.nn.parameters()): 126 | old_params.data = new_params.data.clone() 127 | 128 | def client_update(self, index): # update nn 129 | for k in index: 130 | self.nns[k] = train(self.args, self.nns[k]) 131 | 132 | def global_test(self): 133 | model = self.nn 134 | model.eval() 135 | c = clients_wind 136 | for client in c: 137 | model.name = client 138 | test(self.args, model) 139 | 140 | 141 | def get_val_loss(args, model, Val): 142 | model.eval() 143 | loss_function = nn.MSELoss().to(args.device) 144 | val_loss = [] 145 | for (seq, label) in Val: 146 | with torch.no_grad(): 147 | seq = seq.to(args.device) 148 | label = label.to(args.device) 149 | y_pred = model(seq) 150 | loss = loss_function(y_pred, label) 151 | val_loss.append(loss.item()) 152 | 153 | return np.mean(val_loss) 154 | 155 | 156 | def train(args, model): 157 | model.train() 158 | Dtr, Val, Dte = nn_seq_wind(model.name, args.B) 159 | model.len = len(Dtr) 160 | device = args.device 161 | loss_function = nn.MSELoss().to(device) 162 | lr = args.lr 163 | if args.optimizer == 'adam': 164 | optimizer = torch.optim.Adam(model.parameters(), lr=lr, 165 | weight_decay=args.weight_decay) 166 | else: 167 | optimizer = torch.optim.SGD(model.parameters(), lr=lr, 168 | momentum=0.9, weight_decay=args.weight_decay) 169 | lr_step = StepLR(optimizer, step_size=args.step_size, gamma=args.gamma) 170 | # training 171 | min_epochs = 10 172 | best_model = None 173 | min_val_loss = 5 174 | for epoch in tqdm(range(args.E)): 175 | train_loss = [] 176 | for (seq, label) in Dtr: 177 | seq = seq.to(device) 178 | label = label.to(device) 179 | y_pred = model(seq) 180 | loss = loss_function(y_pred, label) 181 | train_loss.append(loss.item()) 182 | optimizer.zero_grad() 183 | loss.backward() 184 | optimizer.step() 185 | lr_step.step() 186 | # validation 187 | val_loss = get_val_loss(args, model, Val) 188 | if epoch + 1 >= min_epochs and val_loss < min_val_loss: 189 | min_val_loss = val_loss 190 | best_model = copy.deepcopy(model) 191 | 192 | print('epoch {:03d} train_loss {:.8f} val_loss {:.8f}'.format(epoch, np.mean(train_loss), val_loss)) 193 | model.train() 194 | 195 | return best_model 196 | 197 | 198 | def test(args, model): 199 | model.eval() 200 | Dtr, Val, Dte = nn_seq_wind(model.name, args.B) 201 | pred = [] 202 | y = [] 203 | device = args.device 204 | for (seq, target) in Dte: 205 | with torch.no_grad(): 206 | seq = seq.to(device) 207 | y_pred = model(seq) 208 | pred.extend(list(chain.from_iterable(y_pred.data.tolist()))) 209 | y.extend(list(chain.from_iterable(target.data.tolist()))) 210 | # 211 | pred = np.array(pred) 212 | y = np.array(y) 213 | print('mae:', mean_absolute_error(y, pred), 'rmse:', 214 | np.sqrt(mean_squared_error(y, pred))) 215 | 216 | 217 | def main(): 218 | args = args_parser() 219 | fed = FedAvg(args) 220 | fed.server() 221 | fed.global_test() 222 | 223 | 224 | if __name__ == '__main__': 225 | main() 226 | 227 | -------------------------------------------------------------------------------- /algorithms/fedavg-tff.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | """ 3 | @Time: 2022/02/11 12:12 4 | @Author: KI 5 | @File: fedavg-tff.py 6 | @Motto: Hungry And Humble 7 | """ 8 | import os 9 | os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' 10 | import sys 11 | sys.path.append('../') 12 | from algorithms.bp_nn import load_data 13 | import tensorflow as tf 14 | import tensorflow_federated as tff 15 | import nest_asyncio 16 | from args import args_parser 17 | args = args_parser() 18 | 19 | nest_asyncio.apply() 20 | tf.compat.v1.enable_v2_behavior() 21 | 22 | clients_wind = ['Task1_W_Zone' + str(i) for i in range(1, 11)] 23 | 24 | 25 | # Data processing 26 | def client_data_wind(n, B, train_flag): 27 | print('data processing...') 28 | c = clients_wind 29 | data = load_data(c[n]) 30 | if train_flag: 31 | data = data[0:int(len(data) * 0.9)] 32 | else: 33 | data = data[int(len(data) * 0.9):len(data)] 34 | 35 | label = data[data.columns[2]].values.tolist() 36 | data = data.values.tolist() 37 | X, Y = [], [] 38 | for i in range(len(data) - 30): 39 | train_seq = [] 40 | # train_label = [] 41 | for j in range(i, i + 24): 42 | train_seq.append(label[j]) 43 | for c in range(3, 7): 44 | train_seq.append(data[i + 24][c]) 45 | Y.append(label[i + 24]) 46 | X.append(train_seq) 47 | 48 | X = tf.reshape(X, [len(X), -1]) 49 | Y = tf.reshape(Y, [len(Y), -1]) 50 | X = tf.data.Dataset.from_tensor_slices(X) 51 | Y = tf.data.Dataset.from_tensor_slices(Y) 52 | 53 | seq = tf.data.Dataset.zip((X, Y)) 54 | seq = seq.batch(B, drop_remainder=True).shuffle(100).prefetch(B) 55 | # print(list(seq.as_numpy_iterator())[0]) 56 | 57 | return seq 58 | 59 | 60 | # Wrap a Keras model for use with TFF. 61 | def model_fn(): 62 | metrics = [tf.keras.metrics.MeanAbsoluteError()] 63 | input_dim = args.input_dim 64 | model = tf.keras.models.Sequential([ 65 | tf.keras.layers.Dense(20, tf.nn.sigmoid, input_shape=(input_dim,), 66 | kernel_initializer='zeros'), 67 | tf.keras.layers.Dense(20, tf.nn.sigmoid), 68 | tf.keras.layers.Dense(20, tf.nn.sigmoid), 69 | tf.keras.layers.Dense(1, tf.sigmoid) 70 | ]) 71 | return tff.learning.from_keras_model( 72 | model, 73 | input_spec=train_data[0].element_spec, 74 | loss=tf.keras.losses.MeanSquaredError(), 75 | metrics=metrics) 76 | 77 | 78 | def FedAvg(): 79 | # Simulate a few rounds of training with the selected client devices. 80 | trainer = tff.learning.build_federated_averaging_process( 81 | model_fn, 82 | client_optimizer_fn=lambda: tf.keras.optimizers.Adam(0.08), 83 | # server_optimizer_fn=lambda: tf.keras.optimizers.SGD(1.0), 84 | # use_experimental_simulation_loop=True 85 | ) 86 | state = trainer.initialize() 87 | for r in range(args.r): 88 | state, metrics = trainer.next(state, train_data) 89 | print('round', r + 1, 'loss:', metrics['train']['loss']) 90 | evaluation = tff.learning.build_federated_evaluation(model_fn) 91 | for i in range(args.K): 92 | test_data = [client_data_wind(n, 20, train_flag=False) for n in range(i, i + 1)] 93 | # print('test:') 94 | test_metrics = evaluation(state.model, test_data) 95 | m = 'mean_absolute_error' 96 | print(str(test_metrics[m] / len(test_data[0]))) 97 | 98 | print(state.model) 99 | 100 | 101 | if __name__ == '__main__': 102 | train_data = [client_data_wind(n, 20, train_flag=True) for n in range(args.K)] 103 | FedAvg() 104 | -------------------------------------------------------------------------------- /args.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | """ 3 | @Time: 2022/03/01 11:52 4 | @Author: KI 5 | @File: args.py 6 | @Motto: Hungry And Humble 7 | """ 8 | import argparse 9 | import torch 10 | 11 | 12 | def args_parser(): 13 | parser = argparse.ArgumentParser() 14 | 15 | parser.add_argument('--E', type=int, default=20, help='number of rounds of training') 16 | parser.add_argument('--r', type=int, default=5, help='number of communication rounds') 17 | parser.add_argument('--K', type=int, default=10, help='number of total clients') 18 | parser.add_argument('--input_dim', type=int, default=28, help='input dimension') 19 | parser.add_argument('--lr', type=float, default=0.08, help='learning rate') 20 | parser.add_argument('--C', type=float, default=0.5, help='sampling rate') 21 | parser.add_argument('--B', type=int, default=50, help='local batch size') 22 | parser.add_argument('--optimizer', type=str, default='adam', help='type of optimizer') 23 | parser.add_argument('--device', default=torch.device("cuda" if torch.cuda.is_available() else "cpu")) 24 | parser.add_argument('--weight_decay', type=float, default=1e-4, help='weight_decay') 25 | parser.add_argument('--step_size', type=int, default=10, help='step size') 26 | parser.add_argument('--gamma', type=float, default=0.1, help='gamma') 27 | clients = ['Task1_W_Zone' + str(i) for i in range(1, 11)] 28 | parser.add_argument('--clients', default=clients) 29 | 30 | args = parser.parse_args() 31 | 32 | return args 33 | 34 | -------------------------------------------------------------------------------- /data/Wind/Instructions.txt: -------------------------------------------------------------------------------- 1 | Data 2 | 3 | The target variable is power generation, normalized here by the respective nominal capacities of each wind farm. The explanatory variables that can be used are the past power measurements (if relevant), and input weather forecasts, given as u and v components (zonal and meridional) which can be transformed to wind speed and direction by the contestants, or used readily. These forecasts are given at two heights, 10m and 100m above ground level, in order to give a rough idea of wind profiles. -------------------------------------------------------------------------------- /data/Wind/Task 1/Task1_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 1/Task1_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 1/TaskExpVars1_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 1/TaskExpVars1_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 10/Task10_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 10/Task10_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 10/TaskExpVars10_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 10/TaskExpVars10_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 11/Task11_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 11/Task11_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 11/TaskExpVars11_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 11/TaskExpVars11_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 12/Task12_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 12/Task12_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 12/TaskExpVars12_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 12/TaskExpVars12_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 13/Task13_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 13/Task13_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 13/TaskExpVars13_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 13/TaskExpVars13_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 14/Task14_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 14/Task14_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 14/TaskExpVars14_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 14/TaskExpVars14_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 15/Task15_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 15/Task15_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 15/TaskExpVars15_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 15/TaskExpVars15_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 2/Task2_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 2/Task2_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 2/TaskExpVars2_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 2/TaskExpVars2_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 3/Task3_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 3/Task3_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 3/TaskExpVars3_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 3/TaskExpVars3_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 4/Task4_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 4/Task4_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 4/TaskExpVars4_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 4/TaskExpVars4_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 5/Task5_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 5/Task5_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 5/TaskExpVars5_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 5/TaskExpVars5_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 6/Task6_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 6/Task6_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 6/TaskExpVars6_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 6/TaskExpVars6_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 7/Task7_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 7/Task7_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 7/TaskExpVars7_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 7/TaskExpVars7_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 8/Task8_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 8/Task8_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 8/TaskExpVars8_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 8/TaskExpVars8_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 9/Task9_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 9/Task9_W_Zone1_10.zip -------------------------------------------------------------------------------- /data/Wind/Task 9/TaskExpVars9_W_Zone1_10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ki-ljl/FedAvg-numpy-pytorch-tff/8363876b44197167d1819f79c55756bf558cc0ac/data/Wind/Task 9/TaskExpVars9_W_Zone1_10.zip -------------------------------------------------------------------------------- /models.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | """ 3 | @Time: 2022/03/01 22:23 4 | @Author: KI 5 | @File: models.py 6 | @Motto: Hungry And Humble 7 | """ 8 | import numpy as np 9 | from torch import nn 10 | 11 | 12 | class BP: 13 | def __init__(self, args, file_name): 14 | self.file_name = file_name 15 | self.len = 0 16 | self.args = args 17 | self.input = np.zeros((args.B, args.input_dim)) # self.B samples per round 18 | self.w1 = 2 * np.random.random((args.input_dim, 20)) - 1 # limit to (-1, 1) 19 | self.z1 = 2 * np.random.random((args.B, 20)) - 1 20 | self.hidden_layer_1 = np.zeros((args.B, 20)) 21 | self.w2 = 2 * np.random.random((20, 20)) - 1 22 | self.z2 = 2 * np.random.random((args.B, 20)) - 1 23 | self.hidden_layer_2 = np.zeros((args.B, 20)) 24 | self.w3 = 2 * np.random.random((20, 20)) - 1 25 | self.z3 = 2 * np.random.random((args.B, 20)) - 1 26 | self.hidden_layer_3 = np.zeros((args.B, 20)) 27 | self.w4 = 2 * np.random.random((20, 1)) - 1 28 | self.z4 = 2 * np.random.random((args.B, 1)) - 1 29 | self.output_layer = np.zeros((args.B, 1)) 30 | self.loss = np.zeros((args.B, 1)) 31 | 32 | def sigmoid(self, x): 33 | return 1 / (1 + np.exp(-x)) 34 | 35 | def sigmoid_deri(self, x): 36 | return x * (1 - x) 37 | 38 | def forward_prop(self, data, label): 39 | self.input = data 40 | self.z1 = np.dot(self.input, self.w1) 41 | self.hidden_layer_1 = self.sigmoid(self.z1) 42 | self.z2 = np.dot(self.hidden_layer_1, self.w2) 43 | self.hidden_layer_2 = self.sigmoid(self.z2) 44 | self.z3 = np.dot(self.hidden_layer_2, self.w3) 45 | self.hidden_layer_3 = self.sigmoid(self.z3) 46 | self.z4 = np.dot(self.hidden_layer_3, self.w4) 47 | self.output_layer = self.sigmoid(self.z4) 48 | # error 49 | self.loss = 1 / 2 * (label - self.output_layer) ** 2 50 | 51 | return self.output_layer 52 | 53 | def backward_prop(self, label): 54 | # w4 55 | l_deri_out = self.output_layer - label 56 | l_deri_z4 = l_deri_out * self.sigmoid_deri(self.output_layer) 57 | l_deri_w4 = np.dot(self.hidden_layer_3.T, l_deri_z4) 58 | # w3 59 | l_deri_h3 = np.dot(l_deri_z4, self.w4.T) 60 | l_deri_z3 = l_deri_h3 * self.sigmoid_deri(self.hidden_layer_3) 61 | l_deri_w3 = np.dot(self.hidden_layer_2.T, l_deri_z3) 62 | # w2 63 | l_deri_h2 = np.dot(l_deri_z3, self.w3.T) 64 | l_deri_z2 = l_deri_h2 * self.sigmoid_deri(self.hidden_layer_2) 65 | l_deri_w2 = np.dot(self.hidden_layer_1.T, l_deri_z2) 66 | # w1 67 | l_deri_h1 = np.dot(l_deri_z2, self.w2.T) 68 | l_deri_z1 = l_deri_h1 * self.sigmoid_deri(self.hidden_layer_1) 69 | l_deri_w1 = np.dot(self.input.T, l_deri_z1) 70 | # update 71 | self.w4 -= self.args.lr * l_deri_w4 72 | self.w3 -= self.args.lr * l_deri_w3 73 | self.w2 -= self.args.lr * l_deri_w2 74 | self.w1 -= self.args.lr * l_deri_w1 75 | 76 | 77 | class ANN(nn.Module): 78 | def __init__(self, args, name): 79 | super(ANN, self).__init__() 80 | self.name = name 81 | self.len = 0 82 | self.loss = 0 83 | self.sigmoid = nn.Sigmoid() 84 | self.fc1 = nn.Linear(args.input_dim, 16) 85 | self.fc2 = nn.Linear(16, 32) 86 | self.fc3 = nn.Linear(32, 16) 87 | self.fc4 = nn.Linear(16, 1) 88 | 89 | def forward(self, data): 90 | x = self.fc1(data) 91 | x = self.sigmoid(x) 92 | x = self.fc2(x) 93 | x = self.sigmoid(x) 94 | x = self.fc3(x) 95 | x = self.sigmoid(x) 96 | x = self.fc4(x) 97 | x = self.sigmoid(x) 98 | 99 | return x 100 | --------------------------------------------------------------------------------