spacr 0.2.56__py3-none-any.whl → 0.2.61__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.
spacr/deep_spacr.py CHANGED
@@ -1,4 +1,7 @@
1
1
  import os, torch, time, gc, datetime
2
+
3
+ torch.backends.cudnn.benchmark = True
4
+
2
5
  import numpy as np
3
6
  import pandas as pd
4
7
  from torch.optim import Adagrad, AdamW
@@ -8,13 +11,14 @@ import torch.nn.functional as F
8
11
  from IPython.display import display, clear_output
9
12
  import matplotlib.pyplot as plt
10
13
  from PIL import Image
14
+ from sklearn.metrics import auc, precision_recall_curve
15
+ from multiprocessing import set_start_method
16
+ #set_start_method('spawn', force=True)
11
17
 
12
18
  from .logger import log_function_call
13
19
  from .utils import close_multiprocessing_processes, reset_mp
14
- #reset_mp()
15
- #close_multiprocessing_processes()
16
20
 
17
- def evaluate_model_core(model, loader, loader_name, epoch, loss_type):
21
+ def evaluate_model_performance(model, loader, epoch, loss_type):
18
22
  """
19
23
  Evaluates the performance of a model on a given data loader.
20
24
 
@@ -31,7 +35,56 @@ def evaluate_model_core(model, loader, loader_name, epoch, loss_type):
31
35
  all_labels (list): The true labels for each prediction.
32
36
  """
33
37
 
34
- from .utils import calculate_loss, classification_metrics
38
+ from .utils import calculate_loss
39
+
40
+ def classification_metrics(all_labels, prediction_pos_probs):
41
+ """
42
+ Calculate classification metrics for binary classification.
43
+
44
+ Parameters:
45
+ - all_labels (list): List of true labels.
46
+ - prediction_pos_probs (list): List of predicted positive probabilities.
47
+ - loader_name (str): Name of the data loader.
48
+
49
+ Returns:
50
+ - data_df (DataFrame): DataFrame containing the calculated metrics.
51
+ """
52
+
53
+ if len(all_labels) != len(prediction_pos_probs):
54
+ raise ValueError(f"all_labels ({len(all_labels)}) and pred_labels ({len(prediction_pos_probs)}) have different lengths")
55
+
56
+ unique_labels = np.unique(all_labels)
57
+ if len(unique_labels) >= 2:
58
+ pr_labels = np.array(all_labels).astype(int)
59
+ precision, recall, thresholds = precision_recall_curve(pr_labels, prediction_pos_probs, pos_label=1)
60
+ pr_auc = auc(recall, precision)
61
+ thresholds = np.append(thresholds, 0.0)
62
+ f1_scores = 2 * (precision * recall) / (precision + recall)
63
+ optimal_idx = np.nanargmax(f1_scores)
64
+ optimal_threshold = thresholds[optimal_idx]
65
+ pred_labels = [int(p > 0.5) for p in prediction_pos_probs]
66
+ if len(unique_labels) < 2:
67
+ optimal_threshold = 0.5
68
+ pred_labels = [int(p > optimal_threshold) for p in prediction_pos_probs]
69
+ pr_auc = np.nan
70
+ data = {'label': all_labels, 'pred': pred_labels}
71
+ df = pd.DataFrame(data)
72
+ pc_df = df[df['label'] == 1.0]
73
+ nc_df = df[df['label'] == 0.0]
74
+ correct = df[df['label'] == df['pred']]
75
+ acc_all = len(correct) / len(df)
76
+ if len(pc_df) > 0:
77
+ correct_pc = pc_df[pc_df['label'] == pc_df['pred']]
78
+ acc_pc = len(correct_pc) / len(pc_df)
79
+ else:
80
+ acc_pc = np.nan
81
+ if len(nc_df) > 0:
82
+ correct_nc = nc_df[nc_df['label'] == nc_df['pred']]
83
+ acc_nc = len(correct_nc) / len(nc_df)
84
+ else:
85
+ acc_nc = np.nan
86
+ data_dict = {'accuracy': acc_all, 'neg_accuracy': acc_nc, 'pos_accuracy': acc_pc, 'prauc':pr_auc, 'optimal_threshold':optimal_threshold}
87
+ return data_dict
35
88
 
36
89
  device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
37
90
  model.eval()
@@ -61,48 +114,15 @@ def evaluate_model_core(model, loader, loader_name, epoch, loss_type):
61
114
  acc = correct / total_samples
62
115
  end_time = time.time()
63
116
  test_time = end_time - start_time
