使用yolov3训练自己的数据--详细过程及问题总结

环境说明
Ubuntu16.04/GPU 1080Ti/Cuda8

1. 下载YOLOv3

git clone https://github.com/pjreddie/darknet  
cd darknet  

2. 修改Makefile配置

GPU=1 #如果使用GPU设置为1,CPU设置为0
CUDNN=1  #如果使用CUDNN设置为1,否则为0
OPENCV=0 #如果调用摄像头,还需要设置OPENCV为1,否则为0
OPENMP=0  #如果使用OPENMP设置为1,否则为0
DEBUG=0  #如果使用DEBUG设置为1,否则为0


ARCH= -gencode arch=compute_61,code=sm_61 #根据自己型号配置,可参考:http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#virtual-architecture-feature-list
#      -gencode arch=compute_20,code=[sm_20,sm_21] \ This one is deprecated?

# This is what I use, uncomment if you know your arch and want to specify
# ARCH= -gencode arch=compute_52,code=compute_52

VPATH=./src/:./examples
SLIB=libdarknet.so
ALIB=libdarknet.a
EXEC=darknet
OBJDIR=./obj/

CC=gcc
NVCC=/usr/local/cuda-8.0/bin/nvcc   #NVCC=nvcc 修改为自己的路径
AR=ar
ARFLAGS=rcs
OPTS=-Ofast
LDFLAGS= -lm -pthread 
COMMON= -Iinclude/ -Isrc/
CFLAGS=-Wall -Wno-unused-result -Wno-unknown-pragmas -Wfatal-errors -fPIC

ifeq ($(OPENMP), 1) 
CFLAGS+= -fopenmp
endif

ifeq ($(DEBUG), 1) 
OPTS=-O0 -g
endif

CFLAGS+=$(OPTS)

ifeq ($(OPENCV), 1) 
COMMON+= -DOPENCV
CFLAGS+= -DOPENCV
LDFLAGS+= `pkg-config --libs opencv` 
COMMON+= `pkg-config --cflags opencv` 
endif

ifeq ($(GPU), 1) 
COMMON+= -DGPU -I/usr/local/cuda-8.0/include #修改为自己的路径
CFLAGS+= -DGPU
LDFLAGS+= -L/usr/local/cuda-8.0/lib64 -lcuda -lcudart -lcublas -lcurand #修改为自己的路径
endif

ifeq ($(CUDNN), 1) 
COMMON+= -DCUDNN 
CFLAGS+= -DCUDNN
LDFLAGS+= -lcudnn
endif

OBJ=gemm.o utils.o cuda.o deconvolutional_layer.o convolutional_layer.o list.o image.o activations.o im2col.o col2im.o blas.o crop_layer.o dropout_layer.o maxpool_layer.o softmax_layer.o data.o matrix.o network.o connected_layer.o cost_layer.o parser.o option_list.o detection_layer.o route_layer.o upsample_layer.o box.o normalization_layer.o avgpool_layer.o layer.o local_layer.o shortcut_layer.o logistic_layer.o activation_layer.o rnn_layer.o gru_layer.o crnn_layer.o demo.o batchnorm_layer.o region_layer.o reorg_layer.o tree.o  lstm_layer.o l2norm_layer.o yolo_layer.o
EXECOBJA=captcha.o lsd.o super.o art.o tag.o cifar.o go.o rnn.o segmenter.o regressor.o classifier.o coco.o yolo.o detector.o nightmare.o darknet.o
ifeq ($(GPU), 1) 
LDFLAGS+= -lstdc++ 
OBJ+=convolutional_kernels.o deconvolutional_kernels.o activation_kernels.o im2col_kernels.o col2im_kernels.o blas_kernels.o crop_layer_kernels.o dropout_layer_kernels.o maxpool_layer_kernels.o avgpool_layer_kernels.o
endif

