前言
最近在为秋招做准备,回顾到参加过的Kaggle比赛,发现还没有完整地整理一下代码。
我们HellooHalo组(没错就这么随性hhh<3)的最高名次曾经在锁榜后达到过前百,不过很可惜后面因为YoloV5的license is not MIT compliant,导致Notebook被删成绩取消。也算是我为什么很长时间不愿意去回顾这个项目的原因,实在太痛了。。
第二次rerun private testset后的leader board,还勉强踩了个银牌的尾巴。
Anyways,虽然槽点很多,但是作为YOLOv5的第一次实战,还是给我提供了不少宝贵的经验。
目前很多排行榜前列的大神都发表了他们的Notebook,这篇文章也会对其中有价值的tricks作出总结和提炼。可以点击这里查看
为什么要用YOLOv5?
江大白的YOLOv5总结
这篇文章对YOLOv5总结的非常好,感兴趣的朋友可以通读一下,收获很大。对于Global Wheat这个任务,最关键的性能提升体现在:
- Mosaic拼接数据增强。增强了对于小目标的检测效率。
- 可选的多个模型。这里我们用YOLOv5x,CSP结构赋予了很强的特征提取能力,它有着4个残差结构。
- 根据作者在github上发表的性能对比,YOLOv5比YOLOv3&4明显强,甚至强于当前的two-stage SOTA EfficientDet。(插一句,下一篇我打算写一片基于pytorch从头搭建EfficientDet的文章)
其实说这么多,还是因为discussion board上有大佬试出来YOLOv5的效果很好。。这种东西80%都是玄学,不可说。。
Notebook 代码
我将以Kaggle Notebook上的运行顺序详细介绍每一步的操作和注意事项,争取能帮助读者复用到其他的任务上。
导包和安装YOLOV5
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import os
from tqdm.auto import tqdm
import shutil as sh
!pip install --no-deps '../input/weightedboxesfusion/' > /dev/null
数据格式转化
好的我知道我前面留下来一个坑,就是各类型数据转化的代码和讲解,我会在一周内补上的。
def convertTrainLabel():
df = pd.read_csv('../input/global-wheat-detection/train.csv')
# 取出bbox[xmin, ymin, w, h]格式
bboxs = np.stack(df['bbox'].apply(lambda x: np.fromstring(x[1:-1], sep=',')))
for i, column in enumerate(['x', 'y', 'w', 'h']):
df[column] = bboxs[:,i]
df.drop(columns=['bbox'], inplace=True)
df['x_center'] = df['x'] + df['w']/2
df['y_center'] = df['y'] + df['h']/2
df['classes'] = 0
from tqdm.auto import tqdm
# 整理成df,格式看下面
df = df[['image_id','x', 'y', 'w', 'h','x_center','y_center','classes']]
index = list(set(df.image_id))
# 在train的过程中按照val和train 分开放入不同的dir
source = 'train'
if True:
for fold in [0]:
val_index = index[len(index)*fold//5:len(index)*(fold+1)//5]
for name,mini in tqdm(df.groupby('image_id')):
if name in val_index:
path2save = 'val2017/'
else:
path2save = 'train2017/'
if not os.path.exists('convertor/fold{}/labels/'.format(fold)+path2save):
os.makedirs('convertor/fold{}/labels/'.format(fold)+path2save)
with open('convertor/fold{}/labels/'.format(fold)+path2save+name+".txt", 'w+') as f:
row = mini[['classes','x_center','y_center','w','h']].astype(float).values
row = row/1024
row = row.astype(str)
for j in range(len(row)):
text = ' '.join