text: import functools
  import os
  import time
  from torch.utils.tensorboard import SummaryWriter
  import logging
  import yaml
  
  
  def over_write_args_from_file(args, yml):
      if yml == '':
          return
      with open(yml, 'r', encoding='utf-8') as f:
          dic = yaml.load(f.read(), Loader=yaml.Loader)
          for k in dic:
              setattr(args, k, dic[k])
  
  
  def setattr_cls_from_kwargs(cls, kwargs):
      # if default values are in the cls,
      # overlap the value by kwargs
      for key in kwargs.keys():
          if hasattr(cls, key):
              print(f"{key} in {cls} is overlapped by kwargs: {getattr(cls, key)} -> {kwargs[key]}")
          setattr(cls, key, kwargs[key])
  
  
  def test_setattr_cls_from_kwargs():
      class _test_cls:
          def __init__(self):
              self.a = 1
              self.b = 'hello'
  
      test_cls = _test_cls()
      config = {'a': 3, 'b': 'change_hello', 'c': 5}
      setattr_cls_from_kwargs(test_cls, config)
      for key in config.keys():
          print(f"{key}:\t {getattr(test_cls, key)}")
  
  
  def _pretrained_net_builder(model, pretrained):
      if not pretrained:
          return functools.partial(model, pretrained=pretrained)
  
      @functools.wraps(model)
      def _impl(*args, **kwargs):
          if "num_classes" not in kwargs:
              return model(*args, pretrained=True, **kwargs)
  
          from torchvision.models.efficientnet import EfficientNet
          from torch import nn
  
          num_classes = kwargs.pop("num_classes")
  
          inst = model(*args, pretrained=True, **kwargs)
  
          if not isinstance(inst, EfficientNet):
              raise Exception("pretraining is only currently available for efficientnet models")
  
          current_classifier = inst.classifier[1]
  
          if not isinstance(current_classifier, nn.Linear):
              raise Exception("Classification layer was not linear as expected")
  
          inst.classifier[1] = nn.Linear(current_classifier.in_features, num_classes)
  
          return inst
  
      return _impl
  
  
  def net_builder(net_name, from_name: bool, net_conf=None, is_remix=False, pretrained=False):
      """
      return **class** of backbone network (not instance).
      Args
          net_name: 'WideResNet' or network names in torchvision.models
          from_name: If True, net_buidler takes models in torch.vision models. Then, net_conf is ignored.
          net_conf: When from_name is False, net_conf is the configuration of backbone network (now, only WRN is supported).
      """
      if from_name:
          import torchvision.models as models
          model_name_list = sorted(name for name in models.__dict__
                                   if name.islower() and not name.startswith("__")
                                   and callable(models.__dict__[name]))
  
          if net_name not in model_name_list:
              assert Exception(f"[!] Networks\' Name is wrong, check net config, \
                                 expected: {model_name_list}  \
                                 received: {net_name}")
          else:
              return _pretrained_net_builder(models.__dict__[net_name], pretrained)
  
      else:
          if net_name == 'WideResNet':
              import models.nets.wrn as net
              builder = getattr(net, 'build_WideResNet')()
          elif net_name == 'WideResNetVar':
              import models.nets.wrn_var as net
              builder = getattr(net, 'build_WideResNetVar')()
          elif net_name == 'ResNet50':
              import models.nets.resnet50 as net
              builder = getattr(net, 'build_ResNet50')(is_remix)
          else:
              assert Exception("Not Implemented Error")
  
          if net_name != 'ResNet50':
              setattr_cls_from_kwargs(builder, net_conf)
          return builder.build
  
  
  def test_net_builder(net_name, from_name, net_conf=None):
      builder = net_builder(net_name, from_name, net_conf)
      print(f"net_name: {net_name}, from_name: {from_name}, net_conf: {net_conf}")
      print(builder)
  
  
  def get_logger(name, save_path=None, level='INFO'):
      logger = logging.getLogger(name)
      logger.setLevel(getattr(logging, level))
  
      log_format = logging.Formatter('[%(asctime)s %(levelname)s] %(message)s')
      streamHandler = logging.StreamHandler()
      streamHandler.setFormatter(log_format)
      logger.addHandler(streamHandler)
  
      if not save_path is None:
          os.makedirs(save_path, exist_ok=True)
          fileHandler = logging.FileHandler(os.path.join(save_path, 'log.txt'))
          fileHandler.setFormatter(log_format)
          logger.addHandler(fileHandler)
  
      return logger
  
  
  def count_parameters(model):
      return sum(p.numel() for p in model.parameters() if p.requires_grad)
  