Skip to content

Commit 84de632

Browse files
committed
added statistic folder and config.py
1 parent c2915b7 commit 84de632

File tree

3 files changed

+269
-0
lines changed

3 files changed

+269
-0
lines changed

config.py

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
from util.time_generation import TimeGeneration
2+
import os
3+
4+
SERVER_ADDR= 'localhost' # When running in a real distributed setting, change to the server's IP address
5+
SERVER_PORT = 51000
6+
7+
dataset_file_path = os.path.join(os.path.dirname(__file__), 'datasets')
8+
results_file_path = os.path.join(os.path.dirname(__file__), 'results')
9+
single_run_results_file_path = results_file_path + '/SingleRun.csv'
10+
multi_run_results_file_path = results_file_path + '/MultipleRuns.csv'
11+
12+
# Model, dataset, and control parameter configurations for MNIST with SVM
13+
dataset = 'MNIST_ORIG_EVEN_ODD' # Use for SVM model
14+
model_name = 'ModelSVMSmooth'
15+
control_param_phi = 0.025 # Good for MNIST with smooth SVM
16+
17+
# Model, dataset, and control parameter configurations for MNIST with CNN
18+
# dataset = 'MNIST_ORIG_ALL_LABELS' # Use for CNN model
19+
# model_name = 'ModelCNNMnist'
20+
# control_param_phi = 0.00005 # Good for CNN
21+
22+
# Model, dataset, and control parameter configurations for CIFAR-10 with CNN
23+
# dataset = 'CIFAR_10'
24+
# model_name = 'ModelCNNCifar10'
25+
# control_param_phi = 0.00005 # Good for CNN
26+
27+
n_nodes = 5 # Specifies the total number of clients
28+
29+
moving_average_holding_param = 0.0 # Moving average coefficient to smooth the estimation of beta, delta, and rho
30+
31+
step_size = 0.01
32+
33+
# Setting batch_size equal to total_data makes the system use deterministic gradient descent;
34+
# Setting batch_size equal < total_data makes the system use stochastic gradient descent.
35+
# batch_size = 1000 # Value for deterministic gradient descent
36+
# total_data = 1000 # Value for deterministic gradient descent
37+
batch_size = 100 # 100 # Value for stochastic gradient descent
38+
total_data = 60000 # 60000 #Value for stochastic gradient descent
39+
40+
# Choose whether to run a single instance and plot the instantaneous results or
41+
# run multiple instances and plot average results
42+
single_run = False
43+
44+
# Choose whether to estimate beta and delta in all runs, including those where tau is not adaptive,
45+
# this is useful for getting statistics. NOTE: Enabling this may change the communication time when using
46+
# real-world measurements for resource consumption
47+
estimate_beta_delta_in_all_runs = False
48+
49+
# If true, the weight corresponding to minimum loss (the loss is estimated if using stochastic gradient descent) is
50+
# returned. If false, the weight at the end is returned. Setting use_min_loss = True corresponds to the latest
51+
# theoretical bound for the **DISTRIBUTED** case.
52+
# For the **CENTRALIZED** case, set use_min_loss = False,
53+
# because convergence of the final value can be guaranteed in the centralized case.
54+
use_min_loss = True
55+
56+
# Specifies the number of iterations the client uses the same minibatch, using the same minibatch can reduce
57+
# the processing time at the client, but may cause a worse model accuracy.
58+
# We use the same minibatch only when the client receives tau_config = 1
59+
num_iterations_with_same_minibatch_for_tau_equals_one = 3
60+
61+
# Specifies whether all the data should be read when using stochastic gradient descent.
62+
# Reading all the data requires much more memory but should avoid slowing down due to file reading.
63+
read_all_data_for_stochastic = True
64+
65+
MAX_CASE = 4 # Specifies the maximum number of cases, this should be a constant equal to 4
66+
tau_max = 100 # Specifies the maximum value of tau
67+
68+
# tau_setup = -1 is for the proposed adaptive control algorithm, other values of tau correspond to fixed tau values
69+
if not single_run:
70+
tau_setup_all = [-1, 1, 2, 3, 5, 7, 10, 20, 30, 50, 70, 100]
71+
sim_runs = range(0, 2) #Specifies the simulation seeds in each simulation round
72+
case_range = range(0, MAX_CASE)
73+
else:
74+
case_range = [0] # Change if we want single run with other case, should only have one case
75+
tau_setup_all = [-1] # Should only have one value
76+
sim_runs = [0] # Should only have one value, the value specifies the random seed
77+
78+
79+
max_time = 15 # Total time budget in seconds
80+
81+
# If time_gen is None, use actual measured time. Else, use time generated by the TimeGeneration class.
82+
# time_gen = None
83+
# time_gen = TimeGeneration(1, 0.0, 1e-10, 0.0, 0.0, 0.0)
84+
85+
multiply_global = 1.0
86+
multiply_local = 1.0
87+
88+
# These numbers are from measurement on stochastic gradient descent on SVM smooth with MNIST even/odd data.
89+
time_gen = TimeGeneration(multiply_local * 0.013015156, multiply_local * 0.006946299, 1e-10,
90+
multiply_global * 0.131604348, multiply_global * 0.053873234, 1e-10)
91+
92+
# These numbers are from measurement on CENTRALIZED stochastic gradient descent on SVM smooth with MNIST even/odd data.
93+
# time_gen = TimeGeneration(multiply_local * 0.009974248, multiply_local * 0.011922926, 1e-10,
94+
# 0.0, 0.0, 0.0)
95+
96+
# These numbers are from measurement on deterministic gradient descent on SVM smooth with MNIST even/odd data.
97+
# time_gen = []
98+
# time_gen.append(TimeGeneration(multiply_local * 0.020613052, multiply_local * 0.008154439, 1e-10,
99+
# multiply_global * 0.137093837, multiply_global * 0.05548447, 1e-10)) # Case 1
100+
# time_gen.append(TimeGeneration(multiply_local * 0.021810727, multiply_local * 0.008042984, 1e-10,
101+
# multiply_global * 0.12322071, multiply_global * 0.048079171, 1e-10)) # Case 2
102+
# time_gen.append(TimeGeneration(multiply_local * 0.095353094, multiply_local * 0.016688657, 1e-10,
103+
# multiply_global * 0.157255906, multiply_global * 0.066722225, 1e-10)) # Case 3
104+
# time_gen.append(TimeGeneration(multiply_local * 0.022075891, multiply_local * 0.008528005, 1e-10,
105+
# multiply_global * 0.108598094, multiply_global * 0.044627335, 1e-10)) # Case 4

