Yolo目标检测和识别(第二课)

引用地址:

https://pjreddie.com/darknet/yolo/
https://blog.csdn.net/ch_liu23/article/details/53558549
https://blog.csdn.net/lengconglin/article/details/77367246

承接上一章

由于上一章修改Makefile中的OPENCV=1重新make却一直报错,因此一直在网上查找解决方案。最后重装了opencv,并且尝试了这个网站给出的解决方案,依然不能重新得到darknet的文件(因为只有得到了这个文件才算是make成功)。其中还把电脑搞崩了一次。。。然后只能放弃!O…O
darknet

在VOC数据集上训练Yolo

1. 首先获取Pascal VOC数据集

我们可以直接在这里下载数据集,也可以使用如下命令行下载和解压。
(在Yolo官网上,是在darknet文件夹下新建一个名为VOCdevkit的文件夹,然后在这个文件夹下下载和解压的,我们暂时也这样操作。解压后又会在VOCdevkit生成一个名为VOCdevkit的文件夹,其中包含解压后的VOC2007VOC2012,这两个文件夹中包含了Annotations/ImageSets/JPEGImages/SegmentationClass/SegmentationObject五个文件夹。具体里面都代表什么,等用到再讲吧)

wget https://pjreddie.com/media/files/VOCtrainval_11-May-2012.tar
wget https://pjreddie.com/media/files/VOCtrainval_06-Nov-2007.tar
wget https://pjreddie.com/media/files/VOCtest_06-Nov-2007.tar
tar xf VOCtrainval_11-May-2012.tar
tar xf VOCtrainval_06-Nov-2007.tar
tar xf VOCtest_06-Nov-2007.tar

下载和解压后的界面:

2. 产生VOC数据集图片的标签

Darknet需要读取.txt文件,每一张图片就要一个.txt文件来表示真实目标的位置。当然,一张图中可能存在多个目标,一个目标的位置写一行。如下格式:

    

其中x,y,width,height分别代表真实目标在原图中的左上角的横坐标、纵坐标、以及目标的宽和高。

为了生成这些文件,我们需要在Darknet文件夹下的scripts目录下运行voc_label.py。下载voc_label.py可用如下命令:(Darknet官网也是很调皮–>原话说:Let’s just download it again because we are lazy. 相信大家都看得懂,我就不解释了哈!)

wget https://pjreddie.com/media/files/voc_label.py

然后只需运行voc_label.py即可生成.txt文件。

python voc_label.py

打开生成的labels文件夹,可以看到很多.txt文件。如下图所示:
Yolo目标检测和识别(第二课)_第1张图片
打开000001.txt,可以看到如下图所示结果。其中一共包含两行数据,这表明这个图中包含两个目标。

**需要注意的一点:**Darknet官网给出的voc_label.py已经写好了读取文件路径,但是这个路径又跟原来我们一步步按照它的步骤来做的不一样,从而我运行的时候会报错。说找不到VOCdevkit/VOC2007/ImageSets/Main/train.txt这个文件。后来在这里找到了解决方法。也就是说,我们还要将解压后的VOCdevkit文件夹拷贝到scripts中。当然你也可以去修改voc_label.py中的路径,但是我修改了一下,感觉有点乱(因为路径中加了%s字符串怕搞混了),就还是拷贝了。最后我们就可以生成好几个.txt文件啦!(笔者只拷贝了VOC2007,所以只生成了3个)

**还有一点:**voc_label.py其中不但需要真实标签的路径,还可以设置想要生成.txt的集合和要检测哪些类别。这些都可以在第七行和第八、九行进行修改。
如:我只想训练和测试VOC2007,那么我就可以只拷贝解压后的VOC2007的数据到scripts文件夹。然后修改

sets=[('2012', 'train'), ('2012', 'val'), ('2007', 'train'), ('2007', 'val'), ('2007', 'test')]

sets=[('2007', 'train'), ('2007', 'val'), ('2007', 'test')]

(笔者这里就只拷了VOC2007到这个文件夹,所以修改了这个地方,其余没动)
如果你只想检测鸟这一类,则可以将

classes = ["aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"]

修改为

class = ["bird"]

**PS:**如果你修改了这里,那还有一个地方需要修改——voc.data(后面会讲到)

由于用于训练的样本包含train和val(其中train是指训练集,是用于真正训练的;val是指验证集,是作为验证训练的样本是否已经训练的足够好。)test则只用于测试阶段。因此需要将2007_train.txt和2007_val.txt进行合并。我们可以用下列指令合并之:

cat 2007_train.txt 2007_val.txt 2012_*.txt > train.txt

当然,笔者没有用到VOC2012,就不用写后面那个啦~

3. 为VOC数据集更改cfg文件

进入Darknet文件夹,更改cfg/voc.data配置文件:

classes= 20
train  = /train.txt
valid  = 2007_test.txt
names = data/voc.names
backup = backup

