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 CHANGED
@@ -7,22 +7,23 @@
7
7
 
8
8
  from junshan_kit import ModelsHub
9
9
 
10
- def check_args(self, args, parser, allowed_models, allowed_optimizers, allowed_datasets):
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
- try:
14
- model, dataset, optimizer = cfg.split("-")
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
- if model not in allowed_models:
17
- parser.error(f"Invalid model '{model}'. Choose from {allowed_models}")
18
- if optimizer not in allowed_optimizers:
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(self, args, parser):
43
+ def check_subset_info(args, parser):
36
44
  total = sum(args.subset)
37
45
  if args.subset[0]>1:
38
46
  # CHECK
@@ -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-11-14
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("epochs")
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/test samples: {Paras["train_data_num"]}/{Paras["test_data_num"]}), {Paras["device"]}', fontsize=16)
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
- 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'
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
- 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'
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("epochs", fontsize=12)
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 save_name is None:
224
- save_path = f'{model_name}.pdf'
242
+ if save_path is None:
243
+ save_path_ = f'{model_name}.pdf'
225
244
  else:
226
- os.makedirs(save_name, exist_ok=True)
227
- save_path = f'{save_name}/{save_name}.pdf'
228
- plt.savefig(save_path, bbox_inches="tight")
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", svae_path = None, save_name = None, fig_show = False):
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("epochs") # Or whatever your x-axis represents
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 save_name is None:
275
- save_path = f'{model_name}.pdf'
293
+ if save_path is None:
294
+ save_path_ = f'{model_name}.pdf'
276
295
  else:
277
- os.makedirs(save_name, exist_ok=True)
278
- save_path = f'{save_name}/{save_name}.pdf'
279
- plt.savefig(save_path, bbox_inches="tight")
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
+
@@ -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())
@@ -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["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"]}'
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(args, data_name, optimizer_name, hyperparams, Paras, model_name):
13
- if Paras["use_color"]:
14
- print("\033[90m" + "-" * 115 + "\033[0m")
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"\033[32m✅ \033[34mDataset:\033[32m {data_name}, \t\033[34mBatch-size:\033[32m {args.bs}, \t\033[34m(training, test) = \033[32m ({Paras['train_data_num']}, {Paras['test_data_num']}), \t\033[34m device:\033[32m {Paras['device']}"
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"\033[32m✅ \033[34mOptimizer:\033[32m {optimizer_name}, \t\033[34mParams:\033[32m {hyperparams}"
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[34mmodel:\033[32m {model_name}, \t\033[34mmodel type:\033[32m {Paras["model_type"][model_name]},\t\033[34m loss_fn:\033[32m {Paras["loss_fn"]}'
33
+ f'\033[32m✅ \033[34mResults_folder:\033[32m {Paras["Results_folder"]}'
23
34
  )
24
- print(f'\033[32m✅ \033[34mResults_folder:\033[32m {Paras["Results_folder"]}')
25
- print("\033[90m" + "-" * 115 + "\033[0m")
35
+ print('\033[90m' + '-' * 115 + '\033[0m')
26
36
 
27
37
  else:
28
- print("-" * 115)
38
+ print('-' * 115)
29
39
  print(
30
- f"✅ Dataset: {data_name}, \tBatch-size: {args.bs}, \t(training, test) = ({Paras['train_data_num']}, {Paras['test_data_num']}), \tdevice: {Paras['device']}"
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"✅ Optimizer: {optimizer_name}, \tParams: {hyperparams}")
47
+ print(f'✅ Optimizer: {optimizer_name}, \tParams: {hyperparams}')
33
48
  print(
34
- f"✅ model: {model_name}, \tmodel type: {Paras['model_type'][model_name]}, \tloss_fn: {Paras['loss_fn']}"
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"✅ Results_folder: {Paras['Results_folder']}")
37
- print("-" * 115)
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, time):
42
- if Paras["use_color"]:
43
- print(
44
- f'\033[34m epoch = \033[32m{epoch+1}/{Paras["epochs"]}\033[0m,\t\b'
45
- f'\033[34m training_loss = \033[32m{metrics["training_loss"][epoch+1]:.4e}\033[0m,\t\b'
46
- f'\033[34m training_acc = \033[32m{100 * metrics["training_acc"][epoch+1]:.2f}\033[0m,\t\b'
47
- f'\033[34m time = \033[32m{time:.2f}\033[0m,\t\b')
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"epoch = {epoch+1}/{Paras['epochs']},\t"
52
- f"training_loss = {metrics['training_loss'][epoch+1]:.4e},\t"
53
- f"training_acc = {100 * metrics['training_acc'][epoch+1]:.2f}%,\t"
54
- f"time = {time:.2f}"
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()]
@@ -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["test_data_num"] = len(test_dataset)
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: junshan_kit
3
- Version: 2.7.3
3
+ Version: 2.8.6
4
4
  Summary: This is an optimization tool.
5
5
  Author-email: Junshan Yin <junshanyin@163.com>
6
6
  Requires-Dist: cvxpy==1.6.5
@@ -1,20 +1,20 @@
1
1
  junshan_kit/BenchmarkFunctions.py,sha256=tXgZGg-CjTNz78nMyVEQflVFIJDgmmePytXjY_RT9BM,120
2
- junshan_kit/Check_Info.py,sha256=Z6Ls2S7Fl4h8S9s0NB8jP_YpSLZInvQAeyjIXzq5Bpc,1872
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=W2bzugcYnwQC403GdvSmGDBhfz8X1KxJBkOAVg1vHHk,14385
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=116cvRUGUcBqIAs0_xiRzZCzgnPaqmgI5kvNu6cAd_Q,10181
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=RSgsSlH0bgehn27lleKfboT1MuLAyIMxZ5FWC-ANbhA,19822
10
- junshan_kit/Print_Info.py,sha256=uBLpeynOYSZTN8LbJupSH1SuLZ-7cMU3Yp3IlVJWB1s,4772
11
- junshan_kit/TrainingHub.py,sha256=WV3cUz4JsEdGTpbTqgnU3WmlKeob8RAOuL993EsADj0,11469
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=2Yg8Fmc8OkYOrjevD8eAGfI-m-fefoOldybtlp4ZEEs,13730
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.7.3.dist-info/METADATA,sha256=_mIq2RLQUdQECGnjRK4qABiPr41BGiK-aCkk4EQVKik,455
19
- junshan_kit-2.7.3.dist-info/WHEEL,sha256=aha0VrrYvgDJ3Xxl3db_g_MDIW-ZexDdrc_m-Hk8YY4,105
20
- junshan_kit-2.7.3.dist-info/RECORD,,
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,,