YOLO V2v3教程之训练自己的数据还有一些自己面对的问题

 

1. yolo v2很多文件和v1不一样,而且迭代了很多个版,网上现有的V2教程里的src/yolo_kernels.cu已经没有了,这一步改动不用管

2. 教程http://blog.csdn.net/hysteric314/article/details/54097845(记得修改完要重新make)

3.有关于测试阈值改动、中间参数可视化(不能直接用,因为中间参数格式变了)的教程

http://blog.csdn.net/hrsstudy/article/details/65644517?utm_source=itdadao&utm_medium=referral

4. 为了让YOLO v2能像训练VOC数据集一样训练自己的数据集,需要对代码进行以下三个方面的修改: (我在svt数据集上做图像文本检测,是1类text)
一:修改分类的个数:在代码中,默认VOC数据集是20类,而我要改成1类。 
二:准备txt文档:VOC训练数据集中会自带几个txt文档,用来指明文件名或者路径地址,而如果你使用你自己的数据可能就需要自己生成这些文档。 
三:修改代码中路径信息,把代码中VOC训练数据集的路径改成自己训练数据集的路径

5. 把20类改成1类

1) cfg/voc.data文件中:

classes 改成1。

names=data/svt.names。

svt.names这一个文件要存在于darknet目录下的data文件夹里,创建一个svt.names,加上内容,当然名字和路径都可以自己定义。这个文件中的行数要和类数一致,每一行都是一个类别的名字。比如我的这一文件中就只有一行数据:“text”。这个文件在测试你训练的model的时候会用到,系统会在图片上画出bounding box,bounding box上面的文字,也就是这个框中物体的名字,应该就来自这个文件。

2) cfg/yolo_voc.cfg文件中 :

【region】层中 classes 改成1。

【region】层上方第一个【convolution】层,其中的filters值要进行修改,改成(classes+ coords+ 1)* (NUM) ,我的情况中:(1+4+1)* 5=30,我把filters 的值改成了30。

3) src/yolo.c文件中 :

位置大约第14行左右改成:char *voc_names={“text”},原来里面有20类的名字,我改成了唯一1类的名字。

位置大约第328行左右,修改draw_detection这个函数最后一个参数:20改成1。这个函数用于把系统检测出的框给画出来,并把画完框的图片传回第一个参数im中,用于保存和显示。

位置大约第361行左右,demo函数中,倒数第三个参数把20改成了1。

scripts/voc_label.py 文件中 :

这里我不是用作者的代码,因为当时v1的这个文件跑不出来,所以找了另外的

# -*- coding: utf-8 -*-    

import os  

l=["text"]  

for word in l:   

os.system("convert -fill black -background white -bordercolor white -border 4  -font /usr/share/fonts/truetype/arphic/ukai.ttc -pointsize 18 label:\"%s\" \"%s.png\""%(word, word))

6. 数据格式转换(准备txt文档)

一共需要准备四种txt格式文档,分别是记录训练集和测试集的坐标和路径的annotation文件和list文件。

1) 每张图片一个annotation,但是存放路径和V1不同。

V1:需要的是labels的.png文件名称和放图片的文件夹以及放annotation的文件夹名称对应。至于annotation生成之后放在哪里,事实上路径是默认在train.txt的路径其中的JPEGImages改成labels,路径的其余部分不变。

V2:labels的.png文件名称就是和类别名称一样,测试集和训练集分别放在两个文件夹(不知是否也适用于多类),通过2) 中的list文件来指明每张图片的完整路径,那么每张图片annotation的txt文件放在哪呢?

因为在训练集中,一个图片文件和这一图片文件对应标记文件,他们俩除了后缀名之外其余的名称是一样的,所以src/yolo.c中有以下语句:

          find_replace(path, "dout", "labels", labelpath);

          find_replace(labelpath, "JPEGImages", "labels", labelpath);

          find_replace(labelpath, ".jpg", ".txt", labelpath);

          find_replace(labelpath, ".JPEG", ".txt", labelpath);

函数会找到路径中的图片后缀名.jpg,自动替换成.txt,所以只需要把这些txt格式的标记文件复制到图片所在的目录下即可。系统根据替换后的路径地址来读取对应标记文件。

2) 所有训练图片一个路径list,测试集也是一个list文件。下面会说明如何在代码中修改路径信息,指向这两个文件。

7. 修改路径

1) cfg/voc.data文件中:

train = /home/pjreddie/data/voc/train.txt //修改为训练list的路径

valid = /home/pjreddie/data/voc/2007_test.txt /*修改为测试list的路径,因为test不能返回评价指标,valid才行*/

