design a model similar to this one but I want it with two modifications.  1) a many encoder single decoder model and b) a single encoder many decoder:
#based on clustering 
class TCNEncoderTransformerDecoderEnsemble(nn.Module):
    def __init__(self, feature_groups, hidden_size, num_layers, kernel_size, 
                 num_heads, dropout):
        super(TCNEncoderTransformerDecoderEnsemble, self).__init__()

        self.feature_groups = feature_groups  # List of lists containing feature indices
        self.hidden_size = hidden_size

        # Number of sub-models is determined by the number of feature groups
        self.num_submodels = len(feature_groups)

        # Create sub-models for each feature group
        self.encoders = nn.ModuleList()
        self.decoders = nn.ModuleList()
        self.attention_layers = nn.ModuleList()
        self.final_fc_layers = nn.ModuleList()
        self.alphas = nn.ParameterList()

        self.positional_encoding = PositionalEncoding(hidden_size, dropout)
        self.dropout = nn.Dropout(dropout)        

        for group in feature_groups:
            input_size = len(group)

            # Initialize sub-models
            encoder = TCNEncoder(input_size, hidden_size, num_layers, kernel_size, dropout)
            decoder = TransformerDecoder(input_size, hidden_size, num_layers, num_heads, dropout)
            attention_layer = nn.MultiheadAttention(embed_dim=hidden_size, num_heads=num_heads, dropout=dropout)
            final_fc_layer = nn.Linear(hidden_size, input_size)
            alpha = nn.Parameter(torch.full((hidden_size,), 0.5))

            self.encoders.append(encoder)
            self.decoders.append(decoder)
            self.attention_layers.append(attention_layer)
            self.final_fc_layers.append(final_fc_layer)
            self.alphas.append(alpha)

    def forward(self, src, tgt):
        # src: (batch_size, src_seq_length, total_features)
        # tgt: (batch_size, tgt_seq_length, total_features)
    
        outputs = []
    
        for i, group in enumerate(self.feature_groups):
            # Extract features for the current group
            src_sub = src[..., group]  # (batch_size, src_seq_length, group_size)
            tgt_sub = tgt[..., group]  # (batch_size, tgt_seq_length, group_size)
    
            # Get corresponding sub-models
            encoder = self.encoders[i]
            decoder = self.decoders[i]
            attention_layer = self.attention_layers[i]
            final_fc_layer = self.final_fc_layers[i]
            alpha = torch.sigmoid(self.alphas[i]).to(src.device).view(1, 1, -1)
    
            # Encoder
            memory = encoder(src_sub)
            memory = self.positional_encoding(memory)
    
            # Decoder
            tgt_mask = nn.Transformer.generate_square_subsequent_mask(tgt_sub.size(1)).to(tgt_sub.device)
            decoder_output = decoder(tgt_sub, memory, tgt_mask)
    
            # Reshape for MultiheadAttention
            decoder_output_t = decoder_output.transpose(0, 1)
            memory_t = memory.transpose(0, 1)
    
            # Additional Attention Layer
            attn_output, _ = attention_layer(decoder_output_t, memory_t, memory_t)
            attn_output = attn_output.transpose(0, 1)
    
            # Fusion Strategy
            combined = alpha * decoder_output + (1 - alpha) * attn_output
            combined = self.dropout(combined)
    
            # Final Output Layer
            final_output_sub = final_fc_layer(combined)  # (batch_size, tgt_seq_length, group_size)
            outputs.append(final_output_sub)
    
        # Concatenate outputs along the feature dimension
        final_output = torch.cat(outputs, dim=2)  # (batch_size, tgt_seq_length, total_features)
    
        return final_output