Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[<Library component: Model|Core|etc...>] Adding Multivariate Model. #1214

Open
skmanzg opened this issue Nov 25, 2024 · 0 comments
Open

[<Library component: Model|Core|etc...>] Adding Multivariate Model. #1214

skmanzg opened this issue Nov 25, 2024 · 0 comments
Labels

Comments

@skmanzg
Copy link

skmanzg commented Nov 25, 2024

What happened + What you expected to happen

I am trying to change(?) LSTM model into multivariate version based on multivariate correlation + autocorrelation in my local enviroment.

so, I tried to change like this:

  1. use BaseMultivariate instead of recurrent thing
    class LSTM(BaseMultivariate):

  2. set class attributes

    # Class attributes
    SAMPLING_TYPE = "multivariate"
    EXOGENOUS_FUTR = True
    EXOGENOUS_HIST = True
    EXOGENOUS_STAT = True
  1. add 'n_series' in init
    def __init__(
        self,
        h: int,
        input_size,
        n_series,
        inference_input_size: int = -1,
        valid_batch_size: Optional[int] = None,
...
...
)


super(LSTM, self).__init__(
            h=h,
            input_size=input_size,
            n_series=n_series,
            inference_input_size=inference_input_size,
            valid_batch_size=valid_batch_size,
...
..


)

        self.n_series = n_series

  1. add multivariate feature i intended as a new class.

        self.cross_correlation = CrossCorrelationLayer(
            n_series, 
            self.encoder_hidden_size
        )
        self.temporal_attention = TemporalAttention(
            self.encoder_hidden_size
        )


class CrossCorrelationLayer(nn.Module):
    def __init__(self, n_series, hidden_size):
        super().__init__()
        self.correlation_weights = nn.Parameter(
            torch.randn(n_series, n_series)
        )
        self.hidden_transform = nn.Linear(hidden_size * 2, hidden_size)
    
    def forward(self, x):
        # x shape: [batch, seq_len, n_series]
        corr_weighted = torch.matmul(x, self.correlation_weights)
        combined = torch.cat([x, corr_weighted], dim=-1)



class TemporalAttention(nn.Module):
    def __init__(self, hidden_size):
        super().__init__()
        self.attention = nn.MultiheadAttention(
            hidden_size, 
            num_heads=8
        )
    
    def forward(self, x):
        # x shape: [batch, seq_len, hidden_size]
        attn_output, _ = self.attention(x, x, x)
        return attn_output
    

  1. change input_encoder
        # LSTM input size (1 for target variable y)
        input_encoder = n_series + self.hist_exog_size + self.stat_exog_size
  1. fix the forward function accordingly:
def forward(self, windows_batch):

        # Parse windows_batch
        encoder_input = windows_batch["insample_y"]  # [B, seq_len, n_series]
        futr_exog = windows_batch["futr_exog"]
        hist_exog = windows_batch["hist_exog"]
        stat_exog = windows_batch["stat_exog"]
        print('encoder_input:', encoder_input.shape)  # for debug



..

..

        # Cross-correlation 
        corr_features = self.cross_correlation(encoder_input)
        
        # LSTM encoding
        hidden_state, _ = self.hist_encoder(corr_features)
        
        # Apply temporal attention
        hidden_state = self.temporal_attention(hidden_state)
        

        print('hidden_state:',hidden_state.shape)
        # Context adapter
        context = self.context_adapter(hidden_state)
        context = context.reshape(batch_size, seq_len, self.h, self.context_size)
        print('context:',context.shape)
        # Residual connection with futr_exog
        if self.futr_exog_size > 0:
            context = torch.cat((context, futr_exog), dim=-1)

        # Final forecast
        output = self.mlp_decoder(context)
        output = self.loss.domain_map(output)
        
        print(output.shape)

        return output



  1. I set the hyperparameters for five features time series.
model = LSTM(h=288, 
            input_size=1440,
            n_series=5,
            loss=MAE(),
            scaler_type='minmax',
            encoder_n_layers=5,
            encoder_hidden_size=128,
            context_size=10,
            decoder_hidden_size=128,
            decoder_layers=5,
            max_steps=500,
                 )

nf = NeuralForecast(models=[model], freq='10min') 

and the, when I try to do 'nf.fit(df=Y_train_df), the error occurred.

RuntimeError: input.size(-1) must be equal to input_size. Expected 5, got 2

This is mainly because it accepts 2 features instead of 5 features when I print encoder_input
encoder_input: encoder_input:encoder_input:torch.Size([32, 1440, 2])

I do not know why the size became 2 when I set n_series = 5. This is really frustrating tbh.

In addition,

            inference_input_size=inference_input_size,
            valid_batch_size=valid_batch_size,

These also cause problem with TypeError: Trainer.__init__() got an unexpected keyword argument. so I had to remove those two when I run the code.

Those errors seems very common when I try to do it with different model, ModernTCN, not to mention the guide document is very limited.

Versions / Dependencies

python 3.10.14
reinstalled neuralforecast today.

Reproduction script

This was already described above

Issue Severity

High: It blocks me from completing my task.

@skmanzg skmanzg added the bug label Nov 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant