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/core.py +135 -472
- spacr/deep_spacr.py +189 -270
- spacr/gui_core.py +296 -87
- spacr/gui_elements.py +34 -81
- spacr/gui_utils.py +61 -47
- spacr/io.py +104 -41
- spacr/plot.py +47 -1
- spacr/settings.py +27 -31
- spacr/utils.py +14 -13
- {spacr-0.2.56.dist-info → spacr-0.2.61.dist-info}/METADATA +1 -1
- {spacr-0.2.56.dist-info → spacr-0.2.61.dist-info}/RECORD +15 -15
- {spacr-0.2.56.dist-info → spacr-0.2.61.dist-info}/LICENSE +0 -0
- {spacr-0.2.56.dist-info → spacr-0.2.61.dist-info}/WHEEL +0 -0
- {spacr-0.2.56.dist-info → spacr-0.2.61.dist-info}/entry_points.txt +0 -0
- {spacr-0.2.56.dist-info → spacr-0.2.61.dist-info}/top_level.txt +0 -0
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
|
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
|
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
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
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,
|
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
|
-
|
179
|
-
|
180
|
-
|
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,
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
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=
|
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
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
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,
|
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
|
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
|
-
|
369
|
-
|
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
|
-
|
402
|
-
|
403
|
-
|
390
|
+
# Initialize lists to accumulate results
|
391
|
+
accumulated_train_dicts = []
|
392
|
+
accumulated_val_dicts = []
|
393
|
+
accumulated_test_dicts = []
|
404
394
|
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
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
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
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
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
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
|
-
|
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
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
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
|
531
|
-
|
532
|
-
|
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
|
-
|
535
|
-
|
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
|
-
|
538
|
-
|
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
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
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
|
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"
|
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
|
|