一、argparse相关
1.1 参数打印
print("***** Parmeters *****".rjust(62))
arguments = vars(args)
for key, value in arguments.items():
print(f"{key}".rjust(50)+ f": {value}")
print("***** Parmeters *****".rjust(62))
1.2 huggingface trainer logger
def set_logger_with_seed(training_args: Seq2SeqTrainingArguments):
import logging,sys
import transformers
from transformers import set_seed
logger = logging.getLogger(__name__) # 7. 创建一个日志记录器,用于记录脚本运行时的日志信息。
# Setup logging
# 10. 设置日志记录的基本配置,包括日志格式、日期格式和输出处理器(在这里是将日志输出到标准输出流)。
logging.basicConfig(
format="%(asctime)s - %(levelname)s - %(name)s - %(message)s",
datefmt="%m/%d/%Y %H:%M:%S",
handlers=[logging.StreamHandler(sys.stdout)],
)
if training_args.should_log:
# The default of training_args.log_level is passive, so we set log level at info here to have that default.
# 11. 如果训练参数指定应该记录日志,则将Transformers库的日志级别设置为info(信息级别)。默认情况下,训练参数的日志级别是被动的,所以这里将其设置为信息级别。
transformers.utils.logging.set_verbosity_info()
# 12. 获取训练参数指定的进程日志级别,并将该级别设置为当前日志记录器的级别。
log_level = training_args.get_process_log_level()
logger.setLevel(log_level)
# datasets.utils.logging.set_verbosity(log_level)
# 13. 设置Transformers库的日志级别为训练参数指定的进程日志级别,启用默认的日志处理器和显式的日志格式。
transformers.utils.logging.set_verbosity(log_level)
transformers.utils.logging.enable_default_handler()
transformers.utils.logging.enable_explicit_format()
# 设置一切相关的随机种子,保证训练结果的可重现性
set_seed(training_args.seed)
return logger
第二种
from loguru import logger
# 重定义终端显示logger颜色
logger.configure(handlers=[
{
"sink": sys.stderr,
"format": "{time:YYYY-MM-DD HH:mm:ss.SSS} |<cyan><lvl>{level:8}</></>| {name} : {module}:{line:4} | <cyan>mymodule</> | - <lvl>{message}</>",
"colorize": True
},
])
logger.debug('this is debug')
logger.info('this is info')
logger.warning('this is warning')
logger.error('this is error')
logger.critical('this is critical')
二、model 参数
2.1 参数打印
from loguru import logger
# 重定义终端显示logger颜色
logger.configure(handlers=[
{
"sink": sys.stderr,
"format": "{time:YYYY-MM-DD HH:mm:ss.SSS} |<cyan><lvl>{level:8}</></>| {name} : {module}:{line:4} | <cyan>mymodule</> | - <lvl>{message}</>",
"colorize": True
},
])
def verify_model_dtype(model):
"""
功能: 查看模型中各种类型的参数的情况
使用技术: Python 的 defaultdict、model.named_parameters()、参数遍历等
解决问题: 帮助开发者了解模型中参数的数据类型分布,以及可训练参数的情况,从而更好地优化模型
"""
logger.info(f"--> model structure: \n{model}")
ignore_layers = [f"layers.{i}" for i in range(2,21)] # 减少打印的层数
logger.info(f"ignore print layers: \n{ignore_layers}")
for n,v in model.named_parameters():
# 少打印一些层
if not any([i in n for i in ignore_layers]):
if v.requires_grad:
logger.info(f"trainable model arguments: {n} - {v.dtype} - {v.shape} - {v.device}")
else:
logger.info(f"not trainable model arguments: {n} - {v.dtype} - {v.shape} - {v.device}")
dtype2param_num = defaultdict(int) # 每种数据类型的参数量
dtype2param_name = defaultdict(list) # 每种数据类型的参数名称
dtype2trainable_param_num = defaultdict(int) # 每种数据类型参与训练的参数量
dtype2trainable_param_name = defaultdict(list) # 每种数据类型参与训练的参数名称
for name, p in model.named_parameters():
dtype = p.dtype # 获取参数的数据类型
# 统计参数数量和参数名称
dtype2param_num[dtype] += p.numel()
dtype2param_name[dtype].append(name)
# 如果参数参与训练(requires_grad=True),则统计可训练参数的数量和名称
if p.requires_grad:
dtype2trainable_param_num[dtype] += p.numel()
dtype2trainable_param_name[dtype].append(name)
# 统计全部参数中,各种类型参数分布
total = 0
logger.info('verify all params of the model')
for k, v in dtype2param_num.items():
total += v
for k, v in dtype2param_num.items():
print("all params info: {} num: {} {:.3f}%".format(k, v, 100.0 * v / total)) # 打印每种数据类型的参数量和占比
print()
# 统计可训练参数中,各种类型参数分布
logger.info('verify trainable params the model')
total_trainable = 0
for k, v in dtype2trainable_param_num.items():
total_trainable += v
for k, v in dtype2trainable_param_num.items():
print("trainable params info: {} num: {} {:.3f}%".format(k, v, 100.0 * v / total_trainable))
print()
for k, v in dtype2trainable_param_name.items():
print("all params info: {} trainable layers: {}".format(k, v)) # 打印每种数据类型的可训练参数名称
print()
# 查看参与训练的参数情况
total = sum(p.numel() for p in model.parameters())
trainable = sum(p.numel() for p in model.parameters() if p.requires_grad)
logger.info("Total model params: %.2fM" % (total / 1e6))
logger.info(
f'trainable params: {trainable} || all params: {total} || trainable%: {round(trainable / total, 4)}')
logger = ...
if training_args.local_rank == 0: # local 为0时打印
# 打印 TrainingArguments 或 model的config 或 peft model 的 peft_config
logger.info(f"Training/evaluation parameters {training_args}")
logger.info(f"model parameters {model.config}")
logger.info(f"PEFT parameters {peft_config}")
# 进程阻塞,同步所有进程,等待所有进程到达这一点
torch.distributed.barrier()
三、path
3.1 pathlib
from typing import Union
from pathlib import Path
# 1. 获得文件、目录的绝对位置路径
def _resolve_path(path: Union[str, Path]) -> Path:
# Path(path) 将path打包为Path对象
# Path(path).expanduser().resolve() 将Path对象路径转化为绝对位置路径
return Path(path).expanduser().resolve()
# 2. Path 对象文件、目录是否存在,返回bool
dir_name.is_dir()
train_file.is_file()
# dir_name 和 train_file都是 Path 对象
# 3. Path 对象创建文件夹
def _mkdir(dir_name: Union[str, Path]):
dir_name = _resolve_path(dir_name) # 先将输入路径转换为绝对路径
if not dir_name.is_dir(): # 检查目录是否存在,使用 is_dir() 方法
dir_name.mkdir(parents=True, exist_ok=False) # parents=True 表示递归创建父目录
# 4. Path 对象路径拼接
data_dir / 'train.json'
data_dir / 'dev.json'
# 直接用 / 拼接即可
# 5. Path 对象获得相对路径
dir_path : PosixPath('datas/AdvertiseGen')
file = dir_path / "train.json"
file: PosixPath('datas/AdvertiseGen/train.json')
# 获取相对路径
file_name = file.relative_to(dir_path)
# 结果:"train.json"
# 6. Path 对象获取父目录
out_file.parent
# out_file 是Path 对象
(待更...)