64
- print(f'\rTest: epoch: {epoch} Accuracy: {acc:.5f} batch: {batch_idx+1}/{len(loader)} loss: {mean_loss:.5f} loss: {mean_loss:.5f} time {test_time:.5f}', end='\r', flush=True)
117
+ #print(f'\rTest: epoch: {epoch} Accuracy: {acc:.5f} batch: {batch_idx+1}/{len(loader)} loss: {mean_loss:.5f} loss: {mean_loss:.5f} time {test_time:.5f}', end='\r', flush=True)
118
+
65
119
  loss /= len(loader)
66
- data_df = classification_metrics(all_labels, prediction_pos_probs, loader_name, loss, epoch)
67
- return data_df, prediction_pos_probs, all_labels
68
-
69
- def evaluate_model_performance(loaders, model, loader_name_list, epoch, train_mode, loss_type):
70
- """
71
- Evaluate the performance of a model on given data loaders.
72
-
73
- Args:
74
- loaders (list): List of data loaders.
75
- model: The model to evaluate.
76
- loader_name_list (list): List of names for the data loaders.
77
- epoch (int): The current epoch.
78
- train_mode (str): The training mode ('erm' or 'irm').
79
- loss_type: The type of loss function.
80
-
81
- Returns:
82
- tuple: A tuple containing the evaluation result and the time taken for evaluation.
83
- """
84
- start_time = time.time()
85
- df_list = []
86
- if train_mode == 'erm':
87
- result, _, _ = evaluate_model_core(model, loaders, loader_name_list, epoch, loss_type)
88
- if train_mode == 'irm':
89
- for loader_index in range(0, len(loaders)):
90
- loader = loaders[loader_index]
91
- loader_name = loader_name_list[loader_index]
92
- data_df, _, _ = evaluate_model_core(model, loader, loader_name, epoch, loss_type)
93
- torch.cuda.empty_cache()
94
- df_list.append(data_df)
95
- result = pd.concat(df_list)
96
- nc_mean = result['neg_accuracy'].mean(skipna=True)
97
- pc_mean = result['pos_accuracy'].mean(skipna=True)
98
- tot_mean = result['accuracy'].mean(skipna=True)
99
- loss_mean = result['loss'].mean(skipna=True)
100
- prauc_mean = result['prauc'].mean(skipna=True)
101
- data_mean = {'accuracy': tot_mean, 'neg_accuracy': nc_mean, 'pos_accuracy': pc_mean, 'loss': loss_mean, 'prauc': prauc_mean}
102
- result = pd.concat([pd.DataFrame(result), pd.DataFrame(data_mean, index=[str(epoch)+'_mean'])])
103
- end_time = time.time()
104
- test_time = end_time - start_time
105
- return result, test_time
120
+ data_dict = classification_metrics(all_labels, prediction_pos_probs)
121
+ data_dict['loss'] = loss
122
+ data_dict['epoch'] = epoch
123
+ data_dict['Accuracy'] = acc
124
+
125
+ return data_dict, [prediction_pos_probs, all_labels]
106
126
 
107
127
  def test_model_core(model, loader, loader_name, epoch, loss_type):
108
128
 
@@ -145,7 +165,7 @@ def test_model_core(model, loader, loader_name, epoch, loss_type):
145
165
  acc = correct / total_samples
146
166
  end_time = time.time()
147
167
  test_time = end_time - start_time
148
- print(f'\rTest: epoch: {epoch} Accuracy: {acc:.5f} batch: {batch_idx}/{len(loader)} loss: {mean_loss:.5f} time {test_time:.5f}', end='\r', flush=True)
168
+ #print(f'\rTest: epoch: {epoch} Accuracy: {acc:.5f} batch: {batch_idx}/{len(loader)} loss: {mean_loss:.5f} time {test_time:.5f}', end='\r', flush=True)
149
169
 
150
170
  # Constructing the DataFrame
