0 声明
作者联系方式:E-mail: WindForest@yeah.net
本文用于使用Featurize平台在VOC0712数据集上基于Darknet训练YOLO-Fastest的过程参考。
本文仅为个人学习记录,由本文的错误造成的损失,作者概不负责。
项 | 说明 |
---|---|
训练平台 | Featurize |
训练框架 | Darknet |
网络模型 | YOLO-Fastest1.0-XL |
数据集 | VOC2007-2012联合数据集(20分类) |
网络输入 | 320×320 |
cuDNN | cudnn-11.2-linux-x64-v8.1.1.33.tgz 提取码: sese |
1 正文
1.1 框架和数据集准备
由于Darknet框架是基于C语言的,因此在获取到YOLO-Fastest工程之后需要先编译该框架才能进行训练,编译过程需要cuDNN的参与,截至本文发布,Featurize平台提供的实例是基于CUDA11.2的,故选用 cudnn-11.2-linux-x64-v8.1.1.33 。
我们先来做一些准备:首先将该cuDNN压缩包上传到 /work 目录下,该目录下的内容将被持久保留,且后续再申请实例的时候该目录是共享的;由于Darknet环境不包含在实例镜像中,因此每次申请实例都需要重新编译,为了方便起见,我们也把YOLO-Fastest工程从Github上下载并以zip方式保存到该目录,如下图所示。
上述操作可能需要花些时间,因此可以随便申请一个便宜的实例完成,而后再转到要用的配置继续下面的操作。
至此,我们已经准备好了可用于训练的框架,首先解压cuDNN和YOLO-Fastest工程到 ~/ 目录:
# 1 准备cuDNN
cd && sudo tar -zxvf work/cudnn-11.2-linux-x64-v8.1.1.33.tgz -C /usr/local/
# 2 解压YOLO-Fastest工程
cd && unzip work/Yolo-Fastest.zip -d ~/ && mv Yolo-Fastest-master Yolo-Fastest
然后我们需要修改 Yolo-Fastest/Makefile 和 Yolo-Fastest/src/utils.c 文件中的内容。
对于Makefile,我们需要修改三个位置:
# 关闭OpenCV支持
- OPENCV=1
+ OPENCV=0
# 开启对对应GPU架构的支持
- # ARCH= -gencode arch=compute_86,code=[sm_86,compute_86]
+ ARCH= -gencode arch=compute_86,code=[sm_86,compute_86]
# 更改cuDNN路径
- CFLAGS+= -DCUDNN -I/usr/local/cudnn/include
- LDFLAGS+= -L/usr/local/cudnn/lib64 -lcudnn
+ CFLAGS+= -DCUDNN -I/usr/local/cuda/include
+ LDFLAGS+= -L/usr/local/cuda/lib64 -lcudnn
保存并退出,而后我们在utils.c中增加对一会儿要用到的数据集路径的支持:
// 找到此函数:
void replace_image_to_label(const char* input_path, char* output_path)
{
// ...删掉其它find_replace函数调用,然后增加:
find_replace(input_path, "voc-images", "voc-labels", output_path);
// ...
}
保存并退出,我们回到YOLO-Fastest工程目录下,执行以下命令编译:
cd Yolo-Fastest
export PATH=/usr/local/cuda/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
make -j8
至此,Darknet框架环境已经准备完成。
然后我们在导航页 添加数据集 中找到 VOC2007-2012联合数据集(Darknet-YOLO) 并在实例中下载,该数据集为本文使用示例,你当然可以添加自己的数据集,不过要记得对应地修改utils.c和后续的Anchors。
数据集将被下载到 ~/data/ 目录下,但数据集制作时的路径是 data/ALLIMGS/ 因此我们需要将下载好的数据集移动到YOLO-Fastest工程中:
# 3 数据集准备
cd && mkdir Yolo-Fastest/data/ALLIMGS && mkdir Yolo-Fastest/models && rm -rf Yolo-Fastest/cfg/*
mv data/voc-images Yolo-Fastest/data/ALLIMGS
mv data/voc-labels Yolo-Fastest/data/ALLIMGS
mv data/voc.data Yolo-Fastest/data/ALLIMGS/
mv data/voc.names Yolo-Fastest/data/ALLIMGS/
mv data/voc_test.txt Yolo-Fastest/data/ALLIMGS/
mv data/voc_train.txt Yolo-Fastest/data/ALLIMGS/
至此,用于训练的数据集也已经准备好了。
1.2 网络准备
从YOLO-Fastest工程目录下的 ModelZoo\yolo-fastest-1.0_coco 目录获取 yolo-fastest-xl.cfg 拷贝到 cfg 目录下;yolo-fastest-xl.weights 拷贝到 models 目录下。然后打开 yolo-fastest-xl.cfg 文件,根据机器性能和训练要求等修改训练参数,而后保存。
值得注意的是:网络训练的学习率、调整步长和衰减对网络收敛和最终效果有相当大的关系,需要慎重设置。
学习率设置示例:
learning_rate=0.002 burn_in=8000 max_batches=51900 policy=steps steps=17300,34600,43250 scales=.5,.1,.1
经过对比,当采用单精度训练方案时,使用GTX3080是性价比最优的选择,此时batchsize可设置为64,subdivisions设置为2。
接着,在网络配置文件中修改yolo网络层使用的Anchors,对于本次示例,可使用:
26, 49, 64, 93, 75,186, 185,126, 141,242, 265,262
同时需要修改yolo网络层的输出张量和classes设置,一共有2个yolo网络层需要修改。
Anchors可使用Darknet提供的以下命令计算得到:
# 4 计算Anchors
cd && cd Yolo-Fastest/
./darknet detector calc_anchors data/ALLIMGS/voc.data -num_of_clusters 6 -width 320 -height 320
1.3 网络训练
最后,我们使用以下命令开始训练:
# 网络训练
cd && cd Yolo-Fastest/
# 首先提取骨干网络权重,这里109层是根据网络结构得到的最后一层骨干网络的层号
./darknet partial ./cfg/yolo-fastest-xl.cfg ./models/yolo-fastest-xl.weights ./models/yolo-fastest-xl_conv.109 109
# 使用预训练权重执行训练
./darknet detector train ./data/ALLIMGS/voc.data ./cfg/yolo-fastest-xl.cfg ./models/yolo-fastest-xl_conv.109 >> yolo-fastest-xl_train.log
# 从头开始训练,此时不需要预训练权重
./darknet detector train ./data/ALLIMGS/voc.data ./cfg/yolo-fastest-xl.cfg >> yolo-fastest-xl_train.log
此时终端上将打印训练时的信息,每次迭代的损失之变化将被记录到 ./yolo-fastest-xl_train.log 文件中,可用于后续绘制损失曲线。
训练进程不断有打印信息因此会占据一个终端,因此可以再开一个终端窗口实时刷新打印到日志里的损失值信息:
cd && watch -n 1 "tail -n 1 Yolo-Fastest/yolo-fastest-xl_train.log"
说明:由于burn_in参数,训练初期学习率会缓慢增加,因此一开始显示0.000000是正常的。
1.4 网络评估
网络训练完成后,可使用Darknet网络提供的工具查看训练效果,例如mAP计算:
./darknet detector map ./data/ALLIMGS/voc.data ./cfg/yolo-fastest-xl.cfg ./models/yolo-fastest-xl_final.weights
但因为我们在编译时没有勾选OpenCV(为了加快训练速度),因此不能在实例中查看预测结果,只能在本机上重新编译一下Darknet工程来查看效果,这个过程已经在《YOLO系列(v1~v3)的学习及YOLO-Fastest在海思平台的部署(下)》中介绍过了,不再赘述。
最后,我们可以使用以下脚本保存的训练日志绘制网络训练过程中的损失值变化曲线。
# ----------------------------------------------------------------------
# Darknet损失函数处理
# NOTE:使用Darknet训练网络时使用“>>”指定输出到文件,即可保存训练过程中的
# Loss变化信息,本脚本将从这些信息中提取Loss值并绘制曲线。
# NOTE:python ./Darknet_Loss_Process.py darknet_output_file
# ----------------------------------------------------------------------
import sys
import os
import matplotlib.pyplot as plt
# --------------------------------------------------
# 全局变量
# --------------------------------------------------
darknet_output_filename = sys.argv[1]
x_iters = []
y_1_loss = []
y_2_loss = []
# --------------------------------------------------
# 处理流程
# --------------------------------------------------
print("Current Loss Log: " + darknet_output_filename)
darknet_output_file = open(darknet_output_filename, 'r')
for line in darknet_output_file.readlines():
if "avg loss" in line:
line_list = line.replace(',', '').replace(':', '').split(" ")
x_iters.append(float(line_list[1]))
y_1_loss.append(float(line_list[2]))
y_2_loss.append(float(line_list[3]))
darknet_output_file.close()
_, ax1 = plt.subplots()
ax1.set_title("Darknet Loss Log")
ax1.plot(x_iters, y_1_loss, 'green', alpha=0.5)
ax1.set_xlabel('Iteration')
ax1.set_ylabel('Loss Value')
ax2 = ax1.twinx()
ax2.plot(x_iters, y_2_loss, 'red', alpha=0.8)
plt.show()
2 总结
本文其实没什么东西,主要是为了帮助刚刚接触JupyterLab的同学快速上手Darknet训练过程,以上。
———— 2022-1-22@燕卫博 ————