保存模型路径

载入超参数

保存运行设置

日志

配置信息

# Directories 保存模型的路径
    w = save_dir / 'weights'  # weights dir
    (w.parent if evolve else w).mkdir(parents=True, exist_ok=True)  # make dir
    last, best = w / 'last.pt', w / 'best.pt'

    # Hyperparameters 超参数
    if isinstance(hyp, str):   # 检查hyp是否为字符串
        with open(hyp, errors='ignore') as f:
            hyp = yaml.safe_load(f)  # load hyps dict 加载超参数字典
    # 日志输出超参信息 hyperparameters: ...
    LOGGER.info(colorstr('hyperparameters: ') + ', '.join(f'{k}={v}' for k, v in hyp.items()))
    opt.hyp = hyp.copy()  # for saving hyps to checkpoints 将超参数保存到检查点中

    # Save run settings 保存运行时的参数配置
    if not evolve:
        yaml_save(save_dir / 'hyp.yaml', hyp)
        yaml_save(save_dir / 'opt.yaml', vars(opt)) # vars()用于返回一个对象的属性和属性值的字典。

    # Loggers  日志
    data_dict = None
    if RANK in {-1, 0}:
        # loggers 是一个 Loggers 类的实例
        # 传入了一些参数,如 save_dir(保存目录)、weights(权重)、opt(训练选项)、hyp(超参数)和 LOGGER(全局日志记录器)
        loggers = Loggers(save_dir, weights, opt, hyp, LOGGER)  # loggers instance 日志记录器实例

        # Register actions 注册
        for k in methods(loggers):  # 通过 methods(loggers) 函数获取 loggers 实例的方法列表
            # 使用 getattr(loggers, k) 获取每个方法的引用。
            # 通过 callbacks.register_action(k, callback=getattr(loggers, k)) 将每个方法注册为回调函数。这样,在训练过程中,每次执行相应的回调函数时,会触发对应的方法。
            callbacks.register_action(k, callback=getattr(loggers, k))

        # Process custom dataset artifact link
        data_dict = loggers.remote_dataset
        if resume:  # If resuming runs from remote artifact
            weights, epochs, hyp, batch_size = opt.weights, opt.epochs, opt.hyp, opt.batch_size

    # Config
    # 是否需要画图: 所有的labels信息、迭代的epochs、训练结果等
    plots = not evolve and not opt.noplots  # create plots
    cuda = device.type != 'cpu'
    # 初始化随机数种子
    init_seeds(opt.seed + 1 + RANK, deterministic=True)
    with torch_distributed_zero_first(LOCAL_RANK):
        data_dict = data_dict or check_dataset(data)  # check if None
    train_path, val_path = data_dict['train'], data_dict['val']
    # nc: 数据集有多少种类别
    nc = 1 if single_cls else int(data_dict['nc'])  # number of classes
    # 如果只有一个类别并且data_dict里没有names这个key的话,我们将names设置为["item"]代表目标
    names = {0: 'item'} if single_cls and len(data_dict['names']) != 1 else data_dict['names']  # class names
    # 当前数据集是否是coco数据集(80个类别) 
    is_coco = isinstance(val_path, str) and val_path.endswith('coco/val2017.txt')  # COCO dataset