code: def test_lr_scheduler_cosine_decay_increasing_period():
      total_steps = 20000
      steps_per_checkpoint = 1000
      base_lr = 1.0
  
      module = NumberInputFeature(
          NumberInputFeatureConfig(
              name="num1", encoder=DenseEncoderConfig()
          )
      )
  
      optimizer = SGD(module.parameters(), lr=base_lr)
      config = LRSchedulerConfig(
          decay="cosine",
          t_0=steps_per_checkpoint,
          t_mult=2,
          decay_rate=0,
          reduce_on_plateau=0,
      )
      scheduler = LRScheduler(
          config=config,
          optimizer=optimizer,
          steps_per_checkpoint=steps_per_checkpoint,
          total_steps=total_steps,
      )
  
      curr_lr = base_lr
      prev_lr = base_lr
      num_restarts = 0
      for _ in range(total_steps + 1):
          if prev_lr < curr_lr:
              # Since Cosine decay is periodic, we should see the learning rate
              # decrease and then increase again.
              num_restarts += 1
  
          prev_lr = curr_lr
          scheduler.step()
  
          curr_lr = optimizer.param_groups[0]["lr"]
  
      # 1000, 3000, 6000, 12000, 24000 (but we stop at 20000)
      assert num_restarts == 4, f"num_restarts: {num_restarts}"
  
file_path: ludwig/tests/ludwig/modules/test_lr_scheduler.py
imports: import math
  import numpy
  from torch.optim import SGD
  from ludwig.features.number_feature import NumberInputFeature, NumberOutputFeature
  from ludwig.modules.lr_scheduler import LRScheduler
  from ludwig.schema.encoders.base import DenseEncoderConfig
  from ludwig.schema.features.number_feature import ECDNumberOutputFeatureConfig, NumberInputFeatureConfig
  from ludwig.schema.lr_scheduler import LRSchedulerConfig
  from ludwig.utils.metric_utils import TrainerMetric
  from ludwig.utils.trainer_utils import get_new_progress_tracker
label_desc: Use image node_id 4 for calling a global function with example usage: test_lr_scheduler_cosine_decay_increasing_period() without return types