def train_auto_split_scaled(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)
    n_train = int((split * data.shape[0]))
    n_test = (data.shape[0] - n_train)
    (data_train, data_test) = torch.split(data, [n_train, n_test], dim=0)
    (target_train, target_test) = torch.split(target, [n_train, n_test], dim=0)
    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_train)
        MSE = torch.mean(((prediction - target_train) ** 2), dim=0)
        theta_norms = [torch.norm(theta, dim=0) for theta in thetas]
        time_deriv_norms = [torch.norm(dt, dim=0) for dt in time_derivs]
        normed_thetas = [(theta / norm) for (theta, norm) in zip(thetas, theta_norms)]
        normed_time_derivs = [(dt / norm) for (dt, norm) in zip(time_derivs, time_deriv_norms)]
        Reg = torch.stack([torch.mean(((dt - (theta @ coeff_vector)) ** 2)) for (dt, theta, coeff_vector) in zip(normed_time_derivs, normed_thetas, model.constraint_coeffs(scaled=True, sparse=True))])
        loss = torch.sum((MSE + Reg))
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        l1_norm = torch.sum(torch.abs(torch.cat(model.constraint_coeffs(sparse=True, scaled=True), dim=1)), dim=0)
        (prediction_test, coordinates) = model.func_approx(data_test)
        (time_derivs_test, thetas_test) = model.library((prediction_test, coordinates))
        MSE_test = torch.mean(((prediction_test - target_test) ** 2), dim=0)
        Reg_test = torch.stack([torch.mean(((dt - (theta @ coeff_vector)) ** 2)) for (dt, theta, coeff_vector) in zip(time_derivs_test, thetas_test, model.constraint_coeffs(scaled=False, sparse=True))])
        loss_test = torch.sum((MSE_test + Reg_test))
        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(Reg).item(), torch.sum(l1_norm).item())
            board.write(iteration, loss, MSE, Reg, l1_norm, model.constraint_coeffs(sparse=True, scaled=True), model.constraint_coeffs(sparse=True, scaled=False), estimator_coeff_vectors, MSE_test=MSE_test, Reg_test=Reg_test, loss_test=loss_test)
        sparsity_scheduler(loss_test, model, optimizer)
        if (sparsity_scheduler.apply_sparsity is True):
            with torch.no_grad():
                checkpoint = torch.load(sparsity_scheduler.path)
                model.load_state_dict(checkpoint['model_state_dict'])
                optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
                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_scaled(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)
    n_train = int((split * data.shape[0]))
    n_test = (data.shape[0] - n_train)
    (data_train, data_test) = torch.split(data, [n_train, n_test], dim=0)
    (target_train, target_test) = torch.split(target, [n_train, n_test], dim=0)
    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_train)
        MSE = torch.mean(((prediction - target_train) ** 2), dim=0)
        theta_norms = [torch.norm(theta, dim=0) for theta in thetas]
        time_deriv_norms = [torch.norm(dt, dim=0) for dt in time_derivs]
        normed_thetas = [(theta / norm) for (theta, norm) in zip(thetas, theta_norms)]
        normed_time_derivs = [(dt / norm) for (dt, norm) in zip(time_derivs, time_deriv_norms)]
        Reg = torch.stack([torch.mean(((dt - (theta @ coeff_vector)) ** 2)) for (dt, theta, coeff_vector) in zip(normed_time_derivs, normed_thetas, model.constraint_coeffs(scaled=True, sparse=True))])
        loss = torch.sum((MSE + Reg))
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        l1_norm = torch.sum(torch.abs(torch.cat(model.constraint_coeffs(sparse=True, scaled=True), dim=1)), dim=0)
        (prediction_test, coordinates) = model.func_approx(data_test)
        (time_derivs_test, thetas_test) = model.library((prediction_test, coordinates))
        MSE_test = torch.mean(((prediction_test - target_test) ** 2), dim=0)
        Reg_test = torch.stack([torch.mean(((dt - (theta @ coeff_vector)) ** 2)) for (dt, theta, coeff_vector) in zip(time_derivs_test, thetas_test, model.constraint_coeffs(scaled=False, sparse=True))])
        loss_test = torch.sum((MSE_test + Reg_test))
        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(Reg).item(), torch.sum(l1_norm).item())
            board.write(iteration, loss, MSE, Reg, l1_norm, model.constraint_coeffs(sparse=True, scaled=True), model.constraint_coeffs(sparse=True, scaled=False), estimator_coeff_vectors, MSE_test=MSE_test, Reg_test=Reg_test, loss_test=loss_test)
        sparsity_scheduler(loss_test, model, optimizer)
        if (sparsity_scheduler.apply_sparsity is True):
            with torch.no_grad():
                checkpoint = torch.load(sparsity_scheduler.path)
                model.load_state_dict(checkpoint['model_state_dict'])
                optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
                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()