statistic/__init__.py

Whitespace-only changes.

statistic/collect_stat.py

+164
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import numpy as np
2+
import os, sys
3+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
4+
from control_algorithm.adaptive_tau import ControlAlgAdaptiveTauServer
5+
from config import *
6+
7+
8+
class CollectStatistics:
9+
def __init__(self, results_file_name=os.path.dirname(__file__)+'/results.csv', is_single_run=False):
10+
self.results_file_name = results_file_name
11+
self.is_single_run = is_single_run
12+
13+
if not os.path.exists(os.path.dirname(results_file_name)):
14+
os.makedirs(os.path.dirname(results_file_name))
15+
if is_single_run:
16+
with open(results_file_name, 'a') as f:
17+
f.write(
18+
'case,tValue,lossValue,predictionAccuracy,betaAdapt,deltaAdapt,rhoAdapt,tau,it_each_local,it_each_global\n')
19+
f.close()
20+
else:
21+
with open(results_file_name, 'a') as f:
22+
f.write(
23+
'Type,Simulation,case,tau_setup,lossValue,predictionAccuracy,avg_tau,stddev_tau,' +
24+
'avg_each_local,stddev_each_local,avg_each_global,stddev_each_global,' +
25+
'avg_betaAdapt,stddev_betaAdapt,' +
26+
'avg_deltaAdapt,stddev_deltaAdapt,avg_rhoAdapt,stddev_rhoAdapt,' +
27+
'total_time_recomputed\n')
28+
f.close()
29+
30+
def init_stat_new_global_round(self):
31+
32+
if self.is_single_run:
33+
self.loss_values = []
34+
self.prediction_accuracies = []
35+
self.t_values = []
36+
37+
self.taus = []
38+
self.each_locals = []
39+
self.each_globals = []
40+
self.beta_adapts = []
41+
self.delta_adapts = []
42+
self.rho_adapts = []
43+
44+
def init_stat_new_global_round_comp(self):
45+
46+
if self.is_single_run:
47+
self.loss_values = []
48+
self.prediction_accuracies = []
49+
self.t_values = []
50+
self.k = []
51+
self.immediate_cost =[]
52+
53+
def collect_stat_end_local_round(self, case, tau, it_each_local, it_each_global, control_alg, model, train_image,
54+
train_label, test_image, test_label, w_global, total_time_recomputed):
55+
56+
self.taus.append(tau) # Use calculated tau
57+
self.each_locals.append(it_each_local)
58+
self.each_globals.append(it_each_global)
59+
60+
if control_alg is not None:
61+
# TODO: Should define a getter in control algorithm class and use it here
62+
if isinstance(control_alg, ControlAlgAdaptiveTauServer):
63+
if control_alg.beta_adapt_mvaverage is not None:
64+
self.beta_adapts.append(control_alg.beta_adapt_mvaverage)
65+
elif self.is_single_run:
66+
self.beta_adapts.append(np.nan)
67+
68+
if control_alg.delta_adapt_mvaverage is not None:
69+
self.delta_adapts.append(control_alg.delta_adapt_mvaverage)
70+
elif self.is_single_run:
71+
self.delta_adapts.append(np.nan)
72+
73+
if control_alg.rho_adapt_mvaverage is not None:
74+
self.rho_adapts.append(control_alg.rho_adapt_mvaverage)
75+
elif self.is_single_run:
76+
self.rho_adapts.append(np.nan)
77+
78+
else:
79+
if self.is_single_run: # When doing a single run, the array needs to align with the timestamp,
80+
# thus adding an entry on None
81+
self.beta_adapts.append(np.nan)
82+
self.delta_adapts.append(np.nan)
83+
self.rho_adapts.append(np.nan)
84+
85+
if self.is_single_run:
86+
87+
loss_value = model.loss(train_image, train_label, w_global)
88+
self.loss_values.append(loss_value)
89+
90+
prediction_accuracy = model.accuracy(test_image, test_label, w_global)
91+
self.prediction_accuracies.append(prediction_accuracy)
92+
93+
self.t_values.append(total_time_recomputed)
94+
95+
print("***** lossValue: " + str(loss_value))
96+
97+
with open(self.results_file_name, 'a') as f:
98+
f.write(str(case) + ',' + str(total_time_recomputed) + ',' + str(loss_value) + ','
99+
+ str(prediction_accuracy) + ','
100+
+ str(self.beta_adapts[-1]) + ',' + str(self.delta_adapts[-1]) + ',' + str(self.rho_adapts[-1])
101+
+ ',' + str(tau) + ',' + str(it_each_local) + ',' + str(it_each_global) + '\n')
102+
f.close()
103+
104+
def collect_stat_end_local_round_comp(self, case, num_iter, model, train_image, train_label, test_image, test_label,
105+
w_global, total_time_recomputed, k=None, cost=None):
106+
if self.is_single_run:
107+
loss_value = model.loss(train_image, train_label, w_global)
108+
self.loss_values.append(loss_value)
109+
110+
prediction_accuracy = model.accuracy(test_image, test_label, w_global)
111+
self.prediction_accuracies.append(prediction_accuracy)
112+
113+
self.t_values.append(total_time_recomputed)
114+
self.k.append(k)
115+
self.immediate_cost.append(cost)
116+
117+
print("***** lossValue: " + str(loss_value))
118+
119+
with open(self.results_file_name, 'a') as f:
120+
f.write(str(case) + ',' + str(num_iter) + ',' + str(total_time_recomputed) + ',' + str(loss_value) + ','
121+
+ str(prediction_accuracy) + ',' + str(k) + ',' + str(cost) + '\n')
122+
f.close()
123+
124+
def collect_stat_end_global_round(self, sim, case, tau_setup, total_time, model, train_image, train_label,
125+
test_image, test_label, w_eval, total_time_recomputed):
126+
loss_final = model.loss(train_image, train_label, w_eval)
127+
accuracy_final = model.accuracy(test_image, test_label, w_eval)
128+
129+
if not self.is_single_run:
130+
taus_array = np.array(self.taus)
131+
avg_tau = np.sum(np.dot(taus_array, taus_array)) / np.sum(taus_array)
132+
stddev_tau = np.std(taus_array)
133+
avg_each_local = np.mean(np.array(self.each_locals))
134+
stddev_each_local = np.std(np.array(self.each_locals))
135+
avg_each_global = np.mean(np.array(self.each_globals))
136+
stddev_each_global = np.std(np.array(self.each_globals))
137+
avg_beta_adapt = np.mean(np.array(self.beta_adapts))
138+
stddev_beta_adapt = np.std(np.array(self.beta_adapts))
139+
avg_delta_adapt = np.mean(np.array(self.delta_adapts))
140+
stddev_delta_adapt = np.std(np.array(self.delta_adapts))
141+
avg_rho_adapt = np.mean(np.array(self.rho_adapts))
142+
stddev_rho_adapt = np.std(np.array(self.rho_adapts))
143+
144+
if case is None or np.isnan(case):
145+
case = None
146+
type_str = 'centralized'
147+
else:
148+
type_str = 'distributed'
149+
150+
with open(self.results_file_name, 'a') as f:
151+
f.write(type_str + ',' + str(sim) + ',' + str(case) + ',' + str(tau_setup) + ','
152+
+ str(loss_final) + ',' + str(accuracy_final) + ',' + str(avg_tau) + ',' + str(stddev_tau) + ','
153+
+ str(avg_each_local) + ',' + str(stddev_each_local) + ','
154+
+ str(avg_each_global) + ',' + str(stddev_each_global) + ','
155+
+ str(avg_beta_adapt) + ',' + str(stddev_beta_adapt) + ','
156+
+ str(avg_delta_adapt) + ',' + str(stddev_delta_adapt) + ','
157+
+ str(avg_rho_adapt) + ',' + str(stddev_rho_adapt) + ','
158+
+ str(total_time_recomputed) + ','
159+
+ '\n')
160+
f.close()
161+
162+
print('total time', total_time)
163+
print('loss value', loss_final)
164+
print('accuracy', accuracy_final)

0 commit comments

Comments
 (0)