backup = backup /* 这个路径是YOLO用于备份的,在训练过程中YOLO会不断地对产生的weights文件进行备份,darknet目录下就自带一个backup文件夹,这个路径指向那里。这里建议修改为自己的路径 */

2) src/yolo.c 文件中:

train_yolo函数中:

char *train_images = "/data/voc/train.txt"; //修改为训练list的路径

char *backup_directory = "/home/pjreddie/backup/"; //修改为上面的backup路径

validate_yolo函数中:

char *base = "results/comp4_det_test_"; /*可以修改自己的路径,comp4_det_test_[类名].txt用于保存valid命令的测试结果*/

list *plist = get_paths("/home/pjreddie/data/voc/2007_test.txt");//修改为测试list的路径

validate_yolo_recall函数中:

char *base = "results/comp4_det_test_"; //可以修改自己的路径

list *plist = get_paths("data/voc.2007.test"); //修改为测试list的路径

3) src/detector.c 文件中: 

char *train_images = option_find_str(options, "train", "data/train.list"); //修改为训练list的路径

char *backup_directory = option_find_str(options, "backup", "/backup/"); //修改为自己的backup路径

validate_detector_flip函数中:

char *valid_images = option_find_str(options, "valid", "data/train.list"); //修改为测试list路径,该函数对应的测试命令为valid2

validate_detector函数中:

char *valid_images = option_find_str(options, "valid", "data/train.list"); /*修改为测试list路径,该函数对应的测试命令为valid*/

validate_detector_recall函数中:

list *plist = get_paths("data/voc.2007.test"); //修改成测试list路径

8. 调整评价指标

src/detector.c 文件中:

1) 修改评估阈值

评估模型可以使用命令valid或recall

修改valid2阈值(默认.005),validate_detector_flip函数中:

float thresh = .005; //修改为需要的阈值如.1

修改valid阈值(默认.005),validate_detector函数中:

float thresh = .005; //修改为需要的阈值如.1

修改recall阈值(默认为.001),validate_detector_recall函数中:

float thresh = .001; // 修改为需要的阈值如.25

2) 增加返回precision指标并注明指标名称

//fprintf(stderr, "%5d %5d %5d\tRPs/Img: %.2f\tIOU: %.2f%%\tRecall:%.2f%%\n", i, correct, total, (float)proposals/(i+1), avg_iou*100/total, 100.*correct/total);

fprintf(stderr, "ID:%5d Correct:%5d Total:%5d\tRPs/Img: %.2f\tIOU: %.2f%%\tRecall:%.2f%%\t", i, correct, total, (float)proposals/(i+1), avg_iou*100/total, 100.*correct/total);

fprintf(stderr, "proposals:%5d\tPrecision:%.2f%%\n",proposals,100.*correct/(float)proposals);

//评价指标都是累积的,而不是单张图片的

9. 修改完上面所有之后,就可以开始训练啦,最重要的别忘了先重新make:

make clean

make -j16

否则框不出东西别怪我哈哈哈,当然忘了重新make训练出来的权重是不受影响的

训练命令:

./darknet detector train cfg/voc.data cfg/yolo-voc.cfg darknet19_448.conv.23 | tee  ./svt_train_log.txt

一般我都用| tee [路径+文件名] (后面加上-a是续写)命令,或者ls -l >[路径+文件名] (>>[路径+文件名]则是续写)命令,来导出中间过程,一方面备份方便查看,另一方面可以根据中间参数画出图表来分析,第2点的教程里有共享可视化中间参数的代码,但是不能直接用,因为中间参数格式变了

10. 测试并返回评价指标

1) ./darknet detector test cfg/voc.data cfg/yolo-voc.cfg ./svt/backup/yolo-voc_final.weights

/*不现实评价指标,输入图片路径,只显示框好后的图片和类别、置信率*/

2) ./darknet detector valid cfg/voc.data cfg/yolo-voc.cfg backup/yolo-voc_final.weights

/*在终端只返回用时,在./results/comp4_det_test_[类名].txt里保存测试结果*/

3) ./darknet detector recall cfg/voc.data cfg/yolo-voc.cfg backup/yolo-voc_final.weights

/*依次ID:图片序号从0开始,correct:累计检测正确的总框数,total:累计的总ground truth数,RPs/Img: 累计的总proposals/已检测图片数,IOU,Recall: correct / total,proposals:累计的总框数,Precision: correct / proposals*/

猜你喜欢

转载自blog.csdn.net/duanyajun987/article/details/88696009
今日推荐