def METHOD_NAME(model: DeepSpeedEngine, optimizer: Union[Optimizer, List[Optimizer]], \
                   training_step: _TRAINING_STEP, scheduler: Union[None, SCHEDULER, List[SCHEDULER]] = None,
                   max_steps: Union[int, None] = None, max_epochs: Union[int, None] = None):
    assert isinstance(model, DeepSpeedEngine)
    model.train()
    max_epochs = max_epochs or (40 if max_steps is None else 100)
    current_steps = 0
    best_acc = 0.0
    # training
    for epoch in range(max_epochs):
        print(f'Epoch {epoch} start!')
        model.train()
        for batch in train_dataloader:
            if isinstance(optimizer, Optimizer):
                optimizer.zero_grad()
            elif isinstance(optimizer, List) and all(isinstance(_, Optimizer) for _ in optimizer):
                for opt in optimizer:
                    opt.zero_grad()
            loss = training_step(batch, model)
            assert isinstance(loss, torch.Tensor)
            model.backward(loss)
            model.step()
            current_steps += 1
            if max_steps and current_steps == max_steps:
                return
        acc = evaluating_model(model)
        best_acc = max(acc, best_acc)
        print(f"epoch={epoch}\tacc={acc}\tbest_acc={best_acc}")