junshan-kit 2.7.3__py2.py3-none-any.whl → 2.8.6__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- junshan_kit/Check_Info.py +20 -12
- junshan_kit/DataProcessor.py +48 -1
- junshan_kit/FiguresHub.py +43 -24
- junshan_kit/OptimizerHup/SPBM.py +6 -4
- junshan_kit/ParametersHub.py +39 -9
- junshan_kit/Print_Info.py +50 -26
- junshan_kit/TrainingHub.py +63 -3
- {junshan_kit-2.7.3.dist-info → junshan_kit-2.8.6.dist-info}/METADATA +1 -1
- {junshan_kit-2.7.3.dist-info → junshan_kit-2.8.6.dist-info}/RECORD +10 -10
- {junshan_kit-2.7.3.dist-info → junshan_kit-2.8.6.dist-info}/WHEEL +0 -0
junshan_kit/Check_Info.py
CHANGED
|
@@ -7,22 +7,23 @@
|
|
|
7
7
|
|
|
8
8
|
from junshan_kit import ModelsHub
|
|
9
9
|
|
|
10
|
-
def check_args(
|
|
10
|
+
def check_args(args, parser, allowed_models, allowed_optimizers, allowed_datasets):
|
|
11
11
|
# Parse and validate each train_group
|
|
12
12
|
for cfg in args.train:
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
model, dataset, optimizer = cfg.split("-")
|
|
14
|
+
|
|
15
|
+
if model not in allowed_models:
|
|
16
|
+
parser.error(f"Invalid model '{model}'. Choose from {allowed_models}")
|
|
17
|
+
|
|
18
|
+
if optimizer not in allowed_optimizers:
|
|
19
|
+
parser.error(f"Invalid optimizer '{optimizer}'. Choose from {allowed_optimizers}")
|
|
15
20
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
parser.error(f"Invalid optimizer '{optimizer}'. Choose from {allowed_optimizers}")
|
|
20
|
-
if dataset not in allowed_datasets:
|
|
21
|
-
parser.error(f"Invalid dataset '{dataset}'. Choose from {allowed_datasets}")
|
|
21
|
+
if dataset not in allowed_datasets:
|
|
22
|
+
print(type(allowed_datasets), allowed_datasets)
|
|
23
|
+
parser.error(f"Invalid dataset '{dataset}'. Choose from {allowed_datasets}")
|
|
22
24
|
|
|
23
|
-
except ValueError:
|
|
24
|
-
parser.error(f"Invalid format '{cfg}'. Use model-dataset-optimizer")
|
|
25
25
|
|
|
26
|
+
# Check if the model-dataset-optimizer combination exists
|
|
26
27
|
for cfg in args.train:
|
|
27
28
|
model_name, dataset_name, optimizer_name = cfg.split("-")
|
|
28
29
|
try:
|
|
@@ -31,8 +32,15 @@ def check_args(self, args, parser, allowed_models, allowed_optimizers, allowed_d
|
|
|
31
32
|
except:
|
|
32
33
|
print(getattr(ModelsHub, f"Build_{args.model_name_mapping[model_name]}_{args.data_name_mapping[dataset_name]}"))
|
|
33
34
|
assert False
|
|
35
|
+
|
|
36
|
+
# Check epochs or iterations
|
|
37
|
+
if args.e is None and args.iter is None:
|
|
38
|
+
parser.error("one of --e or --iter must be specified")
|
|
39
|
+
|
|
40
|
+
if args.e is not None and args.iter is not None:
|
|
41
|
+
parser.error("one of --e or --iter must be specified")
|
|
34
42
|
|
|
35
|
-
def check_subset_info(
|
|
43
|
+
def check_subset_info(args, parser):
|
|
36
44
|
total = sum(args.subset)
|
|
37
45
|
if args.subset[0]>1:
|
|
38
46
|
# CHECK
|
junshan_kit/DataProcessor.py
CHANGED
|
@@ -8,9 +8,11 @@
|
|
|
8
8
|
import pandas as pd
|
|
9
9
|
import numpy as np
|
|
10
10
|
import torch, bz2
|
|
11
|
+
from typing import Optional
|
|
11
12
|
from torch.utils.data import random_split, Subset
|
|
12
13
|
from sklearn.datasets import load_svmlight_file
|
|
13
14
|
from sklearn.preprocessing import StandardScaler
|
|
15
|
+
from junshan_kit import ParametersHub
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
class CSV_TO_Pandas:
|
|
@@ -386,7 +388,7 @@ def get_libsvm_bz2_data(train_path, test_path, data_name, Paras, split = True):
|
|
|
386
388
|
transform = "-1 → 0 for binary, y-1 for multi-class"
|
|
387
389
|
train_data = LibSVMDataset_bz2(train_path)
|
|
388
390
|
|
|
389
|
-
if data_name in ["Duke", "Ijcnn"]:
|
|
391
|
+
if data_name in ["Duke", "Ijcnn", "RCV1"]:
|
|
390
392
|
test_data = LibSVMDataset_bz2(test_path)
|
|
391
393
|
split = False
|
|
392
394
|
else:
|
|
@@ -410,3 +412,48 @@ def get_libsvm_bz2_data(train_path, test_path, data_name, Paras, split = True):
|
|
|
410
412
|
# assert False
|
|
411
413
|
|
|
412
414
|
return train_dataset, test_dataset, transform
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def subset(dataset, ratio_or_num, seed=None) -> Subset:
|
|
418
|
+
"""
|
|
419
|
+
Randomly sample a subset from a dataset.
|
|
420
|
+
|
|
421
|
+
Parameters
|
|
422
|
+
----------
|
|
423
|
+
dataset : torch.utils.data.Dataset
|
|
424
|
+
The dataset to sample from.
|
|
425
|
+
ratio_or_num : float or int
|
|
426
|
+
If float in (0, 1], treated as sampling ratio.
|
|
427
|
+
Otherwise, treated as absolute number of samples.
|
|
428
|
+
seed : int, optional
|
|
429
|
+
Random seed for reproducibility.
|
|
430
|
+
|
|
431
|
+
Returns
|
|
432
|
+
-------
|
|
433
|
+
torch.utils.data.Subset
|
|
434
|
+
A randomly sampled subset of the dataset.
|
|
435
|
+
"""
|
|
436
|
+
|
|
437
|
+
if ratio_or_num < 0:
|
|
438
|
+
raise ValueError(f"ratio_or_num must be non-negative, got {ratio_or_num}")
|
|
439
|
+
|
|
440
|
+
dataset_len = len(dataset)
|
|
441
|
+
|
|
442
|
+
# Determine number of samples
|
|
443
|
+
if isinstance(ratio_or_num, float) and 0 < ratio_or_num <= 1:
|
|
444
|
+
num = max(1, int(round(dataset_len * ratio_or_num)))
|
|
445
|
+
else:
|
|
446
|
+
num = int(ratio_or_num)
|
|
447
|
+
|
|
448
|
+
# Clamp to valid range
|
|
449
|
+
num = min(max(num, 1), dataset_len)
|
|
450
|
+
|
|
451
|
+
# Create and seed generator
|
|
452
|
+
generator = torch.Generator()
|
|
453
|
+
if seed is not None:
|
|
454
|
+
generator.manual_seed(seed)
|
|
455
|
+
|
|
456
|
+
# Random sampling
|
|
457
|
+
indices = torch.randperm(dataset_len, generator=generator)[:num].tolist()
|
|
458
|
+
|
|
459
|
+
return Subset(dataset, indices)
|
junshan_kit/FiguresHub.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
----------------------------------------------------------------------
|
|
3
3
|
>>> Author : Junshan Yin
|
|
4
|
-
>>> Last Updated : 2025-
|
|
4
|
+
>>> Last Updated : 2025-12-19
|
|
5
5
|
----------------------------------------------------------------------
|
|
6
6
|
"""
|
|
7
7
|
import math, os
|
|
@@ -22,6 +22,8 @@ def marker_schedule(marker_schedule=None):
|
|
|
22
22
|
"SPSmax": "4", # tri-right
|
|
23
23
|
"SPBM-PF": "*", # star
|
|
24
24
|
"SPBM-TR": "s", # star
|
|
25
|
+
"SPBM-PF-NoneCut": "s", # circle
|
|
26
|
+
"SPBM-TR-NoneCut": "s", # circle
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
else:
|
|
@@ -64,6 +66,8 @@ def colors_schedule(colors_schedule=None):
|
|
|
64
66
|
"SPSmax": "#BA6262",
|
|
65
67
|
"SPBM-PF": "#1f77b4",
|
|
66
68
|
"SPBM-TR": "#d62728",
|
|
69
|
+
"SPBM-PF-NoneCut": "#8c564b",
|
|
70
|
+
"SPBM-TR-NoneCut": "#e377c2",
|
|
67
71
|
}
|
|
68
72
|
|
|
69
73
|
else:
|
|
@@ -85,6 +89,10 @@ def colors_schedule(colors_schedule=None):
|
|
|
85
89
|
def Search_Paras(Paras, args, model_name, data_name, optimizer_name, metric_key = "training_loss"):
|
|
86
90
|
|
|
87
91
|
param_dict = Paras["Results_dict"][model_name][data_name][optimizer_name]
|
|
92
|
+
if Paras["epochs"] is not None:
|
|
93
|
+
xlabel = "epochs"
|
|
94
|
+
else:
|
|
95
|
+
xlabel = "iterations"
|
|
88
96
|
|
|
89
97
|
num_polts = len(param_dict)
|
|
90
98
|
cols = 3
|
|
@@ -100,7 +108,7 @@ def Search_Paras(Paras, args, model_name, data_name, optimizer_name, metric_key
|
|
|
100
108
|
ax.plot(metric_list)
|
|
101
109
|
# ax.set_title(f"time:{duration:.8f}s - seed: {Paras['seed']}, ID: {Paras['time_str']} \n params = {param_str}", fontsize=10)
|
|
102
110
|
ax.set_title(f'time = {info["train_time"]:.2f}, seed: {Paras["seed"]}, ID: {Paras["time_str"]} \n params = {param_str}', fontsize=10)
|
|
103
|
-
ax.set_xlabel(
|
|
111
|
+
ax.set_xlabel(xlabel)
|
|
104
112
|
ax.set_ylabel(ParametersHub.fig_ylabel(metric_key))
|
|
105
113
|
ax.grid(True)
|
|
106
114
|
if Paras.get('use_log_scale', False) and any(k in metric_key for k in ['loss', 'grad']):
|
|
@@ -112,7 +120,7 @@ def Search_Paras(Paras, args, model_name, data_name, optimizer_name, metric_key
|
|
|
112
120
|
fig.delaxes(axes[i])
|
|
113
121
|
|
|
114
122
|
|
|
115
|
-
plt.suptitle(f'{model_name} on {data_name} - {optimizer_name} (training
|
|
123
|
+
plt.suptitle(f'{model_name} on {data_name} - {optimizer_name}, (training, test) = ({Paras['train_data_num']}/{Paras['train_data_all_num']}, {Paras['test_data_num']}/{Paras['test_data_all_num']}), {Paras["device"]}, batch_size: {Paras["batch_size"]}', fontsize=16)
|
|
116
124
|
plt.tight_layout(rect=(0, 0, 1, 0.9))
|
|
117
125
|
|
|
118
126
|
filename = f'{Paras["Results_folder"]}/{metric_key}_{ParametersHub.model_abbr(model_name)}_{data_name}_{optimizer_name}.pdf'
|
|
@@ -123,24 +131,28 @@ def Search_Paras(Paras, args, model_name, data_name, optimizer_name, metric_key
|
|
|
123
131
|
|
|
124
132
|
def Read_Results_from_pkl(info_dict, Exp_name, model_name):
|
|
125
133
|
draw_data = defaultdict(dict)
|
|
134
|
+
xlabels = {}
|
|
126
135
|
for data_name, info in info_dict.items():
|
|
127
136
|
for optimizer_name, info_opt in info["optimizer"].items():
|
|
128
137
|
|
|
129
|
-
|
|
138
|
+
if hasattr(info, "epochs") and info["epochs"] is not None:
|
|
139
|
+
pkl_path = f'{Exp_name}/seed_{info["seed"]}/{model_name}/{data_name}/{optimizer_name}/train_{info["train_test"][0]}_test_{info["train_test"][1]}/Batch_size_{info["batch_size"]}/epoch_{info["epochs"]}/{info_opt["ID"]}/Results_{ParametersHub.model_abbr(model_name)}_{data_name}_{optimizer_name}.pkl'
|
|
140
|
+
xlabels[data_name] = "epochs"
|
|
141
|
+
|
|
142
|
+
else:
|
|
143
|
+
pkl_path = f'{Exp_name}/seed_{info["seed"]}/{model_name}/{data_name}/{optimizer_name}/train_{info["train_test"][0]}_test_{info["train_test"][1]}/Batch_size_{info["batch_size"]}/iter_{info["iter"]}/{info_opt["ID"]}/Results_{ParametersHub.model_abbr(model_name)}_{data_name}_{optimizer_name}.pkl'
|
|
144
|
+
xlabels[data_name] = "iterations"
|
|
130
145
|
|
|
131
146
|
data_ = kit.read_pkl_data(pkl_path)
|
|
132
147
|
|
|
133
148
|
param_str = ParametersHub.opt_paras_str(info["optimizer"][optimizer_name])
|
|
134
149
|
|
|
135
|
-
# draw_data[data_name][optimizer_name] = data_[param_str][info["metric_key"]]
|
|
136
|
-
# draw_data[data_name][optimizer_name][param_str] = param_str
|
|
137
|
-
# Store both metric list and parameter string
|
|
138
150
|
draw_data[data_name][optimizer_name] = {
|
|
139
151
|
"metrics": data_[param_str][info["metric_key"]],
|
|
140
152
|
"param_str": param_str
|
|
141
153
|
}
|
|
142
154
|
|
|
143
|
-
return draw_data
|
|
155
|
+
return draw_data, xlabels
|
|
144
156
|
|
|
145
157
|
|
|
146
158
|
|
|
@@ -151,13 +163,20 @@ def Mul_Plot(model_name, info_dict, Exp_name = "SPBM", cols = 3, save_path = Non
|
|
|
151
163
|
mpl.rcParams["axes.unicode_minus"] = False
|
|
152
164
|
mpl.rcParams["font.size"] = 12
|
|
153
165
|
mpl.rcParams["font.family"] = "serif"
|
|
166
|
+
xlabels = {}
|
|
154
167
|
|
|
155
168
|
# Read data
|
|
156
169
|
draw_data = defaultdict(dict)
|
|
157
170
|
for data_name, info in info_dict.items():
|
|
158
171
|
for optimizer_name, info_opt in info["optimizer"].items():
|
|
159
172
|
|
|
160
|
-
|
|
173
|
+
if hasattr(info, "epochs") and info["epochs"] is not None:
|
|
174
|
+
pkl_path = f'{Exp_name}/seed_{info["seed"]}/{model_name}/{data_name}/{optimizer_name}/train_{info["train_test"][0]}_test_{info["train_test"][1]}/Batch_size_{info["batch_size"]}/epoch_{info["epochs"]}/{info_opt["ID"]}/Results_{ParametersHub.model_abbr(model_name)}_{data_name}_{optimizer_name}.pkl'
|
|
175
|
+
xlabels[data_name] = "epochs"
|
|
176
|
+
|
|
177
|
+
else:
|
|
178
|
+
pkl_path = f'{Exp_name}/seed_{info["seed"]}/{model_name}/{data_name}/{optimizer_name}/train_{info["train_test"][0]}_test_{info["train_test"][1]}/Batch_size_{info["batch_size"]}/iter_{info["iter"]}/{info_opt["ID"]}/Results_{ParametersHub.model_abbr(model_name)}_{data_name}_{optimizer_name}.pkl'
|
|
179
|
+
xlabels[data_name] = "iterations"
|
|
161
180
|
|
|
162
181
|
data_ = kit.read_pkl_data(pkl_path)
|
|
163
182
|
|
|
@@ -188,7 +207,7 @@ def Mul_Plot(model_name, info_dict, Exp_name = "SPBM", cols = 3, save_path = Non
|
|
|
188
207
|
ax.scatter(x, metric_list_arr[x], marker=marker_schedule("SPBM")[optimizer_name], color = colors_schedule("SPBM")[optimizer_name])
|
|
189
208
|
|
|
190
209
|
ax.set_title(f'{data_name}', fontsize=12)
|
|
191
|
-
ax.set_xlabel(
|
|
210
|
+
ax.set_xlabel(xlabels[data_name], fontsize=12)
|
|
192
211
|
ax.set_ylabel(ParametersHub.fig_ylabel(info_dict[data_name]["metric_key"]), fontsize=12)
|
|
193
212
|
if any(k in info_dict[data_name]["metric_key"] for k in ['loss', 'grad']):
|
|
194
213
|
ax.set_yscale("log")
|
|
@@ -220,19 +239,19 @@ def Mul_Plot(model_name, info_dict, Exp_name = "SPBM", cols = 3, save_path = Non
|
|
|
220
239
|
)
|
|
221
240
|
|
|
222
241
|
plt.tight_layout()
|
|
223
|
-
if
|
|
224
|
-
|
|
242
|
+
if save_path is None:
|
|
243
|
+
save_path_ = f'{model_name}.pdf'
|
|
225
244
|
else:
|
|
226
|
-
os.makedirs(
|
|
227
|
-
|
|
228
|
-
plt.savefig(
|
|
245
|
+
os.makedirs(save_path, exist_ok=True)
|
|
246
|
+
save_path_ = f'{save_path}/{save_name}.pdf'
|
|
247
|
+
plt.savefig(save_path_, bbox_inches="tight")
|
|
229
248
|
if fig_show:
|
|
230
249
|
plt.show()
|
|
231
250
|
plt.close() # Colse the fig
|
|
232
251
|
|
|
233
252
|
|
|
234
253
|
|
|
235
|
-
def Opt_Paras_Plot(model_name, info_dict, Exp_name = "SPBM",
|
|
254
|
+
def Opt_Paras_Plot(model_name, info_dict, Exp_name = "SPBM", save_path = None, save_name = None, fig_show = False):
|
|
236
255
|
|
|
237
256
|
mpl.rcParams['font.family'] = 'Times New Roman'
|
|
238
257
|
mpl.rcParams["mathtext.fontset"] = "stix"
|
|
@@ -241,7 +260,7 @@ def Opt_Paras_Plot(model_name, info_dict, Exp_name = "SPBM", svae_path = None, s
|
|
|
241
260
|
mpl.rcParams["font.family"] = "serif"
|
|
242
261
|
|
|
243
262
|
# Read data
|
|
244
|
-
draw_data = Read_Results_from_pkl(info_dict, Exp_name, model_name)
|
|
263
|
+
draw_data, xlabels = Read_Results_from_pkl(info_dict, Exp_name, model_name)
|
|
245
264
|
|
|
246
265
|
if len(draw_data) >1:
|
|
247
266
|
print('*' * 40)
|
|
@@ -269,18 +288,18 @@ def Opt_Paras_Plot(model_name, info_dict, Exp_name = "SPBM", svae_path = None, s
|
|
|
269
288
|
plt.yscale("log")
|
|
270
289
|
|
|
271
290
|
plt.tight_layout() # Adjust layout so the legend fits
|
|
272
|
-
plt.xlabel(
|
|
291
|
+
plt.xlabel(xlabels[data_name]) # Or whatever your x-axis represents
|
|
273
292
|
plt.ylabel(f'{ParametersHub.fig_ylabel(info_dict[data_name]["metric_key"])}')
|
|
274
|
-
if
|
|
275
|
-
|
|
293
|
+
if save_path is None:
|
|
294
|
+
save_path_ = f'{model_name}.pdf'
|
|
276
295
|
else:
|
|
277
|
-
os.makedirs(
|
|
278
|
-
|
|
279
|
-
plt.savefig(
|
|
280
|
-
|
|
296
|
+
os.makedirs(save_path, exist_ok=True)
|
|
297
|
+
save_path_ = f'{save_path}/{save_name}.pdf'
|
|
298
|
+
plt.savefig(save_path_, bbox_inches="tight")
|
|
281
299
|
if fig_show:
|
|
282
300
|
plt.show()
|
|
283
301
|
|
|
284
302
|
plt.close()
|
|
285
303
|
|
|
286
304
|
|
|
305
|
+
|
junshan_kit/OptimizerHup/SPBM.py
CHANGED
|
@@ -226,7 +226,6 @@ class TR_NoneCut(Optimizer):
|
|
|
226
226
|
super().__init__(params, defaults)
|
|
227
227
|
self.model = model
|
|
228
228
|
self.cutting_num = hyperparams['cutting_number']
|
|
229
|
-
self.M = hyperparams['M']
|
|
230
229
|
self.delta = hyperparams['delta']
|
|
231
230
|
self.Paras = Paras
|
|
232
231
|
|
|
@@ -254,7 +253,9 @@ class TR_NoneCut(Optimizer):
|
|
|
254
253
|
Gk, rk, ek = SPBM_func.get_var(x_his, f_his, g_his, self.delta)
|
|
255
254
|
|
|
256
255
|
# SOVER (dual)
|
|
257
|
-
xk = SPBM_func.subproblem_tr_NoneLower(Gk, ek, xk, rk, self.Paras)
|
|
256
|
+
# xk = SPBM_func.subproblem_tr_NoneLower(Gk, ek, xk, rk, self.Paras)
|
|
257
|
+
|
|
258
|
+
xk = SPBM_func.subproblem_tr_2(Gk, ek, xk, rk, self.Paras)
|
|
258
259
|
|
|
259
260
|
# print(len(self.f_his))
|
|
260
261
|
vector_to_parameters(xk, self.model.parameters())
|
|
@@ -312,7 +313,6 @@ class PF_NoneCut(Optimizer):
|
|
|
312
313
|
super().__init__(params, defaults)
|
|
313
314
|
self.model = model
|
|
314
315
|
self.cutting_num = hyperparams['cutting_number']
|
|
315
|
-
self.M = hyperparams['M']
|
|
316
316
|
self.delta = hyperparams['delta']
|
|
317
317
|
self.Paras = Paras
|
|
318
318
|
|
|
@@ -340,7 +340,9 @@ class PF_NoneCut(Optimizer):
|
|
|
340
340
|
Gk, rk, ek = SPBM_func.get_var(x_his, f_his, g_his, self.delta)
|
|
341
341
|
|
|
342
342
|
# SOVER (dual)
|
|
343
|
-
xk = SPBM_func.subproblem_pf_NoneLower(Gk, ek, xk, self.delta, self.Paras)
|
|
343
|
+
# xk = SPBM_func.subproblem_pf_NoneLower(Gk, ek, xk, self.delta, self.Paras)
|
|
344
|
+
|
|
345
|
+
xk = SPBM_func.subproblem_pf(Gk, ek, xk, self.delta, self.Paras)
|
|
344
346
|
|
|
345
347
|
# print(len(self.f_his))
|
|
346
348
|
vector_to_parameters(xk, self.model.parameters())
|
junshan_kit/ParametersHub.py
CHANGED
|
@@ -49,7 +49,7 @@ class args:
|
|
|
49
49
|
"HL",
|
|
50
50
|
"HQC",
|
|
51
51
|
"TN_Weather",
|
|
52
|
-
]
|
|
52
|
+
]
|
|
53
53
|
# <allowed_datasets>
|
|
54
54
|
data_name_mapping = {
|
|
55
55
|
"MNIST": "MNIST",
|
|
@@ -59,6 +59,8 @@ class args:
|
|
|
59
59
|
"AIP": "Adult_Income_Prediction",
|
|
60
60
|
"CCFD": "Credit_Card_Fraud_Detection",
|
|
61
61
|
"Ijcnn": "Ijcnn",
|
|
62
|
+
"RCV1": "RCV1",
|
|
63
|
+
"w8a": "w8a",
|
|
62
64
|
"DHI":"Diabetes_Health_Indicators",
|
|
63
65
|
"EVP": "Electric_Vehicle_Population",
|
|
64
66
|
"GHP": "Global_House_Purchase",
|
|
@@ -101,10 +103,15 @@ class args:
|
|
|
101
103
|
parser.add_argument(
|
|
102
104
|
"--e",
|
|
103
105
|
type=int,
|
|
104
|
-
required=True,
|
|
105
106
|
help="Number of training epochs. Example: --e 50"
|
|
106
107
|
)
|
|
107
108
|
|
|
109
|
+
parser.add_argument(
|
|
110
|
+
"--iter",
|
|
111
|
+
type=int,
|
|
112
|
+
help="Number of iteration. Example: --iter 50"
|
|
113
|
+
)
|
|
114
|
+
|
|
108
115
|
parser.add_argument(
|
|
109
116
|
"--seed",
|
|
110
117
|
type=int,
|
|
@@ -166,6 +173,13 @@ class args:
|
|
|
166
173
|
# required=True,
|
|
167
174
|
help = "search_grid: 1: "
|
|
168
175
|
)
|
|
176
|
+
|
|
177
|
+
parser.add_argument(
|
|
178
|
+
"--OptParas",
|
|
179
|
+
type=int,
|
|
180
|
+
nargs=1,
|
|
181
|
+
help="Number of optimization steps for parameter tuning (default: 1)"
|
|
182
|
+
)
|
|
169
183
|
# <args_from_command>
|
|
170
184
|
|
|
171
185
|
args = parser.parse_args()
|
|
@@ -173,20 +187,25 @@ class args:
|
|
|
173
187
|
args.data_name_mapping = data_name_mapping
|
|
174
188
|
args.optimizers_name_mapping = optimizers_mapping
|
|
175
189
|
|
|
190
|
+
# <Check_Info>
|
|
191
|
+
Check_Info.check_args(args, parser, allowed_models, allowed_optimizers, allowed_datasets)
|
|
176
192
|
return args
|
|
177
193
|
# <args>
|
|
178
194
|
|
|
179
195
|
def UpdateOtherParas(args, OtherParas):
|
|
196
|
+
# <time_str>
|
|
180
197
|
if args.time_str is not None:
|
|
181
198
|
time_str = args.time_str[0]
|
|
182
199
|
else:
|
|
183
200
|
time_str = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
|
184
201
|
|
|
202
|
+
# <user_search_grid>
|
|
185
203
|
if args.user_search_grid is not None:
|
|
186
204
|
OtherParas["user_search_grid"] = args.user_search_grid[0]
|
|
187
205
|
else:
|
|
188
206
|
OtherParas["user_search_grid"] = None
|
|
189
207
|
|
|
208
|
+
# <send_email>
|
|
190
209
|
if args.send_email is not None:
|
|
191
210
|
OtherParas["from_email"] = args.send_email[0]
|
|
192
211
|
OtherParas["to_email"] = args.send_email[1]
|
|
@@ -195,6 +214,11 @@ def UpdateOtherParas(args, OtherParas):
|
|
|
195
214
|
else:
|
|
196
215
|
OtherParas["send_email"] = False
|
|
197
216
|
|
|
217
|
+
if args.OptParas is not None:
|
|
218
|
+
OtherParas["SeleParasOn"] = False
|
|
219
|
+
else:
|
|
220
|
+
OtherParas["SeleParasOn"] = True
|
|
221
|
+
|
|
198
222
|
OtherParas["time_str"] = time_str
|
|
199
223
|
OtherParas["results_folder_name"] = f'Results_{OtherParas["exp_name"]}'
|
|
200
224
|
|
|
@@ -231,9 +255,6 @@ def set_paras(args, OtherParas):
|
|
|
231
255
|
# batch-size
|
|
232
256
|
"batch_size": args.bs,
|
|
233
257
|
|
|
234
|
-
# epochs
|
|
235
|
-
"epochs": args.e,
|
|
236
|
-
|
|
237
258
|
# split_train_data
|
|
238
259
|
"split_train_data": args.s,
|
|
239
260
|
|
|
@@ -246,7 +267,8 @@ def set_paras(args, OtherParas):
|
|
|
246
267
|
# type: bool
|
|
247
268
|
"user_search_grid": OtherParas["user_search_grid"],
|
|
248
269
|
}
|
|
249
|
-
|
|
270
|
+
Paras["iter"] = args.iter
|
|
271
|
+
Paras["epochs"] = args.e
|
|
250
272
|
Paras = model_list(Paras)
|
|
251
273
|
Paras = model_type(Paras)
|
|
252
274
|
Paras = data_list(Paras)
|
|
@@ -428,7 +450,6 @@ def optimizer_paras_dict(Paras, OtherParas)->dict:
|
|
|
428
450
|
# ----------- SPBM-TR-NoneCut -----------
|
|
429
451
|
"SPBM-TR-NoneCut": {
|
|
430
452
|
"params": {
|
|
431
|
-
"M": [1e-5],
|
|
432
453
|
"delta": (
|
|
433
454
|
[2**i for i in range(-8, 9)]
|
|
434
455
|
if OtherParas["SeleParasOn"]
|
|
@@ -453,7 +474,6 @@ def optimizer_paras_dict(Paras, OtherParas)->dict:
|
|
|
453
474
|
# ----------- SPBM-PF-NoneCut -----------
|
|
454
475
|
"SPBM-PF-NoneCut": {
|
|
455
476
|
"params": {
|
|
456
|
-
"M": [1e-5],
|
|
457
477
|
"delta": (
|
|
458
478
|
[2**i for i in range(-8, 9)]
|
|
459
479
|
if OtherParas["SeleParasOn"]
|
|
@@ -485,7 +505,15 @@ def hyperparas_and_path(Paras, model_name, data_name, optimizer_name, params_gir
|
|
|
485
505
|
|
|
486
506
|
keys, values = list(params_gird.keys()), list(params_gird.values())
|
|
487
507
|
|
|
488
|
-
Paras["
|
|
508
|
+
if Paras["epochs"] is not None:
|
|
509
|
+
Paras["Results_folder"] = f'./{Paras["results_folder_name"]}/seed_{Paras["seed"]}/{model_name}/{data_name}/{optimizer_name}/train_{Paras["train_data_num"]}_test_{Paras["test_data_num"]}/Batch_size_{Paras["batch_size"]}/epoch_{Paras["epochs"]}/{Paras["time_str"]}'
|
|
510
|
+
|
|
511
|
+
elif Paras["iter"] is not None:
|
|
512
|
+
Paras["Results_folder"] = f'./{Paras["results_folder_name"]}/seed_{Paras["seed"]}/{model_name}/{data_name}/{optimizer_name}/train_{Paras["train_data_num"]}_test_{Paras["test_data_num"]}/Batch_size_{Paras["batch_size"]}/iter_{Paras["iter"]}/{Paras["time_str"]}'
|
|
513
|
+
|
|
514
|
+
else:
|
|
515
|
+
assert "one of --e or --iter must be specified"
|
|
516
|
+
|
|
489
517
|
os.makedirs(Paras["Results_folder"], exist_ok=True)
|
|
490
518
|
|
|
491
519
|
return keys, values, Paras
|
|
@@ -588,10 +616,12 @@ def opt_paras_str(opt_paras_dict):
|
|
|
588
616
|
def set_marker_point(epoch_num: int) -> list:
|
|
589
617
|
marker_point = {
|
|
590
618
|
1: [0],
|
|
619
|
+
3: [0, 2],
|
|
591
620
|
4: [0, 2, 4],
|
|
592
621
|
6: [0, 2, 4, 6],
|
|
593
622
|
8: [0, 2, 4, 6, 8],
|
|
594
623
|
10: [0, 2, 4, 6, 8, 10],
|
|
624
|
+
50: [0, 10, 20, 30, 40, 50],
|
|
595
625
|
100: [0, 20, 40, 60, 80, 100],
|
|
596
626
|
200: [0, 40, 80, 120, 160, 200],
|
|
597
627
|
}
|
junshan_kit/Print_Info.py
CHANGED
|
@@ -9,51 +9,75 @@ def training_group(training_group):
|
|
|
9
9
|
print(f"-------------------------------------------------------")
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
def training_info(
|
|
13
|
-
if Paras[
|
|
14
|
-
print(
|
|
12
|
+
def training_info(data_name, optimizer_name, hyperparams, Paras, model_name):
|
|
13
|
+
if Paras['use_color']:
|
|
14
|
+
print('\033[90m' + '-' * 115 + '\033[0m')
|
|
15
|
+
print(
|
|
16
|
+
f'\033[32m✅ \033[34mDataset:\033[32m {data_name}, \t'
|
|
17
|
+
f'\033[34mBatch-size:\033[32m {Paras["batch_size"]}, \t'
|
|
18
|
+
f'\033[34m(training, test) = \033[32m '
|
|
19
|
+
f'({Paras["train_data_num"]}/{Paras["train_data_all_num"]}, '
|
|
20
|
+
f'{Paras["test_data_num"]}/{Paras["test_data_all_num"]}), \t'
|
|
21
|
+
f'\033[34mdevice:\033[32m {Paras["device"]}'
|
|
22
|
+
)
|
|
15
23
|
print(
|
|
16
|
-
f
|
|
24
|
+
f'\033[32m✅ \033[34mOptimizer:\033[32m {optimizer_name}, \t'
|
|
25
|
+
f'\033[34mParams:\033[32m {hyperparams}'
|
|
17
26
|
)
|
|
18
27
|
print(
|
|
19
|
-
f
|
|
28
|
+
f'\033[32m✅ \033[34mmodel:\033[32m {model_name}, \t'
|
|
29
|
+
f'\033[34mmodel type:\033[32m {Paras["model_type"][model_name]}, \t'
|
|
30
|
+
f'\033[34mloss_fn:\033[32m {Paras["loss_fn"]}'
|
|
20
31
|
)
|
|
21
32
|
print(
|
|
22
|
-
f'\033[32m✅ \033[
|
|
33
|
+
f'\033[32m✅ \033[34mResults_folder:\033[32m {Paras["Results_folder"]}'
|
|
23
34
|
)
|
|
24
|
-
print(
|
|
25
|
-
print("\033[90m" + "-" * 115 + "\033[0m")
|
|
35
|
+
print('\033[90m' + '-' * 115 + '\033[0m')
|
|
26
36
|
|
|
27
37
|
else:
|
|
28
|
-
print(
|
|
38
|
+
print('-' * 115)
|
|
29
39
|
print(
|
|
30
|
-
f
|
|
40
|
+
f'✅ Dataset: {data_name}, \t'
|
|
41
|
+
f'Batch-size: {Paras["batch_size"]}, \t'
|
|
42
|
+
f'(training, test) = '
|
|
43
|
+
f'({Paras["train_data_num"]}/{Paras["train_data_all_num"]}, '
|
|
44
|
+
f'{Paras["test_data_num"]}/{Paras["test_data_all_num"]}), \t'
|
|
45
|
+
f'device: {Paras["device"]}'
|
|
31
46
|
)
|
|
32
|
-
print(f
|
|
47
|
+
print(f'✅ Optimizer: {optimizer_name}, \tParams: {hyperparams}')
|
|
33
48
|
print(
|
|
34
|
-
f
|
|
49
|
+
f'✅ model: {model_name}, \t'
|
|
50
|
+
f'model type: {Paras["model_type"][model_name]}, \t'
|
|
51
|
+
f'loss_fn: {Paras["loss_fn"]}'
|
|
35
52
|
)
|
|
36
|
-
print(f
|
|
37
|
-
print(
|
|
38
|
-
|
|
53
|
+
print(f'✅ Results_folder: {Paras["Results_folder"]}')
|
|
54
|
+
print('-' * 115)
|
|
39
55
|
# <Step_7_2>
|
|
40
56
|
|
|
41
|
-
def per_epoch_info(Paras, epoch, metrics,
|
|
42
|
-
if Paras
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
57
|
+
def per_epoch_info(Paras, epoch, metrics, epoch_time):
|
|
58
|
+
if Paras.get('epochs') is not None:
|
|
59
|
+
progress = f'{epoch + 1}/{Paras["epochs"]}'
|
|
60
|
+
progress_label = 'epoch'
|
|
61
|
+
else:
|
|
62
|
+
progress = f'{epoch + 1}/{Paras["iter"]}'
|
|
63
|
+
progress_label = 'iter'
|
|
48
64
|
|
|
65
|
+
if Paras['use_color']:
|
|
66
|
+
print(
|
|
67
|
+
f'\033[34m {progress_label} = \033[32m{progress}\033[0m,\t'
|
|
68
|
+
f'\033[34m training_loss = \033[32m{metrics["training_loss"][epoch + 1]:.4e}\033[0m,\t'
|
|
69
|
+
f'\033[34m training_acc = \033[32m{100 * metrics["training_acc"][epoch + 1]:.2f}%\033[0m,\t'
|
|
70
|
+
f'\033[34m time = \033[32m{epoch_time:.2f}s\033[0m'
|
|
71
|
+
)
|
|
49
72
|
else:
|
|
50
73
|
print(
|
|
51
|
-
f
|
|
52
|
-
f
|
|
53
|
-
f
|
|
54
|
-
f
|
|
74
|
+
f'{progress_label} = {progress},\t'
|
|
75
|
+
f'training_loss = {metrics["training_loss"][epoch + 1]:.4e},\t'
|
|
76
|
+
f'training_acc = {100 * metrics["training_acc"][epoch + 1]:.2f}%,\t'
|
|
77
|
+
f'time = {epoch_time:.2f}s'
|
|
55
78
|
)
|
|
56
79
|
|
|
80
|
+
|
|
57
81
|
def print_per_epoch_info(epoch, Paras, epoch_loss, training_loss, training_acc, test_loss, test_acc, run_time):
|
|
58
82
|
epochs = Paras["epochs"][Paras["data_name"]]
|
|
59
83
|
# result = [(k, f"{v:.4f}") for k, v in run_time.items()]
|
junshan_kit/TrainingHub.py
CHANGED
|
@@ -90,8 +90,8 @@ def load_data(model_name, data_name, Paras):
|
|
|
90
90
|
assert False
|
|
91
91
|
|
|
92
92
|
# Computing the number of data
|
|
93
|
-
Paras["train_data_num"] = len(train_dataset)
|
|
94
|
-
Paras["
|
|
93
|
+
Paras["train_data_num"], Paras["test_data_num"] = len(train_dataset), len(test_dataset)
|
|
94
|
+
Paras["train_data_all_num"], Paras["test_data_all_num"] = len(train_dataset), len(test_dataset)
|
|
95
95
|
|
|
96
96
|
return train_dataset, test_dataset, Paras
|
|
97
97
|
|
|
@@ -238,7 +238,6 @@ def train(train_loader, optimizer_name, optimizer, model, loss_fn, Paras):
|
|
|
238
238
|
loss = 0
|
|
239
239
|
raise NotImplementedError(f"{optimizer_name} is not supported.")
|
|
240
240
|
|
|
241
|
-
|
|
242
241
|
# Evaluation
|
|
243
242
|
training_loss, training_acc = Evaluate_Metrics.get_loss_acc(train_loader, model, loss_fn, Paras)
|
|
244
243
|
|
|
@@ -254,6 +253,67 @@ def train(train_loader, optimizer_name, optimizer, model, loss_fn, Paras):
|
|
|
254
253
|
return metrics
|
|
255
254
|
# <training>
|
|
256
255
|
|
|
256
|
+
# <training_iteration>
|
|
257
|
+
def train_iteration(train_loader, optimizer_name, optimizer, model, loss_fn, Paras):
|
|
258
|
+
train_time = time.time()
|
|
259
|
+
metrics = ParametersHub.metrics()
|
|
260
|
+
for iter in range(Paras["iter"]):
|
|
261
|
+
iter_time = time.time()
|
|
262
|
+
for index, (X, Y) in enumerate(train_loader):
|
|
263
|
+
X, Y = X.to(Paras["device"]), Y.to(Paras["device"])
|
|
264
|
+
|
|
265
|
+
if iter == 0 and index == 0:
|
|
266
|
+
initial_time = time.time()
|
|
267
|
+
initial_loss, initial_correct = Evaluate_Metrics.get_loss_acc(train_loader, model, loss_fn, Paras)
|
|
268
|
+
metrics["training_loss"].append(initial_loss)
|
|
269
|
+
metrics["training_acc"].append(initial_correct)
|
|
270
|
+
|
|
271
|
+
Print_Info.per_epoch_info(Paras, -1, metrics, time.time() - initial_time)
|
|
272
|
+
|
|
273
|
+
# Update the model
|
|
274
|
+
if optimizer_name in ["SGD", "ADAM"]:
|
|
275
|
+
optimizer.zero_grad()
|
|
276
|
+
loss = Evaluate_Metrics.loss(X, Y, model, loss_fn, Paras)
|
|
277
|
+
loss.backward()
|
|
278
|
+
optimizer.step()
|
|
279
|
+
|
|
280
|
+
elif optimizer_name in [
|
|
281
|
+
"Bundle",
|
|
282
|
+
"SPBM-TR",
|
|
283
|
+
"SPBM-PF",
|
|
284
|
+
"ALR-SMAG",
|
|
285
|
+
"SPSmax",
|
|
286
|
+
"SPBM-TR-NoneSpecial",
|
|
287
|
+
"SPBM-TR-NoneLower",
|
|
288
|
+
"SPBM-TR-NoneCut",
|
|
289
|
+
"SPBM-PF-NoneCut",
|
|
290
|
+
]:
|
|
291
|
+
def closure():
|
|
292
|
+
optimizer.zero_grad()
|
|
293
|
+
loss = Evaluate_Metrics.loss(X, Y, model, loss_fn, Paras)
|
|
294
|
+
loss.backward()
|
|
295
|
+
return loss
|
|
296
|
+
|
|
297
|
+
loss = optimizer.step(closure)
|
|
298
|
+
|
|
299
|
+
else:
|
|
300
|
+
loss = 0
|
|
301
|
+
raise NotImplementedError(f"{optimizer_name} is not supported.")
|
|
302
|
+
|
|
303
|
+
# Evaluation
|
|
304
|
+
training_loss, training_acc = Evaluate_Metrics.get_loss_acc(train_loader, model, loss_fn, Paras)
|
|
305
|
+
|
|
306
|
+
metrics["training_loss"].append(training_loss)
|
|
307
|
+
metrics["training_acc"].append(training_acc)
|
|
308
|
+
|
|
309
|
+
Print_Info.per_epoch_info(Paras, iter, metrics, time.time() - iter_time)
|
|
310
|
+
|
|
311
|
+
time_cost = time.time() - train_time
|
|
312
|
+
metrics["train_time"] = time_cost
|
|
313
|
+
|
|
314
|
+
return metrics
|
|
315
|
+
# <training_iteration>
|
|
316
|
+
|
|
257
317
|
def Record_Results(hyperparams,data_name, model_name, optimizer_name, metrics, Paras):
|
|
258
318
|
|
|
259
319
|
keys = list(hyperparams.keys())
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
junshan_kit/BenchmarkFunctions.py,sha256=tXgZGg-CjTNz78nMyVEQflVFIJDgmmePytXjY_RT9BM,120
|
|
2
|
-
junshan_kit/Check_Info.py,sha256=
|
|
2
|
+
junshan_kit/Check_Info.py,sha256=CTJgzyTYA_kPbBnm3x5oH148SzbULYQnePyY8S_bpsI,2106
|
|
3
3
|
junshan_kit/DataHub.py,sha256=6RCNr8dBTqK-8ey4m-baMU1qOsJP6swOFkaraGdk0fM,6801
|
|
4
|
-
junshan_kit/DataProcessor.py,sha256=
|
|
4
|
+
junshan_kit/DataProcessor.py,sha256=Uc9ixhnVmGf5PoGIe3vvhobH_ADtDAosG9MTjnB1KDQ,15677
|
|
5
5
|
junshan_kit/DataSets.py,sha256=DcpwWRm1_B29hIDjOhvaeKAYYeBknEW2QqsS_qm8Hxs,13367
|
|
6
6
|
junshan_kit/Evaluate_Metrics.py,sha256=PQBGU8fETIvDon1VMdouZ1dhG2n7XHYGbzs2EQUA9FM,3392
|
|
7
|
-
junshan_kit/FiguresHub.py,sha256=
|
|
7
|
+
junshan_kit/FiguresHub.py,sha256=Z9mVN3Pnklt1JhkFPd7LO-46kZnf8JRrjfJEy38H3IE,11407
|
|
8
8
|
junshan_kit/ModelsHub.py,sha256=xM6cwLecq9vukrt1c9l7l9dy7mQn3yq0ZwrRg5f_CfM,7995
|
|
9
|
-
junshan_kit/ParametersHub.py,sha256=
|
|
10
|
-
junshan_kit/Print_Info.py,sha256=
|
|
11
|
-
junshan_kit/TrainingHub.py,sha256=
|
|
9
|
+
junshan_kit/ParametersHub.py,sha256=pDtVEL9nx3UBtNfKfZyvXf9KXjC-OJkBwursOlSigvs,20935
|
|
10
|
+
junshan_kit/Print_Info.py,sha256=xhxcq1XayMZIbNjrG_74sAa8VCNvw5osPjXQhxkgN_M,5393
|
|
11
|
+
junshan_kit/TrainingHub.py,sha256=eK06q_xtcj4E6qkV-EHT2-UKv-yDDXUwx9n1EivdetQ,13775
|
|
12
12
|
junshan_kit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
13
|
junshan_kit/kit.py,sha256=tQGoJJQZW9BeadX2cuwhvOxX2riHBZG0iFExelS4MIY,11487
|
|
14
14
|
junshan_kit/OptimizerHup/OptimizerFactory.py,sha256=x1_cE5ZSkKffdY0uCIirocBNj2X-u_R-V5jNawJ1EfA,4607
|
|
15
|
-
junshan_kit/OptimizerHup/SPBM.py,sha256=
|
|
15
|
+
junshan_kit/OptimizerHup/SPBM.py,sha256=h449QddeN0MvUIQeKcNxFsdxdBuhN354sGc_sN2LZR8,13816
|
|
16
16
|
junshan_kit/OptimizerHup/SPBM_func.py,sha256=5Fz6eHYIVGMoR_CBDA_Xk_1dnPRq3K16DUNoNaWQ2Ag,17301
|
|
17
17
|
junshan_kit/OptimizerHup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
-
junshan_kit-2.
|
|
19
|
-
junshan_kit-2.
|
|
20
|
-
junshan_kit-2.
|
|
18
|
+
junshan_kit-2.8.6.dist-info/METADATA,sha256=PzbDtkti_zBXqS4nZyt3o770Ocx5kBlriB3_LdytvIs,455
|
|
19
|
+
junshan_kit-2.8.6.dist-info/WHEEL,sha256=aha0VrrYvgDJ3Xxl3db_g_MDIW-ZexDdrc_m-Hk8YY4,105
|
|
20
|
+
junshan_kit-2.8.6.dist-info/RECORD,,
|
|
File without changes
|