Loading checkpoint for LightningModule that defines a system
Systems
The style guide encourages to use systems, like this one
class LitModel(LightningModule):
    def __init__(self, encoder: nn.Module = None, decoder: nn.Module = None):
        super().__init__()
        self.encoder = encoder
        self.decoder = decoder
I have problems loading the checkpoint for such modules.
Below example fails. How can I make it work?
Minimal example
import os

import torch
from torch import nn
from torch.utils.data import Dataset
from pytorch_lightning import Trainer, LightningModule


class RandomDataset(Dataset):
    def __init__(self, size, length):
        self.len = length
        self.data = torch.randn(length, size)

    def __getitem__(self, index):
        return self.data[index]

    def __len__(self):
        return self.len


class SystemModel(LightningModule):

    def __init__(self, encoder: nn.Module = None, decoder: nn.Module = None, multiplier=10):
        super().__init__()
        self.save_hyperparameters('multiplier')
        self.encoder = encoder
        self.decoder = decoder
        self.multiplier = multiplier
        print("type of hparams", type(self.hparams))
        print("class of hparams type", self.hparams.__class__.__name__)

    def forward(self, x):
        return self.multiplier * self.decoder(self.encoder(x))

    def loss(self, batch, prediction):
        # An arbitrary loss to have a loss that updates the model weights during `Trainer.fit` calls
        return torch.nn.functional.mse_loss(prediction, torch.ones_like(prediction))

    def step(self, x):
        x = self.forward(x)
        out = torch.nn.functional.mse_loss(x, torch.ones_like(x))
        return out

    def training_step(self, batch, batch_idx):
        output = self.forward(batch)
        loss = self.loss(batch, output)
        return {"loss": loss}

    def training_step_end(self, training_step_outputs):
        return training_step_outputs

    def training_epoch_end(self, outputs) -> None:
        torch.stack([x["loss"] for x in outputs]).mean()

    def validation_step(self, batch, batch_idx):
        output = self.forward(batch)
        loss = self.loss(batch, output)
        return {"x": loss}

    def validation_epoch_end(self, outputs) -> None:
        torch.stack([x['x'] for x in outputs]).mean()

    def test_step(self, batch, batch_idx):
        output = self.forward(batch)
        loss = self.loss(batch, output)
        return {"y": loss}

    def test_epoch_end(self, outputs) -> None:
        torch.stack([x["y"] for x in outputs]).mean()

    def configure_optimizers(self):
        optimizer = torch.optim.SGD(self.parameters(), lr=0.1)
        lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=1)
        return [optimizer], [lr_scheduler]


train_data = torch.utils.data.DataLoader(RandomDataset(32, 64))
val_data = torch.utils.data.DataLoader(RandomDataset(32, 64))
test_data = torch.utils.data.DataLoader(RandomDataset(32, 64))

# model
model = SystemModel(torch.nn.Linear(32, 16), torch.nn.Linear(16, 2), multiplier=15)
trainer = Trainer(
    default_root_dir=os.getcwd(),
    limit_train_batches=1,
    limit_val_batches=1,
    max_epochs=1,
    weights_summary=None,
)
trainer.fit(model, train_data, val_data)

ckpt_path = trainer.checkpoint_callback.best_model_path

# Try to load
# Loading fails....
model = SystemModel.load_from_checkpoint(ckpt_path) # Fails

# Edit: answer by Adrian
# the correct way to load is 
model = SystemModel.load_from_checkpoint(ckpt_path, encoder=torch.nn.Linear(32, 16), decoder=torch.nn.Linear(16, 2))  

print("multiplier:", model.multiplier)
When you reload you need to specify the missing arguments for instantiation:
model = SystemModel.load_from_checkpoint(ckpt_path, encoder=..., decoder=...)