151
171
  results_df = pd.DataFrame({
@@ -158,7 +178,7 @@ def test_model_core(model, loader, loader_name, epoch, loss_type):
158
178
  data_df = classification_metrics(all_labels, prediction_pos_probs, loader_name, loss, epoch)
159
179
  return data_df, prediction_pos_probs, all_labels, results_df
160
180
 
161
- def test_model_performance(loaders, model, loader_name_list, epoch, train_mode, loss_type):
181
+ def test_model_performance(loaders, model, loader_name_list, epoch, loss_type):
162
182
  """
163
183
  Test the performance of a model on given data loaders.
164
184
 
@@ -167,7 +187,6 @@ def test_model_performance(loaders, model, loader_name_list, epoch, train_mode,
167
187
  model: The model to be tested.
168
188
  loader_name_list (list): List of names for the data loaders.
169
189
  epoch (int): The current epoch.
170
- train_mode (str): The training mode ('erm' or 'irm').
171
190
  loss_type: The type of loss function.
172
191
 
173
192
  Returns:
@@ -175,25 +194,9 @@ def test_model_performance(loaders, model, loader_name_list, epoch, train_mode,
175
194
  """
176
195
  start_time = time.time()
177
196
  df_list = []
178
- if train_mode == 'erm':
179
- result, prediction_pos_probs, all_labels, results_df = test_model_core(model, loaders, loader_name_list, epoch, loss_type)
180
- if train_mode == 'irm':
181
- for loader_index in range(0, len(loaders)):
182
- loader = loaders[loader_index]
183
- loader_name = loader_name_list[loader_index]
184
- data_df, prediction_pos_probs, all_labels, results_df = test_model_core(model, loader, loader_name, epoch, loss_type)
185
- torch.cuda.empty_cache()
186
- df_list.append(data_df)
187
- result = pd.concat(df_list)
188
- nc_mean = result['neg_accuracy'].mean(skipna=True)
189
- pc_mean = result['pos_accuracy'].mean(skipna=True)
190
- tot_mean = result['accuracy'].mean(skipna=True)
191
- loss_mean = result['loss'].mean(skipna=True)
192
- prauc_mean = result['prauc'].mean(skipna=True)
193
- data_mean = {'accuracy': tot_mean, 'neg_accuracy': nc_mean, 'pos_accuracy': pc_mean, 'loss': loss_mean, 'prauc': prauc_mean}
194
- result = pd.concat([pd.DataFrame(result), pd.DataFrame(data_mean, index=[str(epoch)+'_mean'])])
195
- end_time = time.time()
196
- test_time = end_time - start_time
197
+
198
+ result, prediction_pos_probs, all_labels, results_df = test_model_core(model, loaders, loader_name_list, epoch, loss_type)
199
+
197
200
  return result, results_df
198
201
 
199
202
  def train_test_model(settings):
@@ -201,14 +204,11 @@ def train_test_model(settings):
201
204
  from .io import _save_settings, _copy_missclassified
202
205
  from .utils import pick_best_model
203
206
  from .core import generate_loaders
204
- from .settings import set_default_train_test_model
205
207
 
206
208
  torch.cuda.empty_cache()
207
209
  torch.cuda.memory.empty_cache()
208
210
  gc.collect()
209
211
 
210
- settings = set_default_train_test_model(settings)
211
-
212
212
  src = settings['src']
213
213
 
214
214
  channels_str = ''.join(settings['train_channels'])
@@ -216,9 +216,6 @@ def train_test_model(settings):
216
216
  os.makedirs(dst, exist_ok=True)
217
217
  settings['src'] = src
218
218
  settings['dst'] = dst
219
- settings_df = pd.DataFrame(list(settings.items()), columns=['Key', 'Value'])
220
- settings_csv = os.path.join(dst,'train_test_model_settings.csv')
221
- settings_df.to_csv(settings_csv, index=False)
222
219
 
223
220
  if settings['custom_model']:
224
221
  model = torch.load(settings['custom_model_path'])
@@ -227,29 +224,27 @@ def train_test_model(settings):
227
224
  _save_settings(settings, src)
228
225
 
229
226
  if settings['train']:
230
- train, val, plate_names, train_fig = generate_loaders(src,
231
- train_mode=settings['train_mode'],
232
- mode='train',
233
- image_size=settings['image_size'],
234
- batch_size=settings['batch_size'],
235
- classes=settings['classes'],
236
- n_jobs=settings['n_jobs'],
237
- validation_split=settings['val_split'],
238
- pin_memory=settings['pin_memory'],
239
- normalize=settings['normalize'],
240
- channels=settings['train_channels'],
241
- augment=settings['augment'],
242
- verbose=settings['verbose'])
227
+ train, val, train_fig = generate_loaders(src,
228
+ mode='train',
229
+ image_size=settings['image_size'],
230
+ batch_size=settings['batch_size'],
231
+ classes=settings['classes'],
232
+ n_jobs=settings['n_jobs'],
233
+ validation_split=settings['val_split'],
234
+ pin_memory=settings['pin_memory'],
235
+ normalize=settings['normalize'],
236
+ channels=settings['train_channels'],
237
+ augment=settings['augment'],
238
+ preload_batches=settings['preload_batches'],
239
+ verbose=settings['verbose'])
243
240
 
244
- train_batch_1_figure = os.path.join(dst, 'batch_1.pdf')
245
- train_fig.savefig(train_batch_1_figure, format='pdf', dpi=600)
241
+ #train_batch_1_figure = os.path.join(dst, 'batch_1.pdf')
242
+ #train_fig.savefig(train_batch_1_figure, format='pdf', dpi=300)
246
243
 
247
244
  if settings['train']:
248
245
  model, model_path = train_model(dst = settings['dst'],
249
246
  model_type=settings['model_type'],
250
247
  train_loaders = train,
251
- train_loader_names = plate_names,
252
- train_mode = settings['train_mode'],
253
248
  epochs = settings['epochs'],
254
249
  learning_rate = settings['learning_rate'],
255
250
  init_weights = settings['init_weights'],
@@ -268,24 +263,20 @@ def train_test_model(settings):
268
263
  gradient_accumulation_steps=settings['gradient_accumulation_steps'],
269
264
  channels=settings['train_channels'])
270
265
 
271
- torch.cuda.empty_cache()
272
- torch.cuda.memory.empty_cache()
273
- gc.collect()
274
-
275
266
  if settings['test']:
276
267
  test, _, plate_names_test, train_fig = generate_loaders(src,
277
- train_mode=settings['train_mode'],
278
- mode='test',
279
- image_size=settings['image_size'],
280
- batch_size=settings['batch_size'],
281
- classes=settings['classes'],
282
- n_jobs=settings['n_jobs'],
283
- validation_split=0.0,
284
- pin_memory=settings['pin_memory'],
285
- normalize=settings['normalize'],
286
- channels=settings['train_channels'],
287
- augment=False,
288
- verbose=settings['verbose'])
268
+ mode='test',
269
+ image_size=settings['image_size'],
270
+ batch_size=settings['batch_size'],
271
+ classes=settings['classes'],
272
+ n_jobs=settings['n_jobs'],
273
+ validation_split=0.0,
274
+ pin_memory=settings['pin_memory'],
275
+ normalize=settings['normalize'],
276
+ channels=settings['train_channels'],
277
+ augment=False,
278
+ preload_batches=settings['preload_batches'],
279
+ verbose=settings['verbose'])
289
280
  if model == None:
290
281
  model_path = pick_best_model(src+'/model')
291
282
  print(f'Best model: {model_path}')
@@ -307,7 +298,6 @@ def train_test_model(settings):
307
298
  model=model,
308
299
  loader_name_list='test',
309
300
  epoch=1,
310
- train_mode=settings['train_mode'],
311
301
  loss_type=settings['loss_type'])
