# Trainloader
# 数据加载
train_loader, dataset = create_dataloader(train_path,
imgsz,
batch_size // WORLD_SIZE,
gs,
single_cls,
hyp=hyp,
augment=True,
cache=None if opt.cache == 'val' else opt.cache,
rect=opt.rect,
rank=LOCAL_RANK,
workers=workers,
image_weights=opt.image_weights,
quad=opt.quad,
prefix=colorstr('train: '),
shuffle=True,
seed=opt.seed)
labels = np.concatenate(dataset.labels, 0)
mlc = int(labels[:, 0].max()) # max label class
assert mlc < nc, f'Label class {mlc} exceeds nc={nc} in {data}. Possible class labels are 0-{nc - 1}'
# Process 0
if RANK in {-1, 0}:
val_loader = create_dataloader(val_path,
imgsz,
batch_size // WORLD_SIZE * 2,
gs,
single_cls,
hyp=hyp,
cache=None if noval else opt.cache,
rect=True,
rank=-1,
workers=workers * 2,
pad=0.5,
prefix=colorstr('val: '))[0]
# 如果不使用断点续训
if not resume:
# Anchors
# 计算默认锚框anchor与数据集标签框的高宽比
# 标签的高h宽w与anchor的高h_a宽h_b的比值 即h/h_a, w/w_a都要在(1/hyp['anchor_t'], hyp['anchor_t'])是可以接受的
# 如果bpr小于98%,则根据k-mean算法聚类新的锚框
if not opt.noautoanchor:
# check_anchors : 这个函数是通过计算bpr确定是否需要改变anchors 需要就调用k-means重新计算anchors。
# bpr(best possible recall): 最多能被召回的ground truth框数量 / 所有ground truth框数量 最大值为1 越大越好
# 小于0.98就需要使用k-means + 遗传进化算法选择出与数据集更匹配的anchor boxes框。
check_anchors(dataset, model=model, thr=hyp['anchor_t'], imgsz=imgsz) # run AutoAnchor
model.half().float() # pre-reduce anchor precision
callbacks.run('on_pretrain_routine_end', labels, names)
这段代码的作用是创建训练数据加载器(train_loader)和数据集(dataset),并进行一些预处理操作。
首先,调用 create_dataloader
函数创建训练数据加载器。该函数接受多个参数,包括训练数据路径(train_path)、图像尺寸(imgsz)、批量大小(batch_size // WORLD_SIZE)、图像采样方式(gs)、是否单类别(single_cls)等。还可以设置一些其他参数,如数据增强(augment)、缓存路径(cache)、是否使用矩形数据(rect)、进程排名(rank)、工作进程数(workers)、图像权重(image_weights)、四分之一数据(quad)等。最后,还可以设置加载器的一些前缀信息(prefix)和是否进行洗牌(shuffle),以及随机种子(seed)。创建完成后,将训练数据加载器赋值给变量 train_loader
,并将数据集赋值给变量 dataset
。
接下来,将数据集中的标签(labels)连接起来,并保存在变量 labels
中。通过 labels[:, 0].max()
计算标签中的最大类别,将其转换为整数,并保存在变量 mlc
中。然后,使用断言语句确保最大类别不超过预设的类别数 nc
,如果超过了,则抛出异常。
接着,判断当前进程的排名 RANK
是否为 -1 或 0。如果是,则执行以下操作。
调用 create_dataloader
函数创建验证数据加载器(val_loader)。与创建训练数据加载器时的参数类似,但批量大小为训练数据加载器的两倍。还可以设置一些其他参数,如是否进行缓存(cache)、是否使用矩形数据(rect)、进程排名(rank)、工作进程数(workers)、填充比例(pad)等。最后,将返回的加载器列表中的第一个加载器赋值给变量 val_loader
。
如果不使用断点续训(resume),则进行锚框(Anchors)的处理。首先,通过计算默认锚框(anchor)与数据集标签框的高宽比,判断是否需要重新计算锚框。如果需要,则调用 check_anchors
函数进行计算。该函数会根据数据集和模型的信息,通过计算最多能被召回的 ground truth 框数量与所有 ground truth 框数量的比值(bpr),来确定是否需要改变锚框。如果 bpr 小于 0.98%,则使用 k-means 算法和遗传进化算法选择与数据集更匹配的锚框。最后,将模型的精度设置为半精度(half)。
最后,调用回调函数 callbacks.run('on_pretrain_routine_end', labels, names)
。这个回调函数的作用是在预训练过程结束时执行一些操作,例如打印标签和名称等信息。
这段代码的目的是创建训练数据加载器和数据集,并进行一些预处理操作,包括计算最大类别、处理验证数据加载器、处理锚框等。