怎样训练YOLOv3
怎样训练YOLOv3
Training YOLOv3 : Deep Learning based Custom Object Detector
本文将在一些公开的雪人图片和视频上分享训练过程、有助于训练的脚本和结果。可以使用相同的过程来训练具有多个目标检测。
先下载代码,例如,
下载地址一:https://github.com/madhawav/YOLO3-4-Py
下载地址二:https://github.com/Eric3911/yolov3_darknet
1. 数据集
与任何深度学习任务一样,第一个最重要的任务是准备数据集。将使用谷歌OpenImagesV4数据集中的雪人图片,该数据集在网上公开发布。它是一个很大的数据集,大约有600个不同的对象类。数据集还包含这些对象的边界框批注。整体而言,数据集超过500GB,但将下载部分用于非商用产品开发的带有“雪人”对象的图像。
1.1 Download data
First we will need to install awscli
sudo
pip3
install
awscli
需要得到相关的openImages文件,class-descriptions-boxable.csv 和
train-annotations-bbox.csv (1.11GB) ,需要找到感兴趣的目标文件。
|
|
Next, move the above .csv files to the same folder as the downloaded code and then use the following script to download the data
随后,将above.csv文件移动到与下载的代码相同的文件夹中,使用以下脚本下载数据。
python3 getDataFromOpenImages_snowman.py
图像下载到JPEGImages文件夹,相应的标签文件写入labels文件夹。下载将获得770个雪人实例539张图片。jpeg图像和标签的大小都应该小于136mb。 对于多类目标检测,需要为每个类提供更多的样本,需要获得测试test-annotations-bbox.csv 和验证validation-annotations-bbox.csv,然后在python脚本中修改运行模式,重新运行以获取每个类的更多图像。在目前的雪人案例中,770个实例就足够了。
1.2 分段训练测试
机器学习训练过程都需要先将数据随机分成两组。
训练集:这是训练模型的数据部分。根据拥有的数据量,可以随机选择70%到90%的数据进行训练。
测试集:用来测试模型的数据的一部分,10-30%的数据。图像不应该是训练和测试集的一部分。
将JPEGImages文件夹中的图像分成训练和测试集。用下面的splitTrainAndTest.py脚本,将JPEGImages文件夹的完整路径作为参数传递。
python3 splitTrainAndTest.py /full/path/to/snowman/JPEGImages/
上面的脚本将数据分成一列(90%)和一个测试集(10%),并生成两个文件snowman_train.txt 和snowman_test.txt。
2. Darknet
使用Joseph Redmon的Darknet版本,这是一个用C语言编写的深度学习框架。
2.1 Download and build Darknet
Let’s first download and build it on your system.
|
|
|
|
2.2 Modify code to save model files regularly
在确保原始repo在您的系统中编译之后,让我们进行一些小的修改以存储中间权重。在examples/detector.c文件中,从
if(i%10000==0 || (i < 1000 && i%100 == 0)){
到
if(i%1000==0 || (i < 2000 && i%200 == 0)){
原始repo在每100次迭代后保存网络权重,直到第一次1000次,然后仅在每10000次迭代后保存。由于只使用一个类进行训练,希望训练收敛得更快。为了密切监视进度,每200次迭代后保存一次,直到达到2000次,然后每1000次迭代后保存一次。再次使用make命令重新编译darknet。使用NVIDIA GeForce GTX 1080 GPU进行了实验。现在了解一些成功运行训练所需的更多详细信息。
3. 数据注释
已将标签文件与“标签”文件夹中的批注共享。标签文件中的每个行条目表示图像中的单个边界框,并包含有关该框的以下信息:
<object-class-id> <center-x> <center-y> <width> <height>
第一个字段object-class-id是表示目标类。它的范围从0到(类数–1)。在现在的例子中,由于只有一个雪人等级,所以它总是设置为0。
第二个和第三个条目center-x和center-y分别是边框中心的x和y坐标,分别被图像宽度和高度规范化(除以)。
第四项和第五项、宽度和高度分别是边界框的宽度和高度,再次分别用图像宽度和高度进行规格化(除以)。
考虑一个带有以下符号的示例:
– x-coordinate(in pixels) of the center of the bounding box
– y-coordinate(in pixels) of the center of the bounding
box
– width(in pixels) of the bounding box
– height(in pixels) of the bounding box
– width(in pixels) of the whole image
– height(in pixels) of the whole image
计算标签文件中的注释值,如下所示:
center-x =
center-y =
width =
height =
以上四项都是0到1之间的浮点值。
4. Download Pre-trained model
在训练目标检测时,最好利用在非常大的数据集上训练的现有模型,即使大数据集可能不包含要检测的目标。这个过程叫做迁移学习。
不需要从头训练,而是使用一个包含在ImageNet上训练的卷积权重的预训练模型。使用这些权重作为起始权重,网络可以更快地训练。现在把它下载到darknet文件夹。
cd
~/darknet
|
5. Data file
在文件中darknet数据(包括在代码分发中),需要提供有关目标检测器的规范和一些相关路径的信息。
classes = 1 |
train = /path/to/snowman/snowman_train.txt |
valid = /path/to/snowman/snowman_test.txt |
names = /path/to/snowman/classes.names |
backup = /path/to/snowman/weights/ |
classes参数需要类的数量在本例子为1。
需要提供雪人图库的snowman_train.txt 和snowman_test.txt绝对路径文件,分别有用于训练(训练参数)和验证(有效参数)的文件列表。
names字段表示包含所有类的名称的文件的路径。已经包括了classes.names,包含类名“snowman”的文件。需要在机器里提供它的绝对路径。
对于backup参数,需要提供到现有目录的路径,可以将中间权重文件存储为训练进展文件darknet数据(包括在代码分发中),需要提供有关目标检测的规范和一些相关路径的信息。
6。YOLOv3配置参数
darknet.data 和 classes.names文件中,YOLOv3还需要一个配置文件darknet-yolov3.cfg,包含在代码库中。基于演示yolov3-voc.cfg(带有darknet代码),用于在VOC数据集上进行训练。所有重要的训练参数都存储在此配置文件中。理解它们的含义和设置它们的值。
6.1 YOLOv3中的批量超参数
进一步了解批处理和细分参数。
[net] |
# Testing |
# batch=1 |
# subdivisions=1 |
# Training |
batch=64 |
subdivisions=16 |
batch参数表示训练期间使用的批大小。
训练集包含了几百张图片,但是使用数百万张图片进行训练并不少见。训练过程包括根据神经网络在训练数据集上的错误次数迭代更新神经网络的权值。 一使用训练集中的所有图像更新权重是不实际的(也是不必要的)。在一次迭代中使用一小部分图像,这个子集称为批处理大小。
当批量大小设置为64时,这意味着在一次迭代中使用64个图像来更新神经网络的参数。
6.2 Subdivisions configuration parameter in YOLOv3
即使使用64的批处理大小来训练,但可能没有具有足够内存的GPU来使用64的批处理大小。幸运的是,Darknet允许指定一个名为subdivisions的变量,该变量允许一次在GPU上处理批大小的一小部分。
可用subdivisions=1开始训练,如果出现内存不足错误,请将subdivisions参数增加2的倍数(例如2、4、8、16),直到训练成功进行。GPU将在任何时候处理图像的数量,但只有在处理完所有64个(如上所述)图像之后,完整的批处理或迭代才会完成。在测试期间,批次和细分都设置为1。
6.3 Width, Height, Channels
这些配置参数指定输入图像大小和通道数。
width=416 |
height=416 |
channels=3 |
训练前,首先将输入的训练图像调整为width x height。这里我们使用默认值416×416。如果增加到608×608,效果可能会有所改善,但训练时间也会更长。channels=3表示将处理3通道RGB输入图像。
6.4 Momentum and Decay
配置文件包含一些控制权重更新方式的参数。
momentum=0.9 |
decay=0.0005 |
前面提到了如何基于一小批图像而不是整个数据集更新神经网络的权重。由于这个原因,权重更新的波动很大。这就是为什么参数动量用于惩罚迭代之间的较大权重变化。 一个典型的神经网络有数百万个权值,很容易对任何训练数据进行过度拟合。过度拟合仅仅意味着在训练数据上会做得很好,而在测试数据上会做得很差。这几乎就像神经网络已经记住了训练集中所有图像的答案,但实际上并没有学习到潜在的概念。减轻这个问题的方法之一是惩罚权重的大值。参数衰减控制这个惩罚项。默认值工作得很好,但如果注意到过拟合,则可能需要对此进行调整。
6.5 Learning Rate, Steps, Scales, Burn In (warm-up)
learning_rate=0.001 |
policy=steps |
steps=3800 |
scales=.1 |
burn_in=400 |
参数学习率控制应该根据当前的一批数据学习的积极性。通常这是一个介于0.01和0.0001之间的数字。在训练过程的开始,从零信息开始的,学习率需要很高。神经网络看到了大量的数据,权值的变化需要减少。学习率需要随着时间的推移而降低。在配置文件中,学习率的降低是通过首先指定学习率降低策略是步骤来实现的。在上面的例子中,学习率将从0.001开始,在3800次迭代中保持不变,然后它将乘以比例得到新的学习率。可以指定多个步骤和比例。
在前一段中,提到学习率在开始时需要很高,以后需要很低。虽然这一说法基本上是正确的,但据经验发现,如果在一开始的短时间内学习率较低,训练速度往往会提高。这由burn_-in参数控制。有时这个磨合期也叫热身期。
6.6数据扩充
数据收集需要很长时间。首先要收集1000个图片,然后在每个图片周围手动创建边框。一个由5个数据采集器组成的团队花了1天的时间完成了这个过程。
希望通过编制新的数据来最大限度地利用这些数据。这个过程叫做数据扩充。例如,雪人旋转5度的图像仍然是雪人的图像。配置文件中的角度参数允许您以±角度随机旋转给定图像。
如果使用饱和度、曝光度和色调变换整个图片的颜色,仍然是雪人的图片。
angle=0 |
saturation = 1.5 |
exposure = 1.5 |
hue=.1 |
使用默认值进行训练。
6.7迭代次数
需要指定训练过程应该运行多少次迭代。最大批数=5200。对于多类对象检测,最大的批数更高,需要运行更多的批数(例如在yolov3 yolov3-voc.cfg中)。对于n类目标检查,建议至少对2000*n批进行训练。只有一个类的情况下,5200似乎是最大批量的安全数字。
max_batches=5200
7. Training YOLOv3
训练需要哪些不同的组件,开始训练过程。转到darknet目录并使用以下命令启动它:
cd ~/darknet |
./darknet detector train /path/to/snowman/darknet.data /path/to/snowman/darknet-yolov3.cfg ./darknet53.conv.74 > /path/to/snowman/train.log |
确保给出正确的路径darknet.data和 darknet-yolov3.cfg文件。我们还将训练日志保存到一个名为train.log数据集目录中,可以在训练继续进行时处理loss。 在训练中使用grep命令监视loss的一种有用方法是train.log文件。
grep
"avg"
/path/to/snowman/train.log
它显示批次号、当前批次中的损失、当前批次之前的平均损失、当前学习速率、批次所用的时间以及当前批次之前使用的图像。如下图所示,直到每批图像增加64个为止,使用的图像数一直在增加。将批处理大小设置为64。
可以看到,到第400批时,学习率从0逐渐增加到0.001。它将一直停在那里,直到第3800批,当它再次变为0.0001。
7.1何时停止训练?
随着训练的进行,日志文件包含每个批次的损失。在损失达到某个临界值之后,就应该停止训练。下面是根据雪人探测的批号绘制的损失。使用以下脚本生成绘图:
python3 plotTrainLoss.py /full/path/to/train.log
实际的测试应该是使用学习到的权重来查看mAP。原始的darknet代码没有用于计算mAP的代码。正致力于提供直接用补充增加代码计算mAP的代码,以便在保存权重文件时,可以监视精度并与mAP一起调用。看看AlexAB's fork of darknet的计算mAP。
对于雪人检测,在配置文件中只有5200次迭代。可以让它一直持续到最后。最后一次训练的权重档案,
darknet-yolov3_final.weights平均精度(mAP)为70.37%。
8. 测试模型
除了loss和mAP外,还应该在新数据上测试权重文件,并直观地查看结果,以确保对结果满意。在前面的文章中,描述了如何使用OpenCV测试YOLOv3模型。已经包含了测试雪人检测的代码。在目标检测中,需要给出模型配置和模型权重文件object_detection_yolo.py的正确路径并用图像或视频进行雪人检测。
python3 object_detection_yolo.py --image=snowmanImage.jpg
怎样训练YOLOv3
Training YOLOv3 : Deep Learning based Custom Object Detector
本文将在一些公开的雪人图片和视频上分享训练过程、有助于训练的脚本和结果。可以使用相同的过程来训练具有多个目标检测。
先下载代码,例如,
下载地址一:https://github.com/madhawav/YOLO3-4-Py
下载地址二:https://github.com/Eric3911/yolov3_darknet
1. 数据集
与任何深度学习任务一样,第一个最重要的任务是准备数据集。将使用谷歌OpenImagesV4数据集中的雪人图片,该数据集在网上公开发布。它是一个很大的数据集,大约有600个不同的对象类。数据集还包含这些对象的边界框批注。整体而言,数据集超过500GB,但将下载部分用于非商用产品开发的带有“雪人”对象的图像。
1.1 Download data
First we will need to install awscli
sudo
pip3
install
awscli
需要得到相关的openImages文件,class-descriptions-boxable.csv 和
train-annotations-bbox.csv (1.11GB) ,需要找到感兴趣的目标文件。
|
|
Next, move the above .csv files to the same folder as the downloaded code and then use the following script to download the data
随后,将above.csv文件移动到与下载的代码相同的文件夹中,使用以下脚本下载数据。
python3 getDataFromOpenImages_snowman.py
图像下载到JPEGImages文件夹,相应的标签文件写入labels文件夹。下载将获得770个雪人实例539张图片。jpeg图像和标签的大小都应该小于136mb。 对于多类目标检测,需要为每个类提供更多的样本,需要获得测试test-annotations-bbox.csv 和验证validation-annotations-bbox.csv,然后在python脚本中修改运行模式,重新运行以获取每个类的更多图像。在目前的雪人案例中,770个实例就足够了。
1.2 分段训练测试
机器学习训练过程都需要先将数据随机分成两组。
训练集:这是训练模型的数据部分。根据拥有的数据量,可以随机选择70%到90%的数据进行训练。
测试集:用来测试模型的数据的一部分,10-30%的数据。图像不应该是训练和测试集的一部分。
将JPEGImages文件夹中的图像分成训练和测试集。用下面的splitTrainAndTest.py脚本,将JPEGImages文件夹的完整路径作为参数传递。
python3 splitTrainAndTest.py /full/path/to/snowman/JPEGImages/
上面的脚本将数据分成一列(90%)和一个测试集(10%),并生成两个文件snowman_train.txt 和snowman_test.txt。
2. Darknet
使用Joseph Redmon的Darknet版本,这是一个用C语言编写的深度学习框架。
2.1 Download and build Darknet
Let’s first download and build it on your system.
|
|
|
|
2.2 Modify code to save model files regularly
在确保原始repo在您的系统中编译之后,让我们进行一些小的修改以存储中间权重。在examples/detector.c文件中,从
if(i%10000==0 || (i < 1000 && i%100 == 0)){
到
if(i%1000==0 || (i < 2000 && i%200 == 0)){
原始repo在每100次迭代后保存网络权重,直到第一次1000次,然后仅在每10000次迭代后保存。由于只使用一个类进行训练,希望训练收敛得更快。为了密切监视进度,每200次迭代后保存一次,直到达到2000次,然后每1000次迭代后保存一次。再次使用make命令重新编译darknet。使用NVIDIA GeForce GTX 1080 GPU进行了实验。现在了解一些成功运行训练所需的更多详细信息。
3. 数据注释
已将标签文件与“标签”文件夹中的批注共享。标签文件中的每个行条目表示图像中的单个边界框,并包含有关该框的以下信息:
<object-class-id> <center-x> <center-y> <width> <height>
第一个字段object-class-id是表示目标类。它的范围从0到(类数–1)。在现在的例子中,由于只有一个雪人等级,所以它总是设置为0。
第二个和第三个条目center-x和center-y分别是边框中心的x和y坐标,分别被图像宽度和高度规范化(除以)。
第四项和第五项、宽度和高度分别是边界框的宽度和高度,再次分别用图像宽度和高度进行规格化(除以)。
考虑一个带有以下符号的示例:
–
x-coordinate(in pixels) of the center of the bounding box
–
y-coordinate(in pixels) of the center of the bounding box
–
width(in pixels) of the bounding box
–
height(in pixels) of the bounding box
–
width(in pixels) of the whole image
– height(in pixels) of the whole image
计算标签文件中的注释值,如下所示:
center-x =
center-y =
width =
height =
以上四项都是0到1之间的浮点值。
4. Download Pre-trained model
在训练目标检测时,最好利用在非常大的数据集上训练的现有模型,即使大数据集可能不包含要检测的目标。这个过程叫做迁移学习。
不需要从头训练,而是使用一个包含在ImageNet上训练的卷积权重的预训练模型。使用这些权重作为起始权重,网络可以更快地训练。现在把它下载到darknet文件夹。
cd
~/darknet
|
5. Data file
在文件中darknet数据(包括在代码分发中),需要提供有关目标检测器的规范和一些相关路径的信息。
classes = 1 |
train = /path/to/snowman/snowman_train.txt |
valid = /path/to/snowman/snowman_test.txt |
names = /path/to/snowman/classes.names |
backup = /path/to/snowman/weights/ |
classes参数需要类的数量在本例子为1。
需要提供雪人图库的snowman_train.txt 和snowman_test.txt绝对路径文件,分别有用于训练(训练参数)和验证(有效参数)的文件列表。
names字段表示包含所有类的名称的文件的路径。已经包括了classes.names,包含类名“snowman”的文件。需要在机器里提供它的绝对路径。
对于backup参数,需要提供到现有目录的路径,可以将中间权重文件存储为训练进展文件darknet数据(包括在代码分发中),需要提供有关目标检测的规范和一些相关路径的信息。
6。YOLOv3配置参数
darknet.data 和 classes.names文件中,YOLOv3还需要一个配置文件darknet-yolov3.cfg,包含在代码库中。基于演示yolov3-voc.cfg(带有darknet代码),用于在VOC数据集上进行训练。所有重要的训练参数都存储在此配置文件中。理解它们的含义和设置它们的值。
6.1 YOLOv3中的批量超参数
进一步了解批处理和细分参数。
[net] |
# Testing |
# batch=1 |
# subdivisions=1 |
# Training |
batch=64 |
subdivisions=16 |
batch参数表示训练期间使用的批大小。
训练集包含了几百张图片,但是使用数百万张图片进行训练并不少见。训练过程包括根据神经网络在训练数据集上的错误次数迭代更新神经网络的权值。 一使用训练集中的所有图像更新权重是不实际的(也是不必要的)。在一次迭代中使用一小部分图像,这个子集称为批处理大小。
当批量大小设置为64时,这意味着在一次迭代中使用64个图像来更新神经网络的参数。
6.2 Subdivisions configuration parameter in YOLOv3
即使使用64的批处理大小来训练,但可能没有具有足够内存的GPU来使用64的批处理大小。幸运的是,Darknet允许指定一个名为subdivisions的变量,该变量允许一次在GPU上处理批大小的一小部分。
可用subdivisions=1开始训练,如果出现内存不足错误,请将subdivisions参数增加2的倍数(例如2、4、8、16),直到训练成功进行。GPU将在任何时候处理图像的数量,但只有在处理完所有64个(如上所述)图像之后,完整的批处理或迭代才会完成。在测试期间,批次和细分都设置为1。
6.3 Width, Height, Channels
这些配置参数指定输入图像大小和通道数。
width=416 |
height=416 |
channels=3 |
训练前,首先将输入的训练图像调整为width x height。这里我们使用默认值416×416。如果增加到608×608,效果可能会有所改善,但训练时间也会更长。channels=3表示将处理3通道RGB输入图像。
6.4 Momentum and Decay
配置文件包含一些控制权重更新方式的参数。
momentum=0.9 |
decay=0.0005 |
前面提到了如何基于一小批图像而不是整个数据集更新神经网络的权重。由于这个原因,权重更新的波动很大。这就是为什么参数动量用于惩罚迭代之间的较大权重变化。 一个典型的神经网络有数百万个权值,很容易对任何训练数据进行过度拟合。过度拟合仅仅意味着在训练数据上会做得很好,而在测试数据上会做得很差。这几乎就像神经网络已经记住了训练集中所有图像的答案,但实际上并没有学习到潜在的概念。减轻这个问题的方法之一是惩罚权重的大值。参数衰减控制这个惩罚项。默认值工作得很好,但如果注意到过拟合,则可能需要对此进行调整。
6.5 Learning Rate, Steps, Scales, Burn In (warm-up)
learning_rate=0.001 |
policy=steps |
steps=3800 |
scales=.1 |
burn_in=400 |
参数学习率控制应该根据当前的一批数据学习的积极性。通常这是一个介于0.01和0.0001之间的数字。在训练过程的开始,从零信息开始的,学习率需要很高。神经网络看到了大量的数据,权值的变化需要减少。学习率需要随着时间的推移而降低。在配置文件中,学习率的降低是通过首先指定学习率降低策略是步骤来实现的。在上面的例子中,学习率将从0.001开始,在3800次迭代中保持不变,然后它将乘以比例得到新的学习率。可以指定多个步骤和比例。
在前一段中,提到学习率在开始时需要很高,以后需要很低。虽然这一说法基本上是正确的,但据经验发现,如果在一开始的短时间内学习率较低,训练速度往往会提高。这由burn_-in参数控制。有时这个磨合期也叫热身期。
6.6数据扩充
数据收集需要很长时间。首先要收集1000个图片,然后在每个图片周围手动创建边框。一个由5个数据采集器组成的团队花了1天的时间完成了这个过程。
希望通过编制新的数据来最大限度地利用这些数据。这个过程叫做数据扩充。例如,雪人旋转5度的图像仍然是雪人的图像。配置文件中的角度参数允许您以±角度随机旋转给定图像。
如果使用饱和度、曝光度和色调变换整个图片的颜色,仍然是雪人的图片。
angle=0 |
saturation = 1.5 |
exposure = 1.5 |
hue=.1 |
使用默认值进行训练。
6.7迭代次数
需要指定训练过程应该运行多少次迭代。最大批数=5200。对于多类对象检测,最大的批数更高,需要运行更多的批数(例如在yolov3 yolov3-voc.cfg中)。对于n类目标检查,建议至少对2000*n批进行训练。只有一个类的情况下,5200似乎是最大批量的安全数字。
max_batches=5200
7. Training YOLOv3
训练需要哪些不同的组件,开始训练过程。转到darknet目录并使用以下命令启动它:
cd ~/darknet |
./darknet detector train /path/to/snowman/darknet.data /path/to/snowman/darknet-yolov3.cfg ./darknet53.conv.74 > /path/to/snowman/train.log |
确保给出正确的路径darknet.data和 darknet-yolov3.cfg文件。我们还将训练日志保存到一个名为train.log数据集目录中,可以在训练继续进行时处理loss。 在训练中使用grep命令监视loss的一种有用方法是train.log文件。
grep
"avg"
/path/to/snowman/train.log
它显示批次号、当前批次中的损失、当前批次之前的平均损失、当前学习速率、批次所用的时间以及当前批次之前使用的图像。如下图所示,直到每批图像增加64个为止,使用的图像数一直在增加。将批处理大小设置为64。
可以看到,到第400批时,学习率从0逐渐增加到0.001。它将一直停在那里,直到第3800批,当它再次变为0.0001。
7.1何时停止训练?
随着训练的进行,日志文件包含每个批次的损失。在损失达到某个临界值之后,就应该停止训练。下面是根据雪人探测的批号绘制的损失。使用以下脚本生成绘图:
python3 plotTrainLoss.py /full/path/to/train.log
实际的测试应该是使用学习到的权重来查看mAP。原始的darknet代码没有用于计算mAP的代码。正致力于提供直接用补充增加代码计算mAP的代码,以便在保存权重文件时,可以监视精度并与mAP一起调用。看看AlexAB's fork of darknet的计算mAP。
对于雪人检测,在配置文件中只有5200次迭代。可以让它一直持续到最后。最后一次训练的权重档案,
darknet-yolov3_final.weights平均精度(mAP)为70.37%。
8. 测试模型
除了loss和mAP外,还应该在新数据上测试权重文件,并直观地查看结果,以确保对结果满意。在前面的文章中,描述了如何使用OpenCV测试YOLOv3模型。已经包含了测试雪人检测的代码。在目标检测中,需要给出模型配置和模型权重文件object_detection_yolo.py的正确路径并用图像或视频进行雪人检测。
python3 object_detection_yolo.py --image=snowmanImage.jpg
References:
YOLOv3: An Incremental Improvement