2021SC@SDUSC
目录
初始化配置1
调整模型
初始化配置2
加载val数据集
初始化配置3
接上一篇的run函数
# Initialize/load model and set device
# 初始化模型并选择相应的计算设备
# 判断是否是训练时调用run函数(执行train.py脚本), 如果是就使用训练时的设备 一般都是train
training = model is not None
if training: # called by train.py
device = next(model.parameters()).device # get model device
# 如果不是trin.py调用run函数(执行val.py脚本)就调用select_device选择可用的设备
# 并生成save_dir + make dir + 加载模型model + check imgsz + 加载data配置信息
else: # called directly
device = select_device(device, batch_size=batch_size)
# Directories
# 生成save_dir文件路径 run\test\expn
save_dir = increment_path(Path(project) / name, exist_ok=exist_ok) # increment run
(save_dir / 'labels' if save_txt else save_dir).mkdir(parents=True, exist_ok=True) # make dir
# 加载模型 load FP32 model 只在运行test.py才需要自己加载model
check_suffix(weights, '.pt')
model = attempt_load(weights, map_location=device) # load FP32 model
# gs: 模型最大的下采样stride 一般[8, 16, 32] 所有gs一般是32
gs = max(int(model.stride.max()), 32) # grid size (max stride)
# 检测输入图片的分辨率imgsz是否能被gs整除 只在运行test.py才需要自己生成check imgsz
imgsz = check_img_size(imgsz, s=gs) # check image size
# Multi-GPU disabled, incompatible with .half() https://github.com/ultralytics/yolov5/issues/99
# if device.type != 'cpu' and torch.cuda.device_count() > 1:
# model = nn.DataParallel(model)
# Data
data = check_dataset(data) # check
训练时(train.py)调用:初始化模型参数、训练设备
验证时(val.py)调用:初始化设备、save_dir文件路径、make dir、加载模型、check imgsz、 加载+check data配置信息
# Half model 只能在单GPU设备上才能使用
# 一旦使用half, 不但模型需要设为half, 输入模型的图片也需要设为half
half &= device.type != 'cpu' # half precision only supported on CUDA
if half:
model.half()
# Configure
model.eval()# 启动模型验证模式
半精度验证half model + 模型剪枝prune + 模型融合conv+bn
# 测试数据是否是coco数据集
is_coco = isinstance(data.get('val'), str) and data['val'].endswith('coco/val2017.txt') # COCO dataset
nc = 1 if single_cls else int(data['nc']) # number of classes
# 计算mAP相关参数
# 设置iou阈值 从0.5-0.95取10个(0.05间隔) iou vector for [email protected]:0.95
iouv = torch.linspace(0.5, 0.95, 10).to(device) # iou vector for [email protected]:0.95
niou = iouv.numel()
是否是coco数据集is_coco + 类别个数nc + 计算mAP相关参数 + 初始化日志 Logging
# Dataloader
# 如果不是训练(执行val.py脚本调用run函数)就调用create_dataloader生成dataloader
# 如果是训练(执行train.py调用run函数)就不需要生成dataloader 可以直接从参数中传过来testloader
if not training:
if device.type != 'cpu':
# 这里创建一个全零数组测试下前向传播是否能够正常运行
model(torch.zeros(1, 3, imgsz, imgsz).to(device).type_as(next(model.parameters()))) # run once
task = task if task in ('train', 'val', 'test') else 'val' # path to train/val/test images
# 创建dataloader 这里的rect默认为True 矩形推理用于测试集 在不影响mAP的情况下可以大大提升推理速度
dataloader = create_dataloader(data[task], imgsz, batch_size, gs, single_cls, pad=0.5, rect=True,
prefix=colorstr(f'{task}: '))[0]
训练时(train.py)调用:加载val数据集
验证时(val.py)调用:不需要加载val数据集 直接从train.py 中传入testloader
# 初始化一些测试需要的参数
seen = 0
# 初始化混淆矩阵
confusion_matrix = ConfusionMatrix(nc=nc)
# 获取数据集所有类别的类名
names = {k: v for k, v in enumerate(model.names if hasattr(model, 'names') else model.module.names)}
class_map = coco80_to_coco91_class() if is_coco else list(range(1000))
# 设置tqdm进度条的显示信息
s = ('%20s' + '%11s' * 6) % ('Class', 'Images', 'Labels', 'P', 'R', '[email protected]', '[email protected]:.95')
# 初始化p, r, f1, mp, mr, map50, map指标和时间t0, t1, t2
dt, p, r, f1, mp, mr, map50, map = [0.0, 0.0, 0.0], 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
# 初始化测试集的损失
loss = torch.zeros(3, device=device)
# 初始化json文件中的字典 统计信息 ap等
jdict, stats, ap, ap_class = [], [], [], []
初始化混淆矩阵 + 数据集类名 + 获取coco数据集的类别索引 + 设置tqdm进度条 + 初始化p, r, f1, mp, mr, map50, map指
标和时间t0, t1, t2 + 初始化测试集的损失 + 初始化json文件中的字典 统计信息 ap等