我们要用自己生成的train.txt和2007_test.txt的路径替换。如果你修改了voc_label.py中的class信息,那么这里的classes=20也要改变为相应的类别数量;voc.names也是一样,如果增加或减少了类别名称,也要在这里修改。backup是用来存放训练后的权重的,一开始backup是空的,训练过程中,会不断出现新的后缀为.weights的权重文件。每循环100,保存一次权重文件。但只会保存前10个权重,最后保存最后一个权重文件。

4. 下载预训练卷积权重

为了获的更好的训练效果,我们可以在这里下载预训练权重,也可以使用下列指令获得:(可直接在darknet文件夹下运行)

wget https://pjreddie.com/media/files/darknet53.conv.74

5. 开始训练

执行代码:

./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet53.conv.74

Yolo目标检测和识别(第二课)_第2张图片
上面是我现在正在训练的情况。

当然,我们总是不可能一帆风顺,作为程序员,总是要和bug作斗争!
虽然有时候没有报错,但是看到运行后,全是nan,就猜到错了。。。然后查看了yolov3-voc.cfg,训练时应当将前几行改为如下:

# Testing
# batch=1
# subdivisions=1
# Training
 batch=64
 subdivisions=16

然后运行了好久,也没有一直出现nan了。结果最后报错说out of memory,然后我又修改了yolov3-voc.cfg中的max_batches和steps。

max_batches = 5000 #50200
steps=1000,3000 #40000,45000

还不知道会不会报错,但是可以看到还是有一些地方总是nan =_=。又运行了几个小时还没跑完。。。跑完后下次继续写!

---------------------- 这是一天后的分割线 ---------------------
今天打开电脑后发现程序竟然还在运行!如下图,已经运行了1w多个epoch了。可我明明改了max_batches啊!
Yolo目标检测和识别(第二课)_第3张图片

实在等不了了,就停下来看看哪里出了问题。结果看了一下自己运行的命令,竟然是

./darknet detector train cfg/voc.data cfg/yolov3.cfg darknet53.conv.74

而我修改的网络配置文件确实yolov3-voc.cfg,分分钟奔溃!然后修改后重新运行,结果报错

yolov3-voc
Segmentation fault (core dumped)

可是我只修改了几个地方,怎么会报错呢?尝试了好几个yolov2.cfg和yolov2-voc.cfg等,在我修改过后都会报同样的错误!然后我把我下面修改的两处:max_batches和steps后注释的地方都删掉了(因为我担心破坏原来的数据,就每次都加了注释。)结果就能跑通了!现在我正在跑的是yolov2-voc.cfg,这些网络配置文件其实都是可以用的,只是yolov2的网络层没有yolov3的复杂。现在我的yolov2-voc.cfg中的数据是这样的:

[net]
# Testing
# batch=1
# subdivisions=1
# Training
batch=64
subdivisions=8
height=416
width=416
channels=3
momentum=0.9
decay=0.0005
angle=0
saturation = 1.5
exposure = 1.5
hue=.1

learning_rate=0.001
burn_in=1000
max_batches = 4000
policy=steps
steps=1000,3000
scales=.1,.1

其他的都没变。我也很好奇,为什么上面有注释的,下面我在max_batches和steps后注释就会报错。希望有明白的童鞋看到能解释一番~

----------------------- 又过了一天 ----------------------
训练完成后,进行测试,使用命令:

./darknet detector test cfg/voc.data cfg/yolov2-voc.cfg backup/yolov2-voc_final.weights data/eagle.jog

没有报错,但是检测没有出框。感觉原因可能是因为训练次数太少,max_batches只有4000,而图片数量却很大,从而训练的不够好。于是又重新修改,重新训练。后来发现还有一个地方需要修改。yolov2-voc.cfg中的filters,filters=num×(classes + coords + 1),yolov2和yolov3能够检测的类别不一样,前者是20类,后者是80类。num通常为5,coords=4,故将其修改为filters=5*(20+4+1)=125。
  对了,还有一处,examples中的darknet.c文件的437行(如果没找到,在这附近找)中的"cfg/coco.data"改为"cfg/voc.data",如下:

test_detector("cfg/voc.data", argv[2], argv[3], filename, thresh, .5, outfile, fullscreen);

因为我们修改的是voc.data,而不是coco.data,所以需要修改成自己用的文件。

最后,我们终于可以再次重新训练,max_batches依然设为4000,因为我们想尽快看到结果。但是发现一开始学习率一直为0,这时候可以修改burn_in这个值从1000改为100。

最后的最后,再再次重新训练。训练完后进行测试终于出了结果,如下:
Yolo目标检测和识别(第二课)_第4张图片
Yolo目标检测和识别(第二课)_第5张图片

由于我们的max_batches=4000,迭代次数较少。所以训练出的东西还是不够的。可以看出图片的框不是很准确,第二张图的狗没有检测出来,且旁边的马被误检为羊。如果按照原始的数据,max_batches=80200+, steps=40000,60000。最后检测出来的效果应该会跟原始提供的权重检测的结果相似,不会有太大区别。

终于,我们完成了darknet的yolov2对voc数据集的训练和测试。太不容易了!=o=

你可能感兴趣的:(Yolo目标检测和识别(第二课))