├── .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 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/dictionaries/Administrator.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | fedavg
5 | pytorch
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
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 |
10 |
11 |
12 |
13 |
14 |
15 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 | 1646110310871
170 |
171 |
172 | 1646110310871
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
204 |
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 | 
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 |
--------------------------------------------------------------------------------