def train_auto_split_MSE(model: DeepMoD, data: torch.Tensor, target: torch.Tensor, optimizer, sparsity_scheduler, split: float=0.8, log_dir: Optional[str]=None, max_iterations: int=10000, write_iterations: int=25, **convergence_kwargs) -> None:
    '[summary]\n\n    Args:\n        model (DeepMoD): [description]\n        data (torch.Tensor): [description]\n        target (torch.Tensor): [description]\n        optimizer ([type]): [description]\n        sparsity_scheduler ([type]): [description]\n        log_dir (Optional[str], optional): [description]. Defaults to None.\n        max_iterations (int, optional): [description]. Defaults to 10000.\n    '
    start_time = time.time()
    board = Tensorboard(log_dir)
    convergence = Convergence(**convergence_kwargs)
    print('| Iteration | Progress | Time remaining |     Loss |      MSE |      Reg |    L1 norm |')
    for iteration in np.arange(0, (max_iterations + 1)):
        (prediction, time_derivs, thetas) = model(data)
        MSE = torch.mean(((prediction - target) ** 2), dim=0)
        loss = torch.sum(MSE)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        with torch.no_grad():
            l1_norm = torch.sum(torch.abs(torch.cat(model.constraint.coeff_vectors, dim=1)), dim=0)
            prediction_test = model.func_approx(data)[0]
            MSE_test = torch.mean(((prediction_test - target) ** 2), dim=0)
            if ((iteration % write_iterations) == 0):
                _ = model.sparse_estimator(thetas, time_derivs)
                estimator_coeff_vectors = model.estimator_coeffs()
                progress(iteration, start_time, max_iterations, loss.item(), torch.sum(MSE).item(), torch.sum(MSE).item(), torch.sum(l1_norm).item())
                board.write(iteration, loss, MSE, MSE, l1_norm, model.constraint.coeff_vectors, model.constraint.coeff_vectors, estimator_coeff_vectors, MSE_test=MSE_test)
        sparsity_scheduler(iteration, torch.sum(MSE_test), model, optimizer)
        if (sparsity_scheduler.apply_sparsity is True):
            with torch.no_grad():
                model.constraint.sparsity_masks = model.sparse_estimator(thetas, time_derivs)
                sparsity_scheduler.reset()
                print(model.sparsity_masks)
        convergence(iteration, torch.sum(l1_norm))
        if (convergence.converged is True):
            print('Algorithm converged. Stopping training.')
            break
    board.close()
[summary]

Args:
    model (DeepMoD): [description]
    data (torch.Tensor): [description]
    target (torch.Tensor): [description]
    optimizer ([type]): [description]
    sparsity_scheduler ([type]): [description]
    log_dir (Optional[str], optional): [description]. Defaults to None.
    max_iterations (int, optional): [description]. Defaults to 10000.
def train_auto_split_MSE(model: DeepMoD, data: torch.Tensor, target: torch.Tensor, optimizer, sparsity_scheduler, split: float=0.8, log_dir: Optional[str]=None, max_iterations: int=10000, write_iterations: int=25, **convergence_kwargs) -> None:
    '[summary]\n\n    Args:\n        model (DeepMoD): [description]\n        data (torch.Tensor): [description]\n        target (torch.Tensor): [description]\n        optimizer ([type]): [description]\n        sparsity_scheduler ([type]): [description]\n        log_dir (Optional[str], optional): [description]. Defaults to None.\n        max_iterations (int, optional): [description]. Defaults to 10000.\n    '
    start_time = time.time()
    board = Tensorboard(log_dir)
    convergence = Convergence(**convergence_kwargs)
    print('| Iteration | Progress | Time remaining |     Loss |      MSE |      Reg |    L1 norm |')
    for iteration in np.arange(0, (max_iterations + 1)):
        (prediction, time_derivs, thetas) = model(data)
        MSE = torch.mean(((prediction - target) ** 2), dim=0)
        loss = torch.sum(MSE)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        with torch.no_grad():
            l1_norm = torch.sum(torch.abs(torch.cat(model.constraint.coeff_vectors, dim=1)), dim=0)
            prediction_test = model.func_approx(data)[0]
            MSE_test = torch.mean(((prediction_test - target) ** 2), dim=0)
            if ((iteration % write_iterations) == 0):
                _ = model.sparse_estimator(thetas, time_derivs)
                estimator_coeff_vectors = model.estimator_coeffs()
                progress(iteration, start_time, max_iterations, loss.item(), torch.sum(MSE).item(), torch.sum(MSE).item(), torch.sum(l1_norm).item())
                board.write(iteration, loss, MSE, MSE, l1_norm, model.constraint.coeff_vectors, model.constraint.coeff_vectors, estimator_coeff_vectors, MSE_test=MSE_test)
        sparsity_scheduler(iteration, torch.sum(MSE_test), model, optimizer)
        if (sparsity_scheduler.apply_sparsity is True):
            with torch.no_grad():
                model.constraint.sparsity_masks = model.sparse_estimator(thetas, time_derivs)
                sparsity_scheduler.reset()
                print(model.sparsity_masks)
        convergence(iteration, torch.sum(l1_norm))
        if (convergence.converged is True):
            print('Algorithm converged. Stopping training.')
            break
    board.close()