312
302
 
313
303
  result.to_csv(result_loc, index=True, header=True, mode='w')
@@ -320,7 +310,7 @@ def train_test_model(settings):
320
310
 
321
311
  return model_path
322
312
 
323
- def train_model(dst, model_type, train_loaders, train_loader_names, train_mode='erm', epochs=100, learning_rate=0.0001, weight_decay=0.05, amsgrad=False, optimizer_type='adamw', use_checkpoint=False, dropout_rate=0, n_jobs=20, val_loaders=None, test_loaders=None, init_weights='imagenet', intermedeate_save=None, chan_dict=None, schedule = None, loss_type='binary_cross_entropy_with_logits', gradient_accumulation=False, gradient_accumulation_steps=4, channels=['r','g','b']):
313
+ def train_model(dst, model_type, train_loaders, epochs=100, learning_rate=0.0001, weight_decay=0.05, amsgrad=False, optimizer_type='adamw', use_checkpoint=False, dropout_rate=0, n_jobs=20, val_loaders=None, test_loaders=None, init_weights='imagenet', intermedeate_save=None, chan_dict=None, schedule = None, loss_type='binary_cross_entropy_with_logits', gradient_accumulation=False, gradient_accumulation_steps=4, channels=['r','g','b'], verbose=False):
324
314
  """
325
315
  Trains a model using the specified parameters.
326
316
 
@@ -328,8 +318,6 @@ def train_model(dst, model_type, train_loaders, train_loader_names, train_mode='
328
318
  dst (str): The destination path to save the model and results.
329
319
  model_type (str): The type of model to train.
330
320
  train_loaders (list): A list of training data loaders.
331
- train_loader_names (list): A list of names for the training data loaders.
332
- train_mode (str, optional): The training mode. Defaults to 'erm'.
333
321
  epochs (int, optional): The number of training epochs. Defaults to 100.
334
322
  learning_rate (float, optional): The learning rate for the optimizer. Defaults to 0.0001.
335
323
  weight_decay (float, optional): The weight decay for the optimizer. Defaults to 0.05.
@@ -353,29 +341,35 @@ def train_model(dst, model_type, train_loaders, train_loader_names, train_mode='
353
341
  """
354
342
 
355
343
  from .io import _save_model, _save_progress
