MultiScopicCNN¶
- class torch_ecg.models.MultiScopicCNN(in_channels: int, **config)[source]¶
Bases:
Module
,SizeMixin
,CitationMixin
CNN part of the SOTA model from CPSC2019 challenge (entry 0416).
This architecture is a multi-branch CNN with multi-scopic convolutions, proposed by the winning team of the CPSC2019 challenge and described in [Cai and Hu[1]]. The multi-scopic convolutions are implemented via different dilations. Similar architectures can be found in the model DeepLabv3 [Chen et al.[2]].
- Parameters:
in_channels (int) – Number of channels (leads) in the input signal tensor.
config (dict) –
Other hyper-parameters of the Module, ref. corr. config file. Key word arguments that must be set:
scopes: sequence of sequences of sequences of
int
, scopes (in terms of dilation) of each convolution.num_filters: sequence of sequences (of
int
or of sequences ofint
), number of filters of the convolutional layers, with granularity to each block of each branch, or to each convolution of each block of each branch.filter_lengths: sequence of sequences (of
int
or of sequences ofint
), filter length(s) (kernel size(s)) of the convolutions, with granularity to each block of each branch, or to each convolution of each block of each branch.subsample_lengths: sequence of
int
or sequence of sequences ofint
, subsampling length(s) (ratio(s)) of all blocks, with granularity to each branch or to each block of each branch, each subsamples after the last convolution of each block.dropouts: sequence of
int
or sequence of sequences ofint
, dropout rates of all blocks, with granularity to each branch or to each block of each branch, each dropouts at the last of each block.groups:
int
, connection pattern (of channels) of the inputs and outputs.block:
dict
, other parameters that can be set for the building blocks.
For a full list of configurable parameters, ref. corr. config file.
References
- assign_weights_lead_wise(other: MultiScopicCNN, indices: Sequence[int]) None [source]¶
Assign weights to the other
MultiScopicCNN
module in the lead-wise manner- Parameters:
other (MultiScopicCNN) – The other
MultiScopicCNN
module.indices (Sequence[int]) – Indices of the
MultiScopicCNN
modules to assign weights.
Examples
>>> from copy import deepcopy >>> import torch >>> from torch_ecg.models import ECG_CRNN >>> from torch_ecg.model_configs import ECG_CRNN_CONFIG >>> from torch_ecg.utils.misc import list_sum >>> # we create models using 12-lead ECGs and using reduced 6-lead ECGs >>> indices = [0, 1, 2, 3, 4, 10] # chosen randomly, no special meaning >>> # chose the lead-wise models >>> lead_12_config = deepcopy(ECG_CRNN_CONFIG) >>> lead_12_config.cnn.name = "multi_scopic_leadwise" >>> lead_6_config = deepcopy(ECG_CRNN_CONFIG) >>> lead_6_config.cnn.name = "multi_scopic_leadwise" >>> # adjust groups and numbers of filters >>> lead_6_config.cnn.multi_scopic_leadwise.groups = 6 >>> # numbers of filters should be proportional to numbers of groups >>> lead_6_config.cnn.multi_scopic_leadwise.num_filters = ( np.array([[192, 384, 768], [192, 384, 768], [192, 384, 768]]) / 2 ).astype(int).tolist() >>> # we assume that model12 is a trained model on 12-lead ECGs >>> model12 = ECG_CRNN(["AF", "PVC", "NSR"], 12, lead_12_config) >>> model6 = ECG_CRNN(["AF", "PVC", "NSR"], 6, lead_6_config) >>> model12.eval() >>> model6.eval() >>> # we create tensor12, tensor6 to check the correctness of the assignment of the weights >>> tensor12 = torch.zeros(1, 12, 200) # batch, leads, seq_len >>> tensor6 = torch.randn(1, 6, 200) >>> # we make tensor12 has identical values as tensor6 at the given leads, and let the other leads have zero values >>> tensor12[:, indices, :] = tensor6 >>> b = "branch_0" # similarly for other branches >>> _, output_shape_12, _ = model12.cnn.branches[b].compute_output_shape() >>> _, output_shape_6, _ = model6.cnn.branches[b].compute_output_shape() >>> units = output_shape_12 // 12 >>> out_indices = list_sum([[i * units + j for j in range(units)] for i in indices]) >>> (model6.cnn.branches[b](tensor6) == model12.cnn.branches[b](tensor12)[:, out_indices, :]).all() tensor(False) # different feature maps >>> # here, we assign weights from model12 that correspond to the given leads to model6 >>> model12.cnn.assign_weights_lead_wise(model6.cnn, indices) >>> (model6.cnn.branches[b](tensor6) == model12.cnn.branches[b](tensor12)[:, out_indices, :]).all() tensor(True) # identical feature maps
- compute_output_shape(seq_len: int | None = None, batch_size: int | None = None) Sequence[int | None] [source]¶
Compute the output shape of the Module.
- forward(input: Tensor) Tensor [source]¶
Forward pass.
- Parameters:
input (torch.Tensor) – Input tensor, of shape
(batch_size, n_channels, seq_len)
.- Returns:
output – Output tensor, of shape
(batch_size, n_channels, seq_len)
.- Return type: