utils.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import os
  15. import sys
  16. import logging
  17. import functools
  18. import paddle.distributed as dist
  19. logger_initialized = {}
  20. def print_dict(d, logger, delimiter=0):
  21. """
  22. Recursively visualize a dict and
  23. indenting acrrording by the relationship of keys.
  24. """
  25. for k, v in sorted(d.items()):
  26. if isinstance(v, dict):
  27. logger.info("{}{} : ".format(delimiter * " ", str(k)))
  28. print_dict(v, logger, delimiter + 4)
  29. elif isinstance(v, list) and len(v) >= 1 and isinstance(v[0], dict):
  30. logger.info("{}{} : ".format(delimiter * " ", str(k)))
  31. for value in v:
  32. print_dict(value, logger, delimiter + 4)
  33. else:
  34. logger.info("{}{} : {}".format(delimiter * " ", k, v))
  35. @functools.lru_cache()
  36. def get_logger(name='root', log_file=None, log_level=logging.DEBUG):
  37. """Initialize and get a logger by name.
  38. If the logger has not been initialized, this method will initialize the
  39. logger by adding one or two handlers, otherwise the initialized logger will
  40. be directly returned. During initialization, a StreamHandler will always be
  41. added. If `log_file` is specified a FileHandler will also be added.
  42. Args:
  43. name (str): Logger name.
  44. log_file (str | None): The log filename. If specified, a FileHandler
  45. will be added to the logger.
  46. log_level (int): The logger level. Note that only the process of
  47. rank 0 is affected, and other processes will set the level to
  48. "Error" thus be silent most of the time.
  49. Returns:
  50. logging.Logger: The expected logger.
  51. """
  52. logger = logging.getLogger(name)
  53. if name in logger_initialized:
  54. return logger
  55. for logger_name in logger_initialized:
  56. if name.startswith(logger_name):
  57. return logger
  58. formatter = logging.Formatter(
  59. '[%(asctime)s] %(name)s %(levelname)s: %(message)s',
  60. datefmt="%Y/%m/%d %H:%M:%S")
  61. stream_handler = logging.StreamHandler(stream=sys.stdout)
  62. stream_handler.setFormatter(formatter)
  63. logger.addHandler(stream_handler)
  64. if log_file is not None and dist.get_rank() == 0:
  65. log_file_folder = os.path.split(log_file)[0]
  66. os.makedirs(log_file_folder, exist_ok=True)
  67. file_handler = logging.FileHandler(log_file, 'a')
  68. file_handler.setFormatter(formatter)
  69. logger.addHandler(file_handler)
  70. if dist.get_rank() == 0:
  71. logger.setLevel(log_level)
  72. else:
  73. logger.setLevel(logging.ERROR)
  74. logger_initialized[name] = True
  75. return logger
  76. def load_model(config, model, optimizer=None):
  77. """
  78. load model from checkpoint or pretrained_model
  79. """
  80. logger = get_logger()
  81. checkpoints = config.get('checkpoints')
  82. pretrained_model = config.get('pretrained_model')
  83. best_model_dict = {}
  84. if checkpoints:
  85. if checkpoints.endswith('.pdparams'):
  86. checkpoints = checkpoints.replace('.pdparams', '')
  87. assert os.path.exists(checkpoints + ".pdparams"), \
  88. "The {}.pdparams does not exists!".format(checkpoints)
  89. # load params from trained model
  90. params = paddle.load(checkpoints + '.pdparams')
  91. state_dict = model.state_dict()
  92. new_state_dict = {}
  93. for key, value in state_dict.items():
  94. if key not in params:
  95. logger.warning("{} not in loaded params {} !".format(
  96. key, params.keys()))
  97. continue
  98. pre_value = params[key]
  99. if list(value.shape) == list(pre_value.shape):
  100. new_state_dict[key] = pre_value
  101. else:
  102. logger.warning(
  103. "The shape of model params {} {} not matched with loaded params shape {} !".
  104. format(key, value.shape, pre_value.shape))
  105. model.set_state_dict(new_state_dict)
  106. if optimizer is not None:
  107. if os.path.exists(checkpoints + '.pdopt'):
  108. optim_dict = paddle.load(checkpoints + '.pdopt')
  109. optimizer.set_state_dict(optim_dict)
  110. else:
  111. logger.warning(
  112. "{}.pdopt is not exists, params of optimizer is not loaded".
  113. format(checkpoints))
  114. if os.path.exists(checkpoints + '.states'):
  115. with open(checkpoints + '.states', 'rb') as f:
  116. states_dict = pickle.load(f) if six.PY2 else pickle.load(
  117. f, encoding='latin1')
  118. best_model_dict = states_dict.get('best_model_dict', {})
  119. if 'epoch' in states_dict:
  120. best_model_dict['start_epoch'] = states_dict['epoch'] + 1
  121. logger.info("resume from {}".format(checkpoints))
  122. elif pretrained_model:
  123. load_pretrained_params(model, pretrained_model)
  124. else:
  125. logger.info('train from scratch')
  126. return best_model_dict
  127. def load_pretrained_params(model, path):
  128. logger = get_logger()
  129. if path.endswith('.pdparams'):
  130. path = path.replace('.pdparams', '')
  131. assert os.path.exists(path + ".pdparams"), \
  132. "The {}.pdparams does not exists!".format(path)
  133. params = paddle.load(path + '.pdparams')
  134. state_dict = model.state_dict()
  135. new_state_dict = {}
  136. for k1 in params.keys():
  137. if k1 not in state_dict.keys():
  138. logger.warning("The pretrained params {} not in model".format(k1))
  139. else:
  140. if list(state_dict[k1].shape) == list(params[k1].shape):
  141. new_state_dict[k1] = params[k1]
  142. else:
  143. logger.warning(
  144. "The shape of model params {} {} not matched with loaded params {} {} !".
  145. format(k1, state_dict[k1].shape, k1, params[k1].shape))
  146. model.set_state_dict(new_state_dict)
  147. logger.info("load pretrain successful from {}".format(path))
  148. return model