356
- from .utils import compute_irm_penalty, calculate_loss, choose_model, print_progress
344
+ from .utils import calculate_loss, choose_model
357
345
 
358
346
  print(f'Train batches:{len(train_loaders)}, Validation batches:{len(val_loaders)}')
359
347
 
360
348
  if test_loaders != None:
361
349
  print(f'Test batches:{len(test_loaders)}')
362
-
350
+
363
351
  use_cuda = torch.cuda.is_available()
364
352
  device = torch.device("cuda" if use_cuda else "cpu")
353
+
354
+ print(f'Using {device} for Torch')
355
+
365
356
  kwargs = {'n_jobs': n_jobs, 'pin_memory': True} if use_cuda else {}
366
357
 
367
- for idx, (images, labels, filenames) in enumerate(train_loaders):
368
- batch, chans, height, width = images.shape
369
- break
370
-
371
- model = choose_model(model_type, device, init_weights, dropout_rate, use_checkpoint)
358
+ #for idx, (images, labels, filenames) in enumerate(train_loaders):
359
+ # batch, chans, height, width = images.shape
360
+ # break
372
361
 
362
+
363
+ model = choose_model(model_type, device, init_weights, dropout_rate, use_checkpoint, verbose=verbose)
364
+
365
+
373
366
  if model is None:
374
367
  print(f'Model {model_type} not found')
375
368
  return
376
369
 
370
+ print(f'Loading Model to {device}...')
377
371
  model.to(device)
378
-
372
+
379
373
  if optimizer_type == 'adamw':
380
374
  optimizer = AdamW(model.parameters(), lr=learning_rate, betas=(0.9, 0.999), weight_decay=weight_decay, amsgrad=amsgrad)
381
375
 
