Skip to content

Commit 3f3e645

Browse files
stmartineau99GOESTERN-1107078
andauthored
SSDA changes (#168)
* update domain_adaptation.py to use * formatting changes + arg added to supervised_learning.py * respond to PR revssda iew comments --------- Co-authored-by: GOESTERN-1107078 <u25914@glogin10.usr.hpc.gwdg.de>
1 parent 4a45fcc commit 3f3e645

3 files changed

Lines changed: 41 additions & 19 deletions

File tree

synapse_net/training/domain_adaptation.py

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@
1818
from ..inference.inference import get_model_path, compute_scale_from_voxel_size, get_available_models
1919
from ..inference.util import _Scaler
2020

21+
# configure weak augmentations
22+
from torch_em.transform.invertible_augmentations import DEFAULT_WEAK_AUGMENTATIONS
23+
24+
# TODO - test settings - fixed kernel size for `RandomGaussianBlur`, fixed std for `RandomGaussianBlur`
25+
DEFAULT_WEAK_AUGMENTATIONS["intensity"] = {
26+
"RandomGaussianBlur": {"kernel_size": (19, 19), "sigma": (0.1, 3.0)},
27+
"RandomGaussianNoise": {"mean": (0.0), "std": (0.1)},
28+
}
2129

2230
def mean_teacher_adaptation(
2331
name: str,
@@ -40,7 +48,8 @@ def mean_teacher_adaptation(
4048
train_mask_paths: Optional[Tuple[str]] = None,
4149
val_mask_paths: Optional[Tuple[str]] = None,
4250
sample_mask_key: Optional[str] = None,
43-
patch_sampler: Optional[callable] = None,
51+
unsupervised_sampler: Optional[callable] = None,
52+
supervised_sampler: Optional[callable] = None,
4453
check: bool = False,
4554
) -> None:
4655
"""Run domain adaptation to transfer a network trained on a source domain for a supervised
@@ -86,10 +95,12 @@ def mean_teacher_adaptation(
8695
based on the patch_shape and size of the volumes used for training.
8796
n_samples_val: The number of val samples per epoch. By default this will be estimated
8897
based on the patch_shape and size of the volumes used for validation.
89-
train_mask_paths: Sample masks used by the patch sampler to accept or reject patches for training.
90-
val_mask_paths: Sample masks used by the patch sampler to accept or reject patches for validation.
98+
train_mask_paths: Sample masks used by the unsupervised sampler to accept or reject patches for training.
99+
val_mask_paths: Sample masks used by the unsupervised sampler to accept or reject patches for validation.
91100
sample_mask_key: The key to the sample mask dataset inside each file.
92-
patch_sampler: Accept or reject patches based on a condition.
101+
unsupervised_sampler: Sampler to accept or reject patches for the unsupervised data stream.
102+
supervised_sampler: Sampler to accept or reject patches for the supervised data stream.
103+
Pass `False` to disable.
93104
check: Whether to check the training and validation loaders instead of running training.
94105
""" # noqa
95106
assert (supervised_train_paths is None) == (supervised_val_paths is None)
@@ -118,8 +129,11 @@ def mean_teacher_adaptation(
118129

119130
# self training functionality
120131
pseudo_labeler = self_training.DefaultPseudoLabeler(confidence_threshold=confidence_threshold)
121-
loss = self_training.DefaultSelfTrainingLoss()
122-
loss_and_metric = self_training.DefaultSelfTrainingLossAndMetric()
132+
loss = self_training.SelfTrainingLossWithInvertibleAugmentations()
133+
loss_and_metric = self_training.SelfTrainingLossAndMetricWithInvertibleAugmentations()
134+
135+
ndim = 2 if is_2d else 3
136+
augmenters = torch_em.transform.invertible_augmentations.MeanTeacherAugmenters(ndim=ndim)
123137

124138
unsupervised_train_loader = get_unsupervised_loader(
125139
data_paths=unsupervised_train_paths,
@@ -129,7 +143,7 @@ def mean_teacher_adaptation(
129143
n_samples=n_samples_train,
130144
sample_mask_paths=train_mask_paths,
131145
sample_mask_key=sample_mask_key,
132-
sampler=patch_sampler,
146+
sampler=unsupervised_sampler,
133147
)
134148
unsupervised_val_loader = get_unsupervised_loader(
135149
data_paths=unsupervised_val_paths,
@@ -139,18 +153,20 @@ def mean_teacher_adaptation(
139153
n_samples=n_samples_val,
140154
sample_mask_paths=val_mask_paths,
141155
sample_mask_key=sample_mask_key,
142-
sampler=patch_sampler,
156+
sampler=unsupervised_sampler,
143157
)
144158

145159
if supervised_train_paths is not None:
146160
assert label_key is not None
147161
supervised_train_loader = get_supervised_loader(
148162
supervised_train_paths, raw_key_supervised, label_key,
149163
patch_shape, batch_size, n_samples=n_samples_train,
164+
sampler=supervised_sampler,
150165
)
151166
supervised_val_loader = get_supervised_loader(
152167
supervised_val_paths, raw_key_supervised, label_key,
153168
patch_shape, batch_size, n_samples=n_samples_val,
169+
sampler=supervised_sampler,
154170
)
155171
else:
156172
supervised_train_loader = None
@@ -166,7 +182,7 @@ def mean_teacher_adaptation(
166182
return
167183

168184
device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
169-
trainer = self_training.MeanTeacherTrainer(
185+
trainer = self_training.MeanTeacherTrainerWithInvertibleAugmentations(
170186
name=name,
171187
model=model,
172188
optimizer=optimizer,
@@ -187,6 +203,7 @@ def mean_teacher_adaptation(
187203
device=device,
188204
reinit_teacher=reinit_teacher,
189205
save_root=save_root,
206+
augmenter=augmenters,
190207
)
191208
trainer.fit(n_iterations)
192209

synapse_net/training/semisupervised_training.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def get_unsupervised_loader(
5757
sample_mask_key: The key to the sample mask dataset inside each file.
5858
bg_mask_paths: The filepaths to the background masks for each tomogram.
5959
bg_mask_key: The key to the background mask dataset inside each file.
60-
sampler: Accept or reject patches based on a condition.
60+
sampler: Optional sampler to accept or reject patches for training.
6161
exclude_top_and_bottom: Whether to exclude the five top and bottom slices to
6262
avoid artifacts at the border of tomograms.
6363
@@ -79,7 +79,7 @@ def get_unsupervised_loader(
7979
_, ndim = _determine_ndim(patch_shape)
8080
raw_transform = torch_em.transform.get_raw_transform()
8181
transform = torch_em.transform.get_augmentations(ndim=ndim)
82-
augmentations = (weak_augmentations(), weak_augmentations())
82+
# augmentations = (weak_augmentations(), weak_augmentations())
8383

8484
if n_samples is None:
8585
n_samples_per_ds = None
@@ -97,7 +97,7 @@ def get_unsupervised_loader(
9797
n_samples=n_samples_per_ds,
9898
sampler=sampler,
9999
ndim=ndim,
100-
augmentations=augmentations,
100+
augmentations=None,
101101
sample_mask_path=sample_mask_paths[i] if sample_mask_paths is not None else None,
102102
sample_mask_key=sample_mask_key,
103103
bg_mask_path=bg_mask_paths[i] if bg_mask_paths is not None else None,

synapse_net/training/supervised_training.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import os
22
from glob import glob
3-
from typing import Optional, Tuple
3+
from typing import Optional, Tuple, Union
44

55
import torch
66
import torch_em
@@ -97,7 +97,7 @@ def get_supervised_loader(
9797
add_boundary_transform: bool = True,
9898
label_dtype=torch.float32,
9999
rois: Optional[Tuple[Tuple[slice]]] = None,
100-
sampler: Optional[callable] = None,
100+
sampler: Optional[Union[callable, bool]] = None,
101101
ignore_label: Optional[int] = None,
102102
label_transform: Optional[callable] = None,
103103
label_paths: Optional[Tuple[str]] = None,
@@ -118,8 +118,8 @@ def get_supervised_loader(
118118
add_boundary_transform: Whether to add a boundary channel to the training data.
119119
label_dtype: The datatype of the labels returned by the dataloader.
120120
rois: Optional region of interests for training.
121-
sampler: Optional sampler for selecting blocks for training.
122-
By default a minimum instance sampler will be used.
121+
sampler: Optional sampler to accept or reject patches for training.
122+
By default a minimum instance sampler will be used, pass `False` to disable.
123123
ignore_label: Ignore label in the ground-truth. The areas marked by this label will be
124124
ignored in the loss computation. By default this option is not used.
125125
label_transform: Label transform that is applied to the segmentation to compute the targets.
@@ -162,6 +162,8 @@ def get_supervised_loader(
162162

163163
if sampler is None:
164164
sampler = torch_em.data.sampler.MinInstanceSampler(min_num_instances=4)
165+
elif sampler is False:
166+
sampler = None
165167

166168
if label_paths is None:
167169
label_paths = data_paths
@@ -194,7 +196,7 @@ def supervised_training(
194196
val_label_paths: Optional[Tuple[str]] = None,
195197
train_rois: Optional[Tuple[Tuple[slice]]] = None,
196198
val_rois: Optional[Tuple[Tuple[slice]]] = None,
197-
sampler: Optional[callable] = None,
199+
sampler: Optional[Union[callable, bool]] = None,
198200
n_samples_train: Optional[int] = None,
199201
n_samples_val: Optional[int] = None,
200202
check: bool = False,
@@ -205,6 +207,7 @@ def supervised_training(
205207
out_channels: int = 2,
206208
mask_channel: bool = False,
207209
checkpoint_path: Optional[str] = None,
210+
save_every_kth_epoch: Optional[int] = None,
208211
**loader_kwargs,
209212
):
210213
"""Run supervised segmentation training.
@@ -233,7 +236,7 @@ def supervised_training(
233236
If not given, the labels are expected to be part of `val_paths`.
234237
train_rois: Optional region of interests for training.
235238
val_rois: Optional region of interests for validation.
236-
sampler: Optional sampler for selecting blocks for training.
239+
sampler: Optional sampler for selecting patches for training.
237240
By default a minimum instance sampler will be used.
238241
n_samples_train: The number of train samples per epoch. By default this will be estimated
239242
based on the patch_shape and size of the volumes used for training.
@@ -249,6 +252,8 @@ def supervised_training(
249252
mask_channel: Whether the last channels in the labels should be used for masking the loss.
250253
This can be used to implement more complex masking operations and is not compatible with `ignore_label`.
251254
checkpoint_path: Path to the directory where 'best.pt' resides; continue training this model.
255+
save_every_kth_epoch: Save checkpoints after every kth epoch in a separate file.
256+
The corresponding checkpoints will be saved with the naming scheme 'epoch-{epoch}.pt'.
252257
loader_kwargs: Additional keyword arguments for the dataloader.
253258
"""
254259
train_loader = get_supervised_loader(train_paths, raw_key, label_key, patch_shape, batch_size,
@@ -317,7 +322,7 @@ def supervised_training(
317322
loss=loss,
318323
metric=metric,
319324
)
320-
trainer.fit(n_iterations)
325+
trainer.fit(n_iterations, save_every_kth_epoch=save_every_kth_epoch)
321326

322327

323328
def _derive_key_from_files(files, key):

0 commit comments

Comments
 (0)