0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

val.py源码解读

jf_pmFSk4VX 来源:GiantPandaCV 作者:冯文 2023-02-20 14:50 次阅读

1.导入需要的包和基本配置

importargparse#解析命令行参数模块
importjson#字典列表和JSON字符串之间的相互解析模块
importos#与操作系统进行交互的模块包含文件路径操作和解析
importsys#sys系统模块包含了与Python解释器和它的环境有关的函数
frompathlibimportPath#Path将str转换为Path对象使字符串路径易于操作的模块

importnumpyasnp#NumPy(NumericalPython)是Python的一种开源的数值计算扩展
importoneflowasflow#OneFlow深度学习框架
fromtqdmimporttqdm#进度条模块

frommodels.commonimportDetectMultiBackend#下面都是one-yolov5定义的模块,在本系列的其它文章都有涉及
fromutils.callbacksimportCallbacks
fromutils.dataloadersimportcreate_dataloader
fromutils.generalimport(
LOGGER,
check_dataset,
check_img_size,
check_requirements,
check_yaml,
coco80_to_coco91_class,
colorstr,
increment_path,
non_max_suppression,
print_args,
scale_coords,
xywh2xyxy,
xyxy2xywh,
)
fromutils.metricsimportConfusionMatrix,ap_per_class,box_iou
fromutils.oneflow_utilsimportselect_device,time_sync
fromutils.plotsimportoutput_to_target,plot_images,plot_val_study

2.opt参数详解

参数 解析
data dataset.yaml path 数据集配置文件地址 包含数据集的路径、类别个数、类名、下载地址等信息
weights model weights path(s) 模型的权重文件地址 weights/yolov5s
batch-size batch size 计算样本的批次大小 默认32
imgsz inference size (pixels) 输入网络的图片分辨率 默认640
conf-thres confidence threshold object置信度阈值 默认0.001
iou-thres NMS IoU threshold 进行NMS时IOU的阈值 默认0.6
task train, val, test, speed or study 设置测试的类型 有train, val, test, speed or study几种 默认val
device cuda device, i.e. 0 or 0,1,2,3 or cpu 测试的设备
workers max dataloader workers (per RANK in DDP mode) 加载数据使用的 dataloader workers
single-cls treat as single-class dataset 数据集是否只用一个类别 默认False
augment augmented inference 测试是否使用TTA Test Time Augment 默认False
verbose report mAP by class 是否打印出每个类别的mAP 默认False
save-hybrid save label+prediction hybrid results to *.txt 保存label+prediction 杂交结果到对应.txt 默认False
save-conf save confidences in --save-txt labels
save-json save a COCO-JSON results file 是否按照coco的json格式保存结果 默认False
project save to project/name 测试保存的源文件 默认runs/val
name save to project/name 测试保存的文件地址名 默认exp 保存在runs/val/exp下
exist-ok existing project/name ok, do not increment 是否保存在当前文件,不新增 默认False
half use FP16 half-precision inference 是否使用半精度推理 默认False
dnn use OpenCV DNN for ONNX inference 是否使用 OpenCV DNN 对 ONNX 模型推理

3.main函数

根据解析的opt参数,调用run函数

defmain(opt):
#检测requirements文件中需要的包是否安装好了
check_requirements(requirements=ROOT/"requirements.txt",exclude=("tensorboard","thop"))

ifopt.taskin("train","val","test"):#runnormally
ifopt.conf_thres>0.001:#更多请见https://github.com/ultralytics/yolov5/issues/1466
LOGGER.info(f"WARNING:confidencethreshold{opt.conf_thres}>0.001producesinvalidresults")
run(**vars(opt))

else:
weights=opt.weightsifisinstance(opt.weights,list)else[opt.weights]
opt.half=True#FP16forfastestresults
ifopt.task=="speed":#speedbenchmarks
#pythonval.py--taskspeed--datacoco.yaml
#--batch1--weightsyolov5n/yolov5s/...
opt.conf_thres,opt.iou_thres,opt.save_json=0.25,0.45,False
foropt.weightsinweights:
run(**vars(opt),plots=False)

