import torch


def create_optimizer(optimizer_name, model, **kwargs):
    """
    Create a torch optimizer of the specified type for the given model.

    Args:
        optimizer_name: The type of optimizer to create (as string), one of: 'SGD', 'NAG', 'Adam', 'RMSprop'.
        model: The model to train with the optimizer.
        **kwargs: Additional named parameters to the optimizers init function.

    Returns:
        The optimizer.

    Raises:
        ValueError: on an invalid loss name (i.e. not in 'SGD', 'NAG', 'Adam', 'RMSprop').
    """
    optimizers = {'SGD': (torch.optim.SGD, {'momentum': 0.9, 'nesterov': False}),
                  'NAG': (torch.optim.SGD, {'momentum': 0.9, 'nesterov': True}),
                  'Adam': (torch.optim.Adam, {}),
                  'RMSprop': (torch.optim.RMSprop, {})}
    if optimizer_name not in optimizers:
        raise ValueError(f'Invalid optimizer {optimizer_name}. Valid optimizers are: {", ".join(optimizers.keys())}.')

    optimizer, init_kwargs = optimizers[optimizer_name]
    return optimizer(model.parameters(), **init_kwargs, **kwargs)