Title : Denoising diffusion weighted imaging data using CNN#
Obtaining tissue microstructure measurements from diffusion weighted imaging
(DWI) with multiple, high b-values is crucial. However, the high noise levels
present in these images can adversely affect the accuracy of the
microstructural measurements. In this context, we suggest a straightforward
denoising technique that can be applied to any DWI dataset as long as a
low-noise, single-subject dataset is obtained using the same DWI sequence.
We created a simple 1D-CNN model with five layers, based on the 1D CNN for
denoising speech. The model consists of two convolutional layers followed by
max-pooling layers, and a dense layer. The first convolutional layer has
16 one-dimensional filters of size 16, and the second layer has 32 filters of
size 8. ReLu activation function is applied to both convolutional layers.
The max-pooling layer has a kernel size of 2 and a stride of 2.
The dense layer maps the features extracted from the noisy image to the
low-noise reference image.
Cheng H, Vinci-Booher S, Wang J, Caron B, Wen Q, Newman S, et al.
(2022) Denoising diffusion weighted imaging data using convolutional neural
networks.
PLoS ONE 17(9): e0274396. https://doi.org/10.1371/journal.pone.0274396
Name of the optimization algorithm to use. Options: ‘adam’, ‘sgd’,
‘rmsprop’, ‘adagrad’, ‘adadelta’.
lossstr, optional
Name of the loss function to use. Available options are
‘mean_squared_error’, ‘mean_absolute_error’,
‘mean_absolute_percentage_error’, ‘mean_squared_logarithmic_error’,
‘squared_hinge’, ‘hinge’, ‘categorical_hinge’, ‘logcosh’,
‘categorical_crossentropy’, ‘sparse_categorical_crossentropy’,
‘binary_crossentropy’, ‘kullback_leibler_divergence’, ‘poisson’,
‘cosine_similarity’.
Suggested to go with ‘mean_squared_error’.
metricstuple of str or function, optional
List of metrics to be evaluated by the model during training and
testing. Available options are ‘accuracy’, ‘binary_accuracy’,
‘categorical_accuracy’, ‘top_k_categorical_accuracy’,
‘sparse_categorical_accuracy’, ‘sparse_top_k_categorical_accuracy’,
and any custom function.
loss_weightsfloat or dict, optional
Scalar coefficients to weight the loss contributions of different
model outputs. Can be a single float value or a dictionary mapping
output names to scalar coefficients.
Name of objective function or objective function itself.
If ‘None’, the model will be compiled without any loss function
and can only be used to predict output.
metricslist of metrics, optional
List of metrics to be evaluated by the model during training
and testing.
loss_weightslist or dict, optional
Optional list or dictionary specifying scalar coefficients(floats)
to weight the loss contributions of different model outputs.
The loss value that will be minimized by the model will then be
the weighted sum of all individual losses. If a list, it is
expected to have a 1:1 mapping to the model’s outputs. If a dict,
it is expected to map output names (strings) to scalar
coefficients.
evaluate(x, y, batch_size=None, verbose=1, steps=None, callbacks=None, max_queue_size=10, workers=1, use_multiprocessing=False, return_dict=False)#
If return_dict is False, returns a list of [loss, metrics]
values on the test dataset. If return_dict is True, returns
a dictionary of metric names and their corresponding values.
Verbosity mode. 0 = silent, 1 = progress bar, 2 = one line
per epoch.
callbackslist of keras.callbacks.Callback instances, optional
List of callbacks to apply during training.
validation_splitfloat between 0 and 1, optional
Fraction of the training data to be used as validation data.
validation_datatuple (x_val, y_val) or None, optional
Data on which to evaluate the loss and any model metrics at
the end of each epoch.
shuffleboolean, optional
This argument is ignored when x is a generator or an object of
tf.data.Dataset.
initial_epochint, optional
Epoch at which to start training.
steps_per_epochint or None, optional
Total number of steps (batches of samples) before declaring one
epoch finished and starting the next epoch.
validation_batch_sizeint or None, optional
Number of samples per validation batch.
validation_stepsint or None, optional
Only relevant if validation_data is provided and is a
tf.data dataset.
validation_freqint or list/tuple/set, optional
Only relevant if validation data is provided. If an integer,
specifies how many training epochs to run before a new validation
run is performed. If a list, tuple, or set, specifies the epochs
on which to run validation.
max_queue_sizeint, optional
Used for generator or keras.utils.Sequence input only.
workersinteger, optional
Used for generator or keras.utils.Sequence input only.
use_multiprocessingboolean, optional
Used for generator or keras.utils.Sequence input only.
If float, should be between 0.0 and 1.0 and represent the
proportion of the dataset to include in the test split.
If int, represents the absolute number of test samples.
If None, the value is set to the complement of the train size.
If train_size is also None, it will be set to 0.25.
train_size: float or int, optional
If float, should be between 0.0 and 1.0 and represent the
proportion of the dataset to include in the train split.
If int, represents the absolute number of train samples.
If None, the value is automatically set to the complement of the
test size.
random_state: int, RandomState instance or None, optional
Controls the shuffling applied to the data before applying
the split. Pass an int for reproducible output across multiple
function calls. See Glossary.
shuffle: bool, optional
Whether or not to shuffle the data before splitting.
If shuffle=False then stratify must be None.
stratify: array-like, optional
If not None, data is split in a stratified fashion,
using this as the class labels. Read more in the User Guide.
The call() method may not create state (except in its first
invocation, wrapping the creation of variables or other resources in
tf.init_scope()). It is recommended to create state, including
tf.Variable instances and nested Layer instances,
in __init__(), or in the build() method that is
called automatically before call() executes for the first time.
Args:
inputs: Input tensor, or dict/list/tuple of input tensors.
The first positional inputs argument is subject to special rules:
- inputs must be explicitly passed. A layer cannot have zero
arguments, and inputs cannot be provided via the default value
of a keyword argument.
NumPy array or Python scalar values in inputs get cast as
tensors.
Keras mask metadata is only collected from inputs.
Layers are built (build(input_shape) method)
using shape info from inputs only.
input_spec compatibility is only checked against inputs.
Mixed precision input casting is only applied to inputs.
If a layer has tensor arguments in *args or **kwargs, their
casting behavior in mixed precision should be handled manually.
The SavedModel input specification is generated using inputs
only.
Integration with various ecosystem packages like TFMOT, TFLite,
TF.js, etc is only supported for inputs and not for tensors in
positional and keyword arguments.
*args: Additional positional arguments. May contain tensors, although
this is not recommended, for the reasons above.
**kwargs: Additional keyword arguments. May contain tensors, although
this is not recommended, for the reasons above.
The following optional keyword arguments are reserved:
- training: Boolean scalar tensor of Python boolean indicating
whether the call is meant for training or inference.
mask: Boolean input mask. If the layer’s call() method takes a
mask argument, its default value will be set to the mask
generated for inputs by the previous layer (if input did come
from a layer that generated a corresponding mask, i.e. if it came
from a Keras layer with masking support).
The call() method may not create state (except in its first
invocation, wrapping the creation of variables or other resources in
tf.init_scope()). It is recommended to create state, including
tf.Variable instances and nested Layer instances,
in __init__(), or in the build() method that is
called automatically before call() executes for the first time.
Args:
inputs: Input tensor, or dict/list/tuple of input tensors.
The first positional inputs argument is subject to special rules:
- inputs must be explicitly passed. A layer cannot have zero
arguments, and inputs cannot be provided via the default value
of a keyword argument.
NumPy array or Python scalar values in inputs get cast as
tensors.
Keras mask metadata is only collected from inputs.
Layers are built (build(input_shape) method)
using shape info from inputs only.
input_spec compatibility is only checked against inputs.
Mixed precision input casting is only applied to inputs.
If a layer has tensor arguments in *args or **kwargs, their
casting behavior in mixed precision should be handled manually.
The SavedModel input specification is generated using inputs
only.
Integration with various ecosystem packages like TFMOT, TFLite,
TF.js, etc is only supported for inputs and not for tensors in
positional and keyword arguments.
*args: Additional positional arguments. May contain tensors, although
this is not recommended, for the reasons above.
**kwargs: Additional keyword arguments. May contain tensors, although
this is not recommended, for the reasons above.
The following optional keyword arguments are reserved:
- training: Boolean scalar tensor of Python boolean indicating
whether the call is meant for training or inference.
mask: Boolean input mask. If the layer’s call() method takes a
mask argument, its default value will be set to the mask
generated for inputs by the previous layer (if input did come
from a layer that generated a corresponding mask, i.e. if it came
from a Keras layer with masking support).
Kanakaraj, P., Yao, T., Cai, L. Y., Lee, H. H., Newlin, N. R.,
Kim, M. E., & Moyer, D. (2023). DeepN4: Learning N4ITK Bias Field
Correction for T1-weighted Images.
Instances of the Logger class represent a single logging channel. A
“logging channel” indicates an area of an application. Exactly how an
“area” is defined is up to the application developer. Since an
application can have any number of areas, logging channels are identified
by a unique string. Application areas can be nested (e.g. an area
of “input processing” might include sub-areas “read CSV files”, “read
XLS files” and “read Gnumeric files”). To cater for this natural nesting,
channel names are organized into a namespace hierarchy where levels are
separated by periods, much like the Java or Python package namespace. So
in the instance given above, channel names might be “input” for the upper
level, and “input.csv”, “input.xls” and “input.gnu” for the sub-levels.
There is no arbitrary limit to the depth of nesting.
The call() method may not create state (except in its first
invocation, wrapping the creation of variables or other resources in
tf.init_scope()). It is recommended to create state, including
tf.Variable instances and nested Layer instances,
in __init__(), or in the build() method that is
called automatically before call() executes for the first time.
Args:
inputs: Input tensor, or dict/list/tuple of input tensors.
The first positional inputs argument is subject to special rules:
- inputs must be explicitly passed. A layer cannot have zero
arguments, and inputs cannot be provided via the default value
of a keyword argument.
NumPy array or Python scalar values in inputs get cast as
tensors.
Keras mask metadata is only collected from inputs.
Layers are built (build(input_shape) method)
using shape info from inputs only.
input_spec compatibility is only checked against inputs.
Mixed precision input casting is only applied to inputs.
If a layer has tensor arguments in *args or **kwargs, their
casting behavior in mixed precision should be handled manually.
The SavedModel input specification is generated using inputs
only.
Integration with various ecosystem packages like TFMOT, TFLite,
TF.js, etc is only supported for inputs and not for tensors in
positional and keyword arguments.
*args: Additional positional arguments. May contain tensors, although
this is not recommended, for the reasons above.
**kwargs: Additional keyword arguments. May contain tensors, although
this is not recommended, for the reasons above.
The following optional keyword arguments are reserved:
- training: Boolean scalar tensor of Python boolean indicating
whether the call is meant for training or inference.
mask: Boolean input mask. If the layer’s call() method takes a
mask argument, its default value will be set to the mask
generated for inputs by the previous layer (if input did come
from a layer that generated a corresponding mask, i.e. if it came
from a Keras layer with masking support).
The call() method may not create state (except in its first
invocation, wrapping the creation of variables or other resources in
tf.init_scope()). It is recommended to create state, including
tf.Variable instances and nested Layer instances,
in __init__(), or in the build() method that is
called automatically before call() executes for the first time.
Args:
inputs: Input tensor, or dict/list/tuple of input tensors.
The first positional inputs argument is subject to special rules:
- inputs must be explicitly passed. A layer cannot have zero
arguments, and inputs cannot be provided via the default value
of a keyword argument.
NumPy array or Python scalar values in inputs get cast as
tensors.
Keras mask metadata is only collected from inputs.
Layers are built (build(input_shape) method)
using shape info from inputs only.
input_spec compatibility is only checked against inputs.
Mixed precision input casting is only applied to inputs.
If a layer has tensor arguments in *args or **kwargs, their
casting behavior in mixed precision should be handled manually.
The SavedModel input specification is generated using inputs
only.
Integration with various ecosystem packages like TFMOT, TFLite,
TF.js, etc is only supported for inputs and not for tensors in
positional and keyword arguments.
*args: Additional positional arguments. May contain tensors, although
this is not recommended, for the reasons above.
**kwargs: Additional keyword arguments. May contain tensors, although
this is not recommended, for the reasons above.
The following optional keyword arguments are reserved:
- training: Boolean scalar tensor of Python boolean indicating
whether the call is meant for training or inference.
mask: Boolean input mask. If the layer’s call() method takes a
mask argument, its default value will be set to the mask
generated for inputs by the previous layer (if input did come
from a layer that generated a corresponding mask, i.e. if it came
from a Keras layer with masking support).
Load the model pre-training weights to use for the fitting.
While the user can load different weights, the function
is mainly intended for the class function ‘predict’.
For a single image, input should be a 3D array.
If multiple images, it should be a a list or tuple.
affinenp.ndarray (4, 4) or (batch, 4, 4)
or list of np.ndarrays with len of batch
Affine matrix for the T1 image. Should have
batch dimension if T1 has one.
voxsizenp.ndarray or list or tuple, optional
(3,) or (batch, 3)
voxel size of the T1 image.
Default is (1, 1, 1)
batch_sizeint, optional
Number of images per prediction pass. Only available if data
is provided with a batch dimension.
Consider lowering it if you get an out of memory error.
Increase it if you want it to be faster and have a lot of data.
If None, batch_size will be set to 1 if the provided image
has a batch dimension.
Default is None
return_affinebool, optional
Whether to return the affine matrix. Useful if the input was a
file path.
Default is False
return_probbool, optional
Whether to return the probability map instead of a
binary mask. Useful for testing.
Default is False
largest_areabool, optional
Whether to exclude only the largest background/foreground.
Useful for solving minor errors.
Default is True
Instances of the Logger class represent a single logging channel. A
“logging channel” indicates an area of an application. Exactly how an
“area” is defined is up to the application developer. Since an
application can have any number of areas, logging channels are identified
by a unique string. Application areas can be nested (e.g. an area
of “input processing” might include sub-areas “read CSV files”, “read
XLS files” and “read Gnumeric files”). To cater for this natural nesting,
channel names are organized into a namespace hierarchy where levels are
separated by periods, much like the Java or Python package namespace. So
in the instance given above, channel names might be “input” for the upper
level, and “input.csv”, “input.xls” and “input.gnu” for the sub-levels.
There is no arbitrary limit to the depth of nesting.
The model was re-trained for usage with a different basis function
(‘tournier07’) like the proposed model in [1, 2].
To obtain the pre-trained model, use::
>>> resdnn_model = HistoResDNN()
>>> fetch_model_weights_path = get_fnames(‘histo_resdnn_weights’)
>>> resdnn_model.load_model_weights(fetch_model_weights_path)
This model is designed to take as input raw DWI signal on a sphere
(ODF) represented as SH of order 8 in the tournier basis and predict
fODF of order 8 in the tournier basis. Effectively, this model is
mimicking a CSD fit.
Maximum SH order (l) in the SH fit. For sh_order_max, there
will be
(sh_order_max+1)*(sh_order_max+2)/2 SH coefficients
for a symmetric basis. Default: 8
The acquisition scheme matching the data (must contain at least
one b0)
masknp.ndarray (optional)
Binary mask of the brain to avoid unnecessary computation and
unreliable prediction outside the brain.
Default: Compute prediction only for nonzero voxels (with at least
one nonzero DWI value).
Instances of the Logger class represent a single logging channel. A
“logging channel” indicates an area of an application. Exactly how an
“area” is defined is up to the application developer. Since an
application can have any number of areas, logging channels are identified
by a unique string. Application areas can be nested (e.g. an area
of “input processing” might include sub-areas “read CSV files”, “read
XLS files” and “read Gnumeric files”). To cater for this natural nesting,
channel names are organized into a namespace hierarchy where levels are
separated by periods, much like the Java or Python package namespace. So
in the instance given above, channel names might be “input” for the upper
level, and “input.csv”, “input.xls” and “input.gnu” for the sub-levels.
There is no arbitrary limit to the depth of nesting.
The call() method may not create state (except in its first
invocation, wrapping the creation of variables or other resources in
tf.init_scope()). It is recommended to create state, including
tf.Variable instances and nested Layer instances,
in __init__(), or in the build() method that is
called automatically before call() executes for the first time.
Args:
inputs: Input tensor, or dict/list/tuple of input tensors.
The first positional inputs argument is subject to special rules:
- inputs must be explicitly passed. A layer cannot have zero
arguments, and inputs cannot be provided via the default value
of a keyword argument.
NumPy array or Python scalar values in inputs get cast as
tensors.
Keras mask metadata is only collected from inputs.
Layers are built (build(input_shape) method)
using shape info from inputs only.
input_spec compatibility is only checked against inputs.
Mixed precision input casting is only applied to inputs.
If a layer has tensor arguments in *args or **kwargs, their
casting behavior in mixed precision should be handled manually.
The SavedModel input specification is generated using inputs
only.
Integration with various ecosystem packages like TFMOT, TFLite,
TF.js, etc is only supported for inputs and not for tensors in
positional and keyword arguments.
*args: Additional positional arguments. May contain tensors, although
this is not recommended, for the reasons above.
**kwargs: Additional keyword arguments. May contain tensors, although
this is not recommended, for the reasons above.
The following optional keyword arguments are reserved:
- training: Boolean scalar tensor of Python boolean indicating
whether the call is meant for training or inference.
mask: Boolean input mask. If the layer’s call() method takes a
mask argument, its default value will be set to the mask
generated for inputs by the previous layer (if input did come
from a layer that generated a corresponding mask, i.e. if it came
from a Keras layer with masking support).
The call() method may not create state (except in its first
invocation, wrapping the creation of variables or other resources in
tf.init_scope()). It is recommended to create state, including
tf.Variable instances and nested Layer instances,
in __init__(), or in the build() method that is
called automatically before call() executes for the first time.
Args:
inputs: Input tensor, or dict/list/tuple of input tensors.
The first positional inputs argument is subject to special rules:
- inputs must be explicitly passed. A layer cannot have zero
arguments, and inputs cannot be provided via the default value
of a keyword argument.
NumPy array or Python scalar values in inputs get cast as
tensors.
Keras mask metadata is only collected from inputs.
Layers are built (build(input_shape) method)
using shape info from inputs only.
input_spec compatibility is only checked against inputs.
Mixed precision input casting is only applied to inputs.
If a layer has tensor arguments in *args or **kwargs, their
casting behavior in mixed precision should be handled manually.
The SavedModel input specification is generated using inputs
only.
Integration with various ecosystem packages like TFMOT, TFLite,
TF.js, etc is only supported for inputs and not for tensors in
positional and keyword arguments.
*args: Additional positional arguments. May contain tensors, although
this is not recommended, for the reasons above.
**kwargs: Additional keyword arguments. May contain tensors, although
this is not recommended, for the reasons above.
The following optional keyword arguments are reserved:
- training: Boolean scalar tensor of Python boolean indicating
whether the call is meant for training or inference.
mask: Boolean input mask. If the layer’s call() method takes a
mask argument, its default value will be set to the mask
generated for inputs by the previous layer (if input did come
from a layer that generated a corresponding mask, i.e. if it came
from a Keras layer with masking support).
This class is intended for the Synb0 model.
The model is the deep learning part of the Synb0-Disco
pipeline, thus stand-alone usage is not
recommended.
The model was pre-trained for usage on pre-processed images
following the synb0-disco pipeline.
One can load their own weights using load_model_weights.
This model is designed to take as input
a b0 image and a T1 weighted image.
Load the model pre-training weights to use for the fitting.
While the user can load different weights, the function
is mainly intended for the class function ‘predict’.
Wrapper function to facilitate prediction of larger dataset.
The function will pad the data to meet the required shape of image.
Note that the b0 and T1 image should have the same shape
For a single image, input should be a 3D array. If multiple images,
there should also be a batch dimension.
T1np.ndarray (batch, 77, 91, 77) or (77, 91, 77)
For a single image, input should be a 3D array. If multiple images,
there should also be a batch dimension.
batch_sizeint
Number of images per prediction pass. Only available if data
is provided with a batch dimension.
Consider lowering it if you get an out of memory error.
Increase it if you want it to be faster and have a lot of data.
If None, batch_size will be set to 1 if the provided image
has a batch dimension.
Default is None
averagebool
Whether the function follows the Synb0-Disco pipeline and
averages the prediction of 5 different models.
If False, it uses the loaded weights for prediction.
Default is True.
Instances of the Logger class represent a single logging channel. A
“logging channel” indicates an area of an application. Exactly how an
“area” is defined is up to the application developer. Since an
application can have any number of areas, logging channels are identified
by a unique string. Application areas can be nested (e.g. an area
of “input processing” might include sub-areas “read CSV files”, “read
XLS files” and “read Gnumeric files”). To cater for this natural nesting,
channel names are organized into a namespace hierarchy where levels are
separated by periods, much like the Java or Python package namespace. So
in the instance given above, channel names might be “input” for the upper
level, and “input.csv”, “input.xls” and “input.gnu” for the sub-levels.
There is no arbitrary limit to the depth of nesting.