| """ |
| LSTM model for Intrusion Detection. |
| Treats 41 features as a sequence of length 41 with 1 feature per step. |
| """ |
|
|
| import torch |
| import torch.nn as nn |
|
|
|
|
| class LSTM_IDS(nn.Module): |
| """ |
| LSTM-based IDS model. |
| |
| Design choices: |
| - Reshape (batch, 41) → (batch, 41, 1): treat each feature as a time step |
| - 2 LSTM layers with hidden=64: captures inter-feature dependencies |
| - Use last hidden state for classification |
| - Feature ordering in NSL-KDD is semantic: basic→content→time-based→host-based |
| """ |
| |
| def __init__(self, in_dim=41, hidden_dim=64, num_layers=2, num_classes=2, dropout=0.2): |
| super().__init__() |
| |
| self.lstm = nn.LSTM( |
| input_size=1, |
| hidden_size=hidden_dim, |
| num_layers=num_layers, |
| batch_first=True, |
| dropout=dropout if num_layers > 1 else 0 |
| ) |
| self.fc = nn.Sequential( |
| nn.Linear(hidden_dim, 32), |
| nn.ReLU(), |
| nn.Linear(32, num_classes) |
| ) |
| |
| def forward(self, x): |
| |
| x = x.unsqueeze(-1) |
| out, (h_n, c_n) = self.lstm(x) |
| |
| last_hidden = h_n[-1] |
| return self.fc(last_hidden) |
| |
| def count_parameters(self): |
| return sum(p.numel() for p in self.parameters() if p.requires_grad) |
|
|
|
|
| if __name__ == '__main__': |
| model = LSTM_IDS(in_dim=41, num_classes=2) |
| print(model) |
| print(f"\nTotal parameters: {model.count_parameters():,}") |
| |
| x = torch.randn(32, 41) |
| out = model(x) |
| print(f"Input: {x.shape}") |
| print(f"Output: {out.shape}") |
|
|