@@ -392,169 +386,91 @@ def train_model(dst, model_type, train_loaders, train_loader_names, train_mode='
392
386
  scheduler = None
393
387
 
394
388
  time_ls = []
395
- if train_mode == 'erm':
396
- for epoch in range(1, epochs+1):
397
- model.train()
398
- start_time = time.time()
399
- running_loss = 0.0
400
389
 
401
- # Initialize gradients if using gradient accumulation
402
- if gradient_accumulation:
403
- optimizer.zero_grad()
390
+ # Initialize lists to accumulate results
391
+ accumulated_train_dicts = []
392
+ accumulated_val_dicts = []
393
+ accumulated_test_dicts = []
404
394
 
405
- for batch_idx, (data, target, filenames) in enumerate(train_loaders, start=1):
406
- data, target = data.to(device), target.to(device).float()
407
- output = model(data)
408
- loss = calculate_loss(output, target, loss_type=loss_type)
409
- # Normalize loss if using gradient accumulation
410
- if gradient_accumulation:
411
- loss /= gradient_accumulation_steps
412
- running_loss += loss.item() * gradient_accumulation_steps # correct the running_loss
413
- loss.backward()
414
-
415
- # Step optimizer if not using gradient accumulation or every gradient_accumulation_steps
416
- if not gradient_accumulation or (batch_idx % gradient_accumulation_steps == 0):
417
- optimizer.step()
418
- optimizer.zero_grad()
419
-
420
- avg_loss = running_loss / batch_idx
421
- #print(f'\rTrain: epoch: {epoch} batch: {batch_idx}/{len(train_loaders)} avg_loss: {avg_loss:.5f} time: {(time.time()-start_time):.5f}', end='\r', flush=True)
422
-
423
- batch_size = len(train_loaders)
424
- duration = time.time() - start_time
425
- time_ls.append(duration)
426
- metricks = f"Loss: {avg_loss:.5f}"
427
- print_progress(files_processed=epoch, files_to_process=epochs, n_jobs=1, time_ls=time_ls, batch_size=batch_size, operation_type=f"Training {model_type} model", metricks=metricks)
395
+ print(f'Training ...')
396
+ for epoch in range(1, epochs+1):
397
+ model.train()
398
+ start_time = time.time()
399
+ running_loss = 0.0
428
400
 
429
- end_time = time.time()
430
- train_time = end_time - start_time
431
- train_metrics = {'epoch':epoch,'loss':loss.cpu().item(), 'train_time':train_time}
432
- train_metrics_df = pd.DataFrame(train_metrics, index=[epoch])
433
- train_names = 'train'
434
- results_df, train_test_time = evaluate_model_performance(train_loaders, model, train_names, epoch, train_mode='erm', loss_type=loss_type)
435
- train_metrics_df['train_test_time'] = train_test_time
436
-
437
- if val_loaders != None:
438
- val_names = 'val'
439
- result, val_time = evaluate_model_performance(val_loaders, model, val_names, epoch, train_mode='erm', loss_type=loss_type)
440
-
441
- if schedule == 'reduce_lr_on_plateau':
442
- val_loss = result['loss']
443
-
444
- results_df = pd.concat([results_df, result])
445
- train_metrics_df['val_time'] = val_time
446
-
447
- if test_loaders != None:
448
- test_names = 'test'
449
- result, test_test_time = evaluate_model_performance(test_loaders, model, test_names, epoch, train_mode='erm', loss_type=loss_type)
450
- results_df = pd.concat([results_df, result])
451
- test_time = (train_test_time+val_time+test_test_time)/3
452
- train_metrics_df['test_time'] = test_time
453
-
454
- if scheduler:
455
- if schedule == 'reduce_lr_on_plateau':
456
- scheduler.step(val_loss)
457
- if schedule == 'step_lr':
458
- scheduler.step()
401
+ # Initialize gradients if using gradient accumulation
402
+ if gradient_accumulation:
403
+ optimizer.zero_grad()
404
+
405
+ for batch_idx, (data, target, filenames) in enumerate(train_loaders, start=1):
406
+ data, target = data.to(device), target.to(device).float()
407
+ output = model(data)
408
+ loss = calculate_loss(output, target, loss_type=loss_type)
459
409
 
460
- _save_progress(dst, results_df, train_metrics_df, epoch, epochs)
461
- #clear_output(wait=True)
462
- #display(results_df)
463
-
464
- train_idx = f"{epoch}_train"
465
- val_idx = f"{epoch}_val"
466
- train_acc = results_df.loc[train_idx, 'accuracy']
467
- neg_train_acc = results_df.loc[train_idx, 'neg_accuracy']
468
- pos_train_acc = results_df.loc[train_idx, 'pos_accuracy']
469
- val_acc = results_df.loc[val_idx, 'accuracy']
470
- neg_val_acc = results_df.loc[val_idx, 'neg_accuracy']
471
- pos_val_acc = results_df.loc[val_idx, 'pos_accuracy']
472
- train_loss = results_df.loc[train_idx, 'loss']
473
- train_prauc = results_df.loc[train_idx, 'prauc']
474
- val_loss = results_df.loc[val_idx, 'loss']
475
- val_prauc = results_df.loc[val_idx, 'prauc']
476
-
477
- metricks = f"Train Acc: {train_acc:.5f} Val Acc: {val_acc:.5f} Train Loss: {train_loss:.5f} Val Loss: {val_loss:.5f} Train PRAUC: {train_prauc:.5f} Val PRAUC: {val_prauc:.5f}, Nc Train Acc: {neg_train_acc:.5f} Nc Val Acc: {neg_val_acc:.5f} Pc Train Acc: {pos_train_acc:.5f} Pc Val Acc: {pos_val_acc:.5f}"
410
+ # Normalize loss if using gradient accumulation
411
+ if gradient_accumulation:
412
+ loss /= gradient_accumulation_steps
413
+ running_loss += loss.item() * gradient_accumulation_steps # correct the running_loss
414
+ loss.backward()
415
+
416
+ # Step optimizer if not using gradient accumulation or every gradient_accumulation_steps
417
+ if not gradient_accumulation or (batch_idx % gradient_accumulation_steps == 0):
418
+ optimizer.step()
419
+ optimizer.zero_grad()
478
420
 
421
+ avg_loss = running_loss / batch_idx
479
422
  batch_size = len(train_loaders)
480
423
  duration = time.time() - start_time
481
424
  time_ls.append(duration)
482
- print_progress(files_processed=epoch, files_to_process=epochs, n_jobs=1, time_ls=time_ls, batch_size=batch_size, operation_type=f"Training {model_type} model", metricks=metricks)
483
-
484
- model_path = _save_model(model, model_type, results_df, dst, epoch, epochs, intermedeate_save=[0.99,0.98,0.95,0.94], channels=channels)
485
-
486
- if train_mode == 'irm':
487
- dummy_w = torch.nn.Parameter(torch.Tensor([1.0])).to(device)
488
- phi = torch.nn.Parameter (torch.ones(4,1))
489
- for epoch in range(1, epochs):
490
- model.train()
491
- penalty_factor = epoch * 1e-5
492
- epoch_names = [str(epoch) + '_' + item for item in train_loader_names]
493
- loader_erm_loss_list = []
494
- total_erm_loss_mean = 0
495
- for loader_index in range(0, len(train_loaders)):
496
- start_time = time.time()
497
- loader = train_loaders[loader_index]
498
- loader_erm_loss_mean = 0
499
- batch_count = 0
500
- batch_erm_loss_list = []
501
- for batch_idx, (data, target, filenames) in enumerate(loader, start=1):
502
- optimizer.zero_grad()
503
- data, target = data.to(device), target.to(device).float()
504
-
505
- output = model(data)
506
- erm_loss = F.binary_cross_entropy_with_logits(output * dummy_w, target, reduction='none')
507
-
508
- batch_erm_loss_list.append(erm_loss.mean())
509
- print(f'\repoch: {epoch} loader: {loader_index} batch: {batch_idx+1}/{len(loader)}', end='\r', flush=True)
510
- loader_erm_loss_mean = torch.stack(batch_erm_loss_list).mean()
511
- loader_erm_loss_list.append(loader_erm_loss_mean)
512
- total_erm_loss_mean = torch.stack(loader_erm_loss_list).mean()
513
- irm_loss = compute_irm_penalty(loader_erm_loss_list, dummy_w, device)
425
+ #print(f'Progress: {batch_idx}/{batch_size}, operation_type: DL-Batch, Epoch {epoch}/{epochs}, Loss {avg_loss}, Time {duration}')
514
426
 
515
- (total_erm_loss_mean + penalty_factor * irm_loss).backward()
516
- optimizer.step()
517
-
518
- end_time = time.time()
519
- train_time = end_time - start_time
520
-
521
- train_metrics = {'epoch': epoch, 'irm_loss': irm_loss, 'erm_loss': total_erm_loss_mean, 'penalty_factor': penalty_factor, 'train_time': train_time}
522
- #train_metrics = {'epoch':epoch,'irm_loss':irm_loss.cpu().item(),'erm_loss':total_erm_loss_mean.cpu().item(),'penalty_factor':penalty_factor, 'train_time':train_time}
523
- train_metrics_df = pd.DataFrame(train_metrics, index=[epoch])
524
- print(f'\rTrain: epoch: {epoch} loader: {loader_index} batch: {batch_idx+1}/{len(loader)} irm_loss: {irm_loss:.5f} mean_erm_loss: {total_erm_loss_mean:.5f} train time {train_time:.5f}', end='\r', flush=True)
525
-
526
- train_names = [item + '_train' for item in train_loader_names]
527
- results_df, train_test_time = evaluate_model_performance(train_loaders, model, train_names, epoch, train_mode='irm', loss_type=loss_type)
528
- train_metrics_df['train_test_time'] = train_test_time
427
+ end_time = time.time()
428
+ train_time = end_time - start_time
429
+ train_dict, _ = evaluate_model_performance(model, train_loaders, epoch, loss_type=loss_type)
430
+ train_dict['train_time'] = train_time
431
+ accumulated_train_dicts.append(train_dict)
432
+
433
+ if val_loaders != None:
434
+ val_dict, _ = evaluate_model_performance(model, val_loaders, epoch, loss_type=loss_type)
435
+ accumulated_val_dicts.append(val_dict)
529
436
 
530
- if val_loaders != None:
531
- val_names = [item + '_val' for item in train_loader_names]
532
- result, val_time = evaluate_model_performance(val_loaders, model, val_names, epoch, train_mode='irm', loss_type=loss_type)
437
+ if schedule == 'reduce_lr_on_plateau':
438
+ val_loss = val_dict['loss']
439
+
440
+ print(f"Progress: {train_dict['epoch']}/{epochs}, operation_type: Training, Train Loss: {train_dict['loss']:.3f}, Val Loss: {val_dict['loss']:.3f}, Train acc.: {train_dict['accuracy']:.3f}, Val acc.: {val_dict['accuracy']:.3f}, Train NC acc.: {train_dict['neg_accuracy']:.3f}, Val NC acc.: {val_dict['neg_accuracy']:.3f}, Train PC acc.: {train_dict['pos_accuracy']:.3f}, Val PC acc.: {val_dict['pos_accuracy']:.3f}, Train PRAUC: {train_dict['prauc']:.3f}, Val PRAUC: {val_dict['prauc']:.3f}")
441
+
442
+ else:
443
+ print(f"Progress: {train_dict['epoch']}/{epochs}, operation_type: Training, Train Loss: {train_dict['loss']:.3f}, Train acc.: {train_dict['accuracy']:.3f}, Train NC acc.: {train_dict['neg_accuracy']:.3f}, Train PC acc.: {train_dict['pos_accuracy']:.3f}, Train PRAUC: {train_dict['prauc']:.3f}")
444
+ if test_loaders != None:
445
+ test_dict, _ = evaluate_model_performance(model, test_loaders, epoch, loss_type=loss_type)
446
+ accumulated_test_dicts.append(test_dict)
447
+ print(f"Progress: {test_dict['epoch']}/{epochs}, operation_type: Training, Train Loss: {test_dict['loss']:.3f}, Train acc.: {test_dict['accuracy']:.3f}, Train NC acc.: {test_dict['neg_accuracy']:.3f}, Train PC acc.: {test_dict['pos_accuracy']:.3f}, Train PRAUC: {test_dict['prauc']:.3f}")
448
+
449
+ if scheduler:
450
+ if schedule == 'reduce_lr_on_plateau':
451
+ scheduler.step(val_loss)
452
+ if schedule == 'step_lr':
453
+ scheduler.step()
454
+
455
+ if epoch % 10 == 0 or epoch == epochs:
456
+ if accumulated_train_dicts:
457
+ train_df = pd.DataFrame(accumulated_train_dicts)
458
+ _save_progress(dst, train_df, result_type='train')
533
459
 
534
- if schedule == 'reduce_lr_on_plateau':
535
- val_loss = result['loss']
460
+ if accumulated_val_dicts:
461
+ val_df = pd.DataFrame(accumulated_val_dicts)
462
+ _save_progress(dst, val_df,result_type='validation')
536
463
 
537
- results_df = pd.concat([results_df, result])
538
- train_metrics_df['val_time'] = val_time
539
-
540
- if test_loaders != None:
541
- test_names = [item + '_test' for item in train_loader_names] #test_loader_names?
542
- result, test_test_time = evaluate_model_performance(test_loaders, model, test_names, epoch, train_mode='irm', loss_type=loss_type)
543
- results_df = pd.concat([results_df, result])
544
- train_metrics_df['test_test_time'] = test_test_time
464
+ if accumulated_test_dicts:
465
+ val_df = pd.DataFrame(accumulated_test_dicts)
466
+ _save_progress(dst, val_df, result_type='test')
545
467
 
546
- if scheduler:
547
- if schedule == 'reduce_lr_on_plateau':
548
- scheduler.step(val_loss)
549
- if schedule == 'step_lr':
550
- scheduler.step()
468
+ batch_size = len(train_loaders)
469
+ duration = time.time() - start_time
470
+ time_ls.append(duration)
471
+
472
+ model_path = _save_model(model, model_type, train_dict, dst, epoch, epochs, intermedeate_save=[0.99,0.98,0.95,0.94], channels=channels)
551
473
 
552
- clear_output(wait=True)
553
- display(results_df)
554
- _save_progress(dst, results_df, train_metrics_df, epoch, epochs)
555
- model_path = _save_model(model, model_type, results_df, dst, epoch, epochs, intermedeate_save=[0.99,0.98,0.95,0.94])
556
- print(f'Saved model: {model_path}')
557
-
558
474
  return model, model_path
559
475
 
560
476
  def visualize_saliency_map(src, model_type='maxvit', model_path='', image_size=224, channels=[1,2,3], normalize=True, class_names=None, save_saliency=False, save_dir='saliency_maps'):
@@ -817,16 +733,19 @@ def visualize_smooth_grad(src, model_path, target_label_idx, image_size=224, cha
817
733
  def deep_spacr(settings={}):
818
734
  from .settings import deep_spacr_defaults
819
735
  from .core import generate_training_dataset, generate_dataset, apply_model_to_tar
736
+ from .utils import save_settings
820
737
 
821
738
  settings = deep_spacr_defaults(settings)
822
739
  src = settings['src']
740
+
741
+ save_settings(settings, name='DL_model')
823
742
 
824
743
  if settings['train'] or settings['test']:
825
744
  if settings['generate_training_dataset']:
826
745
  print(f"Generating train and test datasets ...")
827
746
  train_path, test_path = generate_training_dataset(settings)
828
747
  print(f'Generated Train set: {train_path}')
829
- print(f'Generated Train set: {test_path}')
748
+ print(f'Generated Test set: {test_path}')
830
749
  settings['src'] = os.path.dirname(train_path)
831
750
 
832
751
  if settings['train_DL_model']:
@@ -836,8 +755,8 @@ def deep_spacr(settings={}):
836
755
  settings['src'] = src
837
756
 
838
757
  if settings['apply_model_to_dataset']:
839
- if not os.path.exists(settings['tar_path']):
840
- print(f"Generating dataset ...")
758
+ if not settings['tar_path'] and os.path.isabs(settings['tar_path']) and os.path.exists(settings['tar_path']):
759
+ print(f"{settings['tar_path']} not found generating dataset ...")
841
760
  tar_path = generate_dataset(settings)
842
761
  settings['tar_path'] = tar_path
843
762