EXECOBJ = $(addprefix $(OBJDIR), $(EXECOBJA))
OBJS = $(addprefix $(OBJDIR), $(OBJ))
DEPS = $(wildcard src/*.h) Makefile include/darknet.h

all: obj backup results $(SLIB) $(ALIB) $(EXEC)
#all: obj  results $(SLIB) $(ALIB) $(EXEC)


$(EXEC): $(EXECOBJ) $(ALIB)
        $(CC) $(COMMON) $(CFLAGS) $^ -o $@ $(LDFLAGS) $(ALIB)

$(ALIB): $(OBJS)
        $(AR) $(ARFLAGS) $@ $^

$(SLIB): $(OBJS)
        $(CC) $(CFLAGS) -shared $^ -o $@ $(LDFLAGS)

$(OBJDIR)%.o: %.c $(DEPS)
        $(CC) $(COMMON) $(CFLAGS) -c $< -o $@

$(OBJDIR)%.o: %.cu $(DEPS)
        $(NVCC) $(ARCH) $(COMMON) --compiler-options "$(CFLAGS)" -c $< -o $@

obj:
        mkdir -p obj
backup:
        mkdir -p backup
results:
        mkdir -p results

.PHONY: clean

clean:
        rm -rf $(OBJS) $(SLIB) $(ALIB) $(EXEC) $(EXECOBJ) $(OBJDIR)/*

保存完成后,在此路径下执行make。
3. 准备训练数据集
此部分可参考:https://blog.csdn.net/hitzijiyingcai/article/details/81636455
其中VOCdevkit 可以放在scripts目录下。
按下列文件夹结构,将训练数据集放到各个文件夹下面,生成4个训练、测试和验证txt文件列表
VOCdevkit
—VOC2007
——Annotations
——ImageSets
———Layout
———Main
———Segmentation
——JPEGImages
Annotations中是所有的xml文件
JPEGImages中是所有的训练图片
Main中是4个txt文件,其中test.txt是测试集,train.txt是训练集,val.txt是验证集,trainval.txt是训练和验证集。
4个文件中内容如下,只保留文件名称,没有后缀。

使用yolov3训练自己的数据--详细过程及问题总结_第1张图片
生成2007_train.txt和2007_val.txt文件
编辑./scripts/voc_label.py,如下:
使用yolov3训练自己的数据--详细过程及问题总结_第2张图片
其中sets中内容代表要生成train和val两个文件,classes代表自己的训练类别。
运行python voc_label.py,生成2007_train.txt训练文件列表。
在这里插入图片描述
4.下载Imagenet上预先训练的权重

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

放在model目录下
5. 修改cfg/voc.data
在这里插入图片描述
6. 在darknet文件夹下面新建文件夹backup
7. 修改data/voc.name为样本集的标签名

cat
dog
person
fish
card
8. 修改cfg/yolov3-voc.cfg

[net]
# Testing            ### 测试模式                                          
# batch=1
# subdivisions=1
# Training           ### 训练模式,每次前向的图片数目 = batch/subdivisions 
batch=64
subdivisions=16
width=416            ### 网络的输入宽、高、通道数
height=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 = 5000  ### 迭代次数                                          
policy=steps         ### 学习率策略 
steps=40000,45000    ### 学习率变动步长 
scales=.1,.1         ### 学习率变动因子  



[convolutional]
batch_normalize=1    ### BN
filters=32           ### 卷积核数目
size=3               ### 卷积核尺寸
stride=1             ### 卷积核步长
pad=1                ### pad
activation=leaky     ### 激活函数

......

[convolutional]
size=1
stride=1
pad=1
filters=30  #3*(5+4+1)
activation=linear

[yolo]
mask = 6,7,8
anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
classes=5  #类别
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=0  #1,如果显存很小,将random设置为0,关闭多尺度训练;
......

[convolutional]
size=1
stride=1
pad=1
filters=30  #3*(5+4+1)
activation=linear

[yolo]
mask = 3,4,5
anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
classes=5  #类别
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=0  #1,如果显存很小,将random设置为0,关闭多尺度训练;
......

[convolutional]
size=1
stride=1
pad=1
filters=30  #3*(5+4+1)
activation=linear

[yolo]
mask = 0,1,2
anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
classes=5  #类别
num=9
jitter=.3  # 数据扩充的抖动操作
ignore_thresh = .5  #文章中的阈值1
truth_thresh = 1  #文章中的阈值2
random=0  #1,如果显存很小,将random设置为0,关闭多尺度训练;

9. 开始训练

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

中间结果如下:
使用yolov3训练自己的数据--详细过程及问题总结_第3张图片
上面输出信息参数的意义
Region xx: cfg文件中yolo-layer的索引;
Avg IOU:当前迭代中,预测的box与标注的box的平均交并比,越大越好,期望数值为1;
Class: 标注物体的分类准确率,越大越好,期望数值为1;
obj: 越大越好,期望数值为1;
No obj: 越小越好;
.5R: 以IOU=0.5为阈值时候的recall; recall = 检出的正样本/实际的正样本
0.75R: 以IOU=0.75为阈值时候的recall;
count:正样本数目。

10. 识别

方法1:

./darknet detect cfg/yolov3-voc.cfg backup/yolov3-voc_final.weights data/dog.jpg

注意:使用detect参数进行检测,默认用的是coco.names文件的类别,应该适配改一下。
方法2:

./darknet detector test cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_final.weights data/pet/american_bulldog_56.jpg

要注意detect和detector参数是不同的。
方法3:
也可以修改python/darknet.py,然后进行批量测试。
在这里插入图片描述
注意:此脚本输出的坐标信息不是检测框2个点,而是检测框中心位置和框大小,画框时需要简单转换一下,如下:

left = 589-int(366/2)
top = 525-int(415/2)
right = 589+int(366/2)
bottom = 525+int(415/2)

迭代500次效果:
使用yolov3训练自己的数据--详细过程及问题总结_第4张图片
迭代1700次效果:
使用yolov3训练自己的数据--详细过程及问题总结_第5张图片
迭代10000次效果:
使用yolov3训练自己的数据--详细过程及问题总结_第6张图片
11. 问题
11.1训练报错
使用yolov3训练自己的数据--详细过程及问题总结_第7张图片
cfg/yolov3-voc.cfg中filters配置错误,这个要根据自己类别数按照公式3*(Class+4+1)配置。
11.2
使用yolov3训练自己的数据--详细过程及问题总结_第8张图片
由于在步骤3中准备好数据后,为调用voc_label.py生成2007_train.txt和2007_val.txt。
11.3
运行python/darknet.py,报错:
在这里插入图片描述
在python/darknet.py中将so文件路径写死。

参考资料:
https://blog.csdn.net/john_bh/article/details/80625220
https://github.com/pjreddie/darknet/issues/559
http://shartoo.github.io/darknet_on_tx2/

你可能感兴趣的:(目标检测)