elifopt.task=="study":#speedvsmAPbenchmarks
#pythonval.py--taskstudy--datacoco.yaml
#--iou0.7--weightsyolov5n/yolov5s/...
foropt.weightsinweights:
f=f"study_{Path(opt.data).stem}_{Path(opt.weights).stem}.txt"
x,y=(
list(range(256,1536+128,128)),
[],
)#xaxis(imagesizes),yaxis
#"study":模型在各个尺度下的指标并可视化,
#上面list(range(256,1536+128,128)),代表img-size的各个尺度,具体代码如下:
foropt.imgszinx:#img-size
LOGGER.info(f"
Running{f}--imgsz{opt.imgsz}...")
r,_,t=run(**vars(opt),plots=False)
y.append(r+t)#resultsandtimes
np.savetxt(f,y,fmt="%10.4g")#save
os.system("zip-rstudy.zipstudy_*.txt")
#可视化各个指标
plot_val_study(x=x)#plot

3. run函数

3.1 载入参数

#不参与反向传播
@flow.no_grad()
defrun(
data,#数据集配置文件地址包含数据集的路径、类别个数、类名、下载地址等信息train.py时传入data_dict
weights=None,#模型的权重文件地址运行train.py=None运行test.py=默认weights/yolov5s
batch_size=32,#前向传播的批次大小运行test.py传入默认32运行train.py则传入batch_size//WORLD_SIZE*2
imgsz=640,#输入网络的图片分辨率运行test.py传入默认640运行train.py则传入imgsz_test
conf_thres=0.001,#object置信度阈值默认0.001
iou_thres=0.6,#进行NMS时IOU的阈值默认0.6
task="val",#设置测试的类型有train,val,test,speedorstudy几种默认val
device="",#执行val.py所在的设备cudadevice,i.e.0or0,1,2,3orcpu
workers=8,#dataloader中的最大worker数(线程个数)
single_cls=False,#数据集是否只有一个类别默认False
augment=False,#测试时增强,详细请看我们的教程:https://start.oneflow.org/oneflow-yolo-doc/tutorials/03_chapter/TTA.html
verbose=False,#是否打印出每个类别的mAP运行test.py传入默认Fasle运行train.py则传入nc< 50 and final_epoch
    save_txt=False,  # 是否以txt文件的形式保存模型预测框的坐标 默认True
    save_hybrid=False,  # 是否save label+prediction hybrid results to *.txt  默认False
    save_conf=False,  # 是否保存预测每个目标的置信度到预测txt文件中 默认True
    save_json=False,  # 是否按照coco的json格式保存预测框,并且使用cocoapi做评估(需要同样coco的json格式的标签),
                      #运行test.py传入默认Fasle 运行train.py则传入is_coco and final_epoch(一般也是False)
    project=ROOT / "runs/val",  # 验证结果保存的根目录 默认是 runs/val
    name="exp",   # 验证结果保存的目录 默认是exp  最终: runs/val/exp
    exist_ok=False,  # 如果文件存在就increment name,不存在就新建  默认False(默认文件都是不存在的)
    half=True,    # 使用 FP16 的半精度推理
    dnn=False,    # 在 ONNX 推理时使用 OpenCV DNN 后段端
    model=None,   # 如果执行val.py就为None 如果执行train.py就会传入( model=attempt_load(f, device).half() )
    dataloader=None,   # 数据加载器 如果执行val.py就为None 如果执行train.py就会传入testloader
    save_dir=Path(""), # 文件保存路径 如果执行val.py就为‘’ , 如果执行train.py就会传入save_dir(runs/train/expn)
    plots=True,  # 是否可视化 运行val.py传入,默认True 
    callbacks=Callbacks(), 
    compute_loss=None, # 损失函数 运行val.py传入默认None 运行train.py则传入compute_loss(train)
):

3.2 Initialize/load model and set device(初始化/加载模型以及设置设备)

iftraining:#通过train.py调用的run函数
device,of,engine=(
next(model.parameters()).device,
True,
False,
)#getmodeldevice,OneFlowmodel
half&=device.type!="cpu"#halfprecisiononlysupportedonCUDA
model.half()ifhalfelsemodel.float()
else:#直接通过val.py调用run函数
device=select_device(device,batch_size=batch_size)

#Directories生成save_dir文件路径run/val/expn
save_dir=increment_path(Path(project)/name,exist_ok=exist_ok)#incrementrun
(save_dir/"labels"ifsave_txtelsesave_dir).mkdir(parents=True,exist_ok=True)#makedir

#加载模型只在运行val.py才需要自己加载model
model=DetectMultiBackend(weights,device=device,dnn=dnn,data=data,fp16=half)

stride,of,engine=model.stride,model.of,model.engine
#检测输入图片的分辨率imgsz是否能被stride整除
imgsz=check_img_size(imgsz,s=stride)#checkimagesize
half=model.fp16#FP16supportedonlimitedbackendswithCUDA
ifengine:
batch_size=model.batch_size
else:
device=model.device
ifnotof:
batch_size=1#export.pymodelsdefaulttobatch-size1
LOGGER.info(f"Forcing--batch-size1inference(1,3,{imgsz},{imgsz})fornon-OneFlowmodels")

#Data
data=check_dataset(data)#check

3.3 Configure

#配置
model.eval()#启动模型验证模式
cuda=device.type!="cpu"
is_coco=isinstance(data.get("val"),str)anddata["val"].endswith(f"coco{os.sep}val2017.txt")#通过COCO数据集的文件夹组织结构判断当前数据集是否为COCO数据集
nc=1ifsingle_clselseint(data["nc"])#numberofclasses
#设置iou阈值从0.5-0.95取10个(0.05间隔)iouvectorformAP@0.5:0.95
#iouv:[0.50000,0.55000,0.60000,0.65000,0.70000,0.75000,0.80000,0.85000,0.90000,0.95000]
iouv=flow.linspace(0.5,0.95,10,device=device)#iouvectorformAP@0.5:0.95
niou=iouv.numel()#示例mAP@0.5:0.95iou阈值个数=10个,计算mAP的详细教程可以在https://start.oneflow.org/oneflow-yolo-doc/tutorials/05_chapter/map_analysis.html这里查看

3.4 Dataloader

通过 train.py 调用 run 函数会传入一个 Dataloader,而通过 val.py 需要加载测试数据集

#Dataloader
#如果不是训练(执行val.py脚本调用run函数)就调用create_dataloader生成dataloader
#如果是训练(执行train.py调用run函数)就不需要生成dataloader可以直接从参数中传过来testloader
ifnottraining:#加载val数据集
ifofandnotsingle_cls:#check--weightsaretrainedon--data
ncm=model.model.nc
assertncm==nc,(
f"{weights}({ncm}classes)trainedondifferent--datathanwhatyoupassed({nc}"f"classes).Passcorrectcombinationof"f"--weightsand--datathataretrainedtogether."
)
model.warmup(imgsz=(1ifofelsebatch_size,3,imgsz,imgsz))#warmup
pad=0.0iftaskin("speed","benchmark")else0.5
rect=Falseiftask=="benchmark"elseof#squareinferenceforbenchmarks
task=taskiftaskin("train","val","test")else"val"#pathtotrain/val/testimages
#创建dataloader这里的rect默认为True矩形推理用于测试集在不影响mAP的情况下可以大大提升推理速度
dataloader=create_dataloader(
data[task],
imgsz,
batch_size,
stride,
single_cls,
pad=pad,
rect=rect,
workers=workers,
prefix=colorstr(f"{task}:"),
)[0]

3.5 初始化

#初始化验证的图片的数量
seen=0
#初始化混淆矩阵
confusion_matrix=ConfusionMatrix(nc=nc)

#获取数据集所有目标类别的类名
names=dict(enumerate(model.namesifhasattr(model,"names")elsemodel.module.names))

#coco80_to_coco91_class:converts80-index(val2014)to91-index(paper)
#https://tech.amikelive.com/node-718/what-object-categories-labels-are-in-coco-dataset/
class_map=coco80_to_coco91_class()ifis_cocoelselist(range(1000))
#设置进度条模块显示信息
s=("%20s"+"%11s"*6)%(
"Class",
"Images",
"Labels",
"P",
"R",
"mAP@.5",
"mAP@.5:.95",
)
#初始化时间dt[t0(预处理的时间),t1(推理的时间),t2(后处理的时间)]和p,r,f1,mp,mr,map50,map指标
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=flow.zeros(3,device=device)
#初始化json文件中的字典,统计信息,ap,ap_class
jdict,stats,ap,ap_class=[],[],[],[]
callbacks.run("on_val_start")
#初始化tqdm进度条模块
pbar=tqdm(dataloader,desc=s,bar_format="{l_bar}{bar:10}{r_bar}{bar:-10b}")
示例输出
val:data=data/coco.yaml,weights=['yolov5x'],batch_size=32,imgsz=640,conf_thres=0.001,iou_thres=0.6,task=val,
device=,workers=8,single_cls=False,augment=False,verbose=False,save_txt=False,save_hybrid=False,
save_conf=False,save_json=True,project=runs/val,name=exp,exist_ok=False,half=True,dnn=False
YOLOv5v1.0-8-g94ec5c4Python-3.8.13oneflow-0.8.1.dev20221018+cu112
Fusinglayers...
Modelsummary:322layers,86705005parameters,571965gradients
val:Scanning'/data/dataset/fengwen/coco/val2017.cache'imagesandlabels...4952found,48missing,0empty,0corrupt:100%|████████
ClassImagesLabelsPRmAP@.5mAP@.5:.95:100%|██████████|157/157[01:55<00:00,  1.36it/
                 all       5000      36335      0.743      0.627      0.685      0.503
Speed: 0.1ms pre-process, 7.5ms inference, 2.1ms NMS per image at shape (32, 3, 640, 640)  # <--- baseline speed

Evaluating pycocotools mAP... saving runs/val/exp3/yolov5x_predictions.json...

...
Average Precision  (AP) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.505 # <--- baseline mAP
 Average Precision  (AP) @[ IoU=0.50      | area=   all | maxDets=100 ] = 0.689
 Average Precision  (AP) @[ IoU=0.75      | area=   all | maxDets=100 ] = 0.545
 Average Precision  (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.339
 Average Precision  (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.557
 Average Precision  (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.650
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=  1 ] = 0.382
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets= 10 ] = 0.628
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.677  # <--- baseline mAR
 Average Recall     (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.523
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.730
 Average Recall     (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.826

3.6 开始验证

forbatch_i,(im,targets,paths,shapes)inenumerate(pbar):
"""https://github.com/Oneflow-Inc/one-yolov5/blob/bf8c66e011fcf5b8885068074ffc6b56c113a20c/utils/dataloaders.py#L735
im:flow.from_numpy(img);
targets:labels_out
paths:self.im_files[index]
shapes:shapes
"""

3.6.1 验证开始前的预处理

callbacks.run("on_val_batch_start")
t1=time_sync()
ifcuda:
im=im.to(device)
targets=targets.to(device)
im=im.half()ifhalfelseim.float()#uint8tofp16/32
im/=255#0-255to0.0-1.0
nb,_,height,width=im.shape#batchsize,channels,height,width
t2=time_sync()
dt[0]+=t2-t1

3.6.2 推理

#Inference
out,train_out=model(im)iftrainingelsemodel(im,augment=augment,val=True)#输出为:推理结果、损失值
dt[1]+=time_sync()-t2

3.6.3 计算损失

#Loss
"""
分类损失(cls_loss):该损失用于判断模型是否能够准确地识别出图像中的对象,并将其分类到正确的类别中。

置信度损失(obj_loss):该损失用于衡量模型预测的框(即包含对象的矩形)与真实框之间的差异。

边界框损失(box_loss):该损失用于衡量模型预测的边界框与真实边界框之间的差异,这有助于确保模型能够准确地定位对象。
"""
ifcompute_loss:
loss+=compute_loss([x.float()forxintrain_out],targets)[1]#box,obj,cls

3.6.4 Run NMS

#NMS
#将真实框target的xywh(因为target是在labelimg中做了归一化的)映射到真实的图像(test)尺寸
targets[:,2:]*=flow.tensor((width,height,width,height),device=device)#topixels
#在NMS之前将数据集标签targets添加到模型预测中,这允许在数据集中自动标记(forautolabelling)其它对象(在pred中混入gt)并且mAP反映了新的混合标签
#targets:[num_target,img_index+class_index+xywh]=[31,6]
#lb:{list:bs}第一张图片的target[17,5]第二张[1,5]第三张[7,5]第四张[6,5]
lb=[targets[targets[:,0]==i,1:]foriinrange(nb)]ifsave_hybridelse[]#forautolabelling
t3=time_sync()
"""non_max_suppression(非最大值抑制)
Non-MaximumSuppression(NMS)oninferenceresultstorejectoverlappingboundingboxes
该算法的原理:
先假设有6个矩形框,根据分类器的类别分类概率大小排序,假设从小到大属于车辆(被检测的目标)的概率分别为:A、B、C、D、E、F
(1)从最大概率矩形框F开始,分别判断A~E与F的重叠度IOU是否大于某个指定的阀值;
(2)假设B、D与F的重叠度大于指定的阀值,则丢弃B、D,并标记第一个矩形框F,是我们要保留的
(3)从剩下的矩形框A、C、E中,选择最大概率,假设为E,然后判断A、C与E的重叠度是否大于指定的阀值,
假如大于就丢弃A、C,并标记E,是我们保留下来的第二个矩形框
一直重复上述过程,找到所有被保留的矩形框
Returns:
listofdetections,on(n,6)tensorperimage[xyxy,conf,cls]
"""
out=non_max_suppression(out,conf_thres,iou_thres,labels=lb,multi_label=True,agnostic=single_cls)
#获取NMS时间
dt[2]+=time_sync()-t3

3.6.5 统计每张图片的真实框、预测框信息

#为每张图片做统计,写入预测信息到txt文件,生成json文件字典,统计tp等
#out:list{bs}[300,6][42,6][300,6][300,6][:,image_index+class+xywh]
forsi,predinenumerate(out):
#获取第si张图片的gt标签信息包括class,x,y,w,htarget[:,0]为标签属于哪张图片的编号
labels=targets[targets[:,0]==si,1:]#[:,class+xywh]
nl,npr=labels.shape[0],pred.shape[0]#numberoflabels,predictions
path,shape=Path(paths[si]),shapes[si][0]
correct=flow.zeros(npr,niou,dtype=flow.bool,device=device)#init
seen+=1#统计测试图片数量+1

ifnpr==0:#如果预测为空,则添加空的信息到stats里
ifnl:
stats.append((correct,*flow.zeros((2,0),device=device),labels[:,0]))
ifplots:
confusion_matrix.process_batch(detections=None,labels=labels[:,0])
continue
#Predictions
ifsingle_cls:
pred[:,5]=0
predn=pred.clone()
#将预测坐标映射到原图img中
scale_coords(im[si].shape[1:],predn[:,:4],shape,shapes[si][1])#native-spacepred

#Evaluate
ifnl:
tbox=xywh2xyxy(labels[:,1:5])#targetboxes
scale_coords(im[si].shape[1:],tbox,shape,shapes[si][1])#native-spacelabels
labelsn=flow.cat((labels[:,0:1],tbox),1)#native-spacelabels
correct=process_batch(predn,labelsn,iouv)
ifplots:
confusion_matrix.process_batch(predn,labelsn)
stats.append((correct,pred[:,4],pred[:,5],labels[:,0]))#(correct,conf,pcls,tcls)

#Save/log
#保存预测信息到txt文件runsvalexp7labelsimage_name.txt
ifsave_txt:
save_one_txt(
predn,
save_conf,
shape,
file=save_dir/"labels"/f"{path.stem}.txt",
)
ifsave_json:
save_one_json(predn,jdict,path,class_map)#appendtoCOCO-JSONdictionary
callbacks.run("on_val_image_end",pred,predn,path,names,im[si])

3.6.6 画出前三个batch图片的 gt 和 pred 框

gt : 真实框,Ground truth box, 是人工标注的位置,存放在标注文件中

pred : 预测框,Prediction box, 是由目标检测模型计算输出的框

#Plotimages
ifplotsandbatch_i< 3:
    plot_images(im, targets, paths, save_dir / f"val_batch{batch_i}_labels.jpg", names)  # labels
    plot_images(
        im,
        output_to_target(out),
        paths,
        save_dir / f"val_batch{batch_i}_pred.jpg",
        names,
    )  # pred

callbacks.run("on_val_batch_end")

3.7 计算指标

指标名字在代码中体现

#Computemetrics
stats=[flow.cat(x,0).cpu().numpy()forxinzip(*stats)]#tonumpy
iflen(stats)andstats[0].any():
tp,fp,p,r,f1,ap,ap_class=ap_per_class(*stats,plot=plots,save_dir=save_dir,names=names)
ap50,ap=ap[:,0],ap.mean(1)#AP@0.5,AP@0.5:0.95
mp,mr,map50,map=p.mean(),r.mean(),ap50.mean(),ap.mean()
nt=np.bincount(stats[3].astype(int),minlength=nc)#numberoftargetsperclass

3.8 打印日志

#Printresultsperclass
if(verboseor(nc< 50 and not training)) and nc >1andlen(stats):
fori,cinenumerate(ap_class):
LOGGER.info(pf%(names[c],seen,nt[c],p[i],r[i],ap50[i],ap[i]))

#Printspeeds
t=tuple(x/seen*1e3forxindt)#speedsperimage
ifnottraining:
shape=(batch_size,3,imgsz,imgsz)
LOGGER.info(f"Speed:%.1fmspre-process,%.1fmsinference,%.1fmsNMSperimageatshape{shape}"%t)

3.9 保存验证结果

#Plots
ifplots:
confusion_matrix.plot(save_dir=save_dir,names=list(names.values()))
callbacks.run("on_val_end")

#SaveJSON
ifsave_jsonandlen(jdict):
w=Path(weights[0]ifisinstance(weights,list)elseweights).stemifweightsisnotNoneelse""#weights
anno_json=str(Path(data.get("path","../coco"))/"annotations/instances_val2017.json")#annotationsjson
pred_json=str(save_dir/f"{w}_predictions.json")#predictionsjson
LOGGER.info(f"
EvaluatingpycocotoolsmAP...saving{pred_json}...")
withopen(pred_json,"w")asf:
json.dump(jdict,f)
#try-catch,会有哪些error
"""
pycocotools介绍:
https://github.com/cocodataset/cocoapi/blob/master/PythonAPI/pycocoEvalDemo.ipynb
尝试:
使用pycocotools工具计算loss
COCOAPI-http://cocodataset.org/
失败error:
直接打印抛出的异常
1.可能没有安装pycocotools,但是网络有问题,无法实现自动下载。
2.pycocotools包版本有问题
"""
try:#https://github.com/cocodataset/cocoapi/blob/master/PythonAPI/pycocoEvalDemo.ipynb
check_requirements(["pycocotools"])
frompycocotools.cocoimportCOCO
frompycocotools.cocoevalimportCOCOeval

anno=COCO(anno_json)#initannotationsapi
pred=anno.loadRes(pred_json)#initpredictionsapi
eval=COCOeval(anno,pred,"bbox")
ifis_coco:
eval.params.imgIds=[int(Path(x).stem)forxindataloader.dataset.im_files]#imageIDstoevaluate
eval.evaluate()
eval.accumulate()
eval.summarize()
map,map50=eval.stats[:2]#updateresults(mAP@0.5:0.95,mAP@0.5)
exceptExceptionase:
LOGGER.info(f"pycocotoolsunabletorun:{e}")

3.10 返回结果

#Returnresults
model.float()#fortraining
ifnottraining:
s=f"
{len(list(save_dir.glob('labels/*.txt')))}labelssavedto{save_dir/'labels'}"ifsave_txtelse""
LOGGER.info(f"Resultssavedto{colorstr('bold',save_dir)}{s}")
maps=np.zeros(nc)+map
fori,cinenumerate(ap_class):
maps[c]=ap[i]
return(mp,mr,map50,map,*(loss.cpu()/len(dataloader)).tolist()),maps,t





审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • NMS
    NMS
    +关注

    关注

    0

    文章

    9

    浏览量

    6021
  • python
    +关注

    关注

    56

    文章

    4782

    浏览量

    84449
  • JSON
    +关注

    关注

    0

    文章

    117

    浏览量

    6940
  • 解释器
    +关注

    关注

    0

    文章

    103

    浏览量

    6494

原文标题:《YOLOv5全面解析教程》​十六,val.py 源码解读

文章出处:【微信号:GiantPandaCV,微信公众号:GiantPandaCV】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Faster Transformer v2.1版本源码解读

    写在前面 :本文将对 Faster Transformer v2.1 版本源码进行解读,重点介绍该版本基于 v1.0 和 v2.0 所做的优化内容,剖析源码作者优化意图。 1 v2.1 版本发布背景
    的头像 发表于 09-19 11:39 1337次阅读
    Faster Transformer v2.1版本<b class='flag-5'>源码</b><b class='flag-5'>解读</b>

    OneFlow Softmax算子源码解读之BlockSoftmax

    写在前面:笔者这段时间工作太忙,身心俱疲,博客停更了一段时间,现在重新捡起来。本文主要解读 OneFlow 框架的第二种 Softmax 源码实现细节,即 block 级别的 Softmax。
    的头像 发表于 01-08 09:26 658次阅读
    OneFlow Softmax算子<b class='flag-5'>源码</b><b class='flag-5'>解读</b>之BlockSoftmax

    【HarmonyOS IPC 试用连载 】鸿蒙源码编译报错 无法找到build.py的错误

    现象描述:搭建好环境,下载源代码,编译报错。NameError: name 'build' is not defined可能原因在源码主目录执行 ll 命令:发现 build.py的链接丢失,可能是
    发表于 10-20 11:25

    【HarmonyOS】鸿蒙源码编译报错 无法找到build.py的错误

    ' is not defined复制代码 可能原因在源码主目录执行 ll 命令: 发现 build.py的链接丢失,可能是使用window下解压源码导致的,因为在windows下的文件没有链接这个概念
    发表于 10-20 17:13

    AP侧中网相关的PLMN业务源码流程解读

    的运营商相关信息获取的业务,比如我们常见的手机状态栏上的运营商名称显示。下面来针对 AP 侧中搜网相关的 PLMN 业务解读源码流程。
    发表于 03-24 15:48

    51单片机拼音中文输入法c程序源代码

    拼音输入法杳询函数: unsigned char code * py_ime(unsigned char input_py_val[]); input_py_val为已输入的拼音码字符串头指针, 反回值为中文的起始地址,当为
    发表于 07-26 14:34 222次下载

    海尔29F3A-PY、29F9B-PY(100赫兹)彩电电路

    海尔29F3A-PY彩电电路图海尔29F3A-PY彩色电视机电路图,海尔29F3A-PY彩电图纸,海尔29F3A-PY原理图。
    发表于 05-06 17:55 310次下载
    海尔29F3A-<b class='flag-5'>PY</b>、29F9B-<b class='flag-5'>PY</b>(100赫兹)彩电电路

    51单片机的中文拼音输入法-c语言源程序

    51单片机的中文拼音输入法-c语言源程序:拼音输入法杳询函数: unsigned char code * py_ime(unsigned char input_py_val[]);input_py_val为已输入的拼音码字符串头
    发表于 08-23 11:00 142次下载

    基于MCU的U盘源码实现flash的windos文件系统

    基于MCU的U盘源码实现flash的windos文件系统.rar #include "d12ci.h"#include "main.h"//#include "44b.h" extern
    发表于 02-24 14:37 11次下载

    spider.py代码

    spider.py代码,感兴趣的可以看看。
    发表于 03-24 16:14 0次下载

    基于EAIDK的人脸算法应用-源码解读(2)

    上一期介绍了基于EAIDK的人脸算法应用,本期从应用角度,解读一下该案例源码。本期案例源码解读,主要从源码目录结构、配置文件、模型目...
    的头像 发表于 12-10 21:14 850次阅读

    openharmony源码解读

    如何获取OpenHarmony源码并说明OpenHarmony的源码目录结构。OpenHarmony的代码以组件的形式开放,开发者可以通过如下其中一种方式获取:
    的头像 发表于 06-24 09:29 3779次阅读

    低电容单向双ESD保护二极管-MMBZ15VAL-Q

    低电容单向双ESD保护二极管-MMBZ15VAL-Q
    发表于 02-09 19:26 0次下载
    低电容单向双ESD保护二极管-MMBZ15<b class='flag-5'>VAL</b>-Q

    Faster Transformer v1.0源码详解

    解读的内容仅限 Faster Transformer v1.0 版本,更高版本的源码将在后续文章中继续解读
    的头像 发表于 09-08 10:20 925次阅读
    Faster Transformer v1.0<b class='flag-5'>源码</b>详解

    Auto-py-to-exe:将Python脚本转为Exe的流程

    Auto-py-to-exe 能够基于简单的GUI图形界面和Python中的 PyInstaller,将.py转换为.exe,非常容易使用,适合那些需要在windows上直接执行py文件但又
    的头像 发表于 10-31 11:02 2309次阅读
    Auto-<b class='flag-5'>py</b>-to-exe:将Python脚本转为Exe的流程