Darknet这种结构化的封装是一种学习启示,其中对图像数据的组织方式比较规律化,可以作为一种定式来学习。
这个主题主要是用比较简单的分类训练来说明这种定式的数据组织方式,数据组织可能需要程式化的处理,这里写了了一些Python脚本程序来验证这一点。同时训练了两种网络AlexNet与VGG,再次证明少量的ImageNet数据在VGG收敛是个考验。
除了程式化的训练数据预处理,可能标签工具的开发与应用也是一个方面,这个主题没有涉及。
-
掌握YOLO的训练,我们直接使用现成的darknet实现来训练。
-
相关的资源链接:
- yolo官网:
https://pjreddie.com/darknet/yolo/
- darknet官网:
https://pjreddie.com/darknet/
- github安装下载:
- Linux:
https://github.com/pjreddie/darknet
- windows:
https://github.com/AlexeyAB/darknet
- Linux:
- yolo官网:
DarkNet的下载与安装
下载
- 地址:
https://github.com/AlexeyAB/darknet
安装
- 解压
- 使用CMake -gui配置
- 基本上采用默认就行
- 使用Visual Studio打开工程
- 记得使用管理员权限打开工程
- 开始编译
- 选择【ALL BUILD】,在生成菜单选择【重新生成ALL BUILD】
- 选择【INSTALL】,在生成菜单选择【重新生成ALL BUILD】
- 编译需要一定时间
- 把安装路径设置为PATH,就可以在任何人地方使用darknet了
- 记得设置几个PATH
- 因为使用的是darknet提供的多线程库。
- 使用darknet工具
- 记得重启控制终端或者powershell。
- 下面使用随便一个非法的
-
选项来执行。会输出cuda与opencv的信息。具体的选项可以阅读C的源代码。
使用Darknet
- 可以提供很多选项来,使用darknet
- 下面使用detect指令执行,指令的使用帮助可以阅读源代码获取。
- ./darknet detect 模型文件 与训练的权重文件 检测的图像文件
-
测试需要准备的文件
- 网络结构配置文件:在下载包的cfg目录中有很多模型文件,我们使用
yolov3.cfg
- 预训练的模型文件:可以去下载:
https://pjreddie.com/darknet/yolo/
https://pjreddie.com/media/files/yolov3.weights
- 一张需要侦测的图像:可以随便找一张,在下载包的data目录中有几张官方的侦测图像。
- 网络结构配置文件:在下载包的cfg目录中有很多模型文件,我们使用
-
运行
darknet detect .\cfg\yolov3.cfg .\yolov3.weights .\data\person.jpg
使用python调用darknet
-
python调用darknet是加载dll或者so库来实现调用的。具体的范例在Darknet安装包提供了两个范例文件:
darknet.py
darknet_video.py
-
其中需要确认下dll库的名字是正确的。
- 这个例子实际就是python调用C编译动态库的例子。可以慢慢模仿调用。本质还是C/C++调用。
使用Darknet训练定制数据集
训练图像分类
-
图像分类训练的指令是:
./darknet classifier train cfg/imagenet1k.data cfg/csdarknet53-omega.cfg -topk
-
需要准备的条件:
- 网络模型结构的配置文件:cfg文件
- 训练相关的数据集描述
- 描述文件: data文件
-
train = data/imagenet1k.train.list
-
valid = data/inet.val.list
-
labels = data/imagenet.labels.list
-
names = data/imagenet.shortnames.list
-
classes = 1000
-
top=5
-
backup = backup
-
- 描述文件依赖的实际数据集
- 描述文件: data文件
DarkNet预训练的网络
- 下面是Darknet官方提供的图像分类预先训练的网络列表
分类网络的模型选择
- 下面使用VGG-D16作为测试
- 模型下载:
https://github.com/pjreddie/darknet/blob/master/cfg/vgg-16.cfg
- 模型下载:
[net]
# Training
# batch=128
# subdivisions=4
# Testing
batch=1
subdivisions=1
height=256
width=256
channels=3
learning_rate=0.00001
momentum=0.9
decay=0.0005
[crop]
crop_height=224
crop_width=224
flip=1
exposure=1
saturation=1
angle=0
[convolutional]
filters=64
size=3
stride=1
pad=1
activation=relu
[convolutional]
filters=64
size=3
stride=1
pad=1
activation=relu
[maxpool]
size=2
stride=2
[convolutional]
filters=128
size=3
stride=1
pad=1
activation=relu
[convolutional]
filters=128
size=3
stride=1
pad=1
activation=relu
[maxpool]
size=2
stride=2
[convolutional]
filters=256
size=3
stride=1
pad=1
activation=relu
[convolutional]
filters=256
size=3
stride=1
pad=1
activation=relu
[convolutional]
filters=256
size=3
stride=1
pad=1
activation=relu
[maxpool]
size=2
stride=2
[convolutional]
filters=512
size=3
stride=1
pad=1
activation=relu
[convolutional]
filters=512
size=3
stride=1
pad=1
activation=relu
[convolutional]
filters=512
size=3
stride=1
pad=1
activation=relu
[maxpool]
size=2
stride=2
[convolutional]
filters=512
size=3
stride=1
pad=1
activation=relu
[convolutional]
filters=512
size=3
stride=1
pad=1
activation=relu
[convolutional]
filters=512
size=3
stride=1
pad=1
activation=relu
[maxpool]
size=2
stride=2
[connected]
output=4096
activation=relu
[dropout]
probability=.5
[connected]
output=4096
activation=relu
[dropout]
probability=.5
[connected]
output=1000
activation=linear
[softmax]
groups=1
数据集准备与处理
- Darknet分类训练的数据集需要固定的组织格式。我们通过如下4类图像来进行处理。
- 数据集与数据描述文件的对应关系
-
为了偷懒,我这类的测试集与训练集完全一样,如果愿意也可以准备一些测试集
- shortname描述在训练的时候没有使用,在预测作为最终输出使用。
-
实际上,上面描述文件可以使用python写个工具程序来完成
- 规则清楚,代码的逻辑就很简单。
-
描述文件自动生成程序
import os
import cv2
class_names = ["organ", "palace", "roll", "skirt"]
dataset_dir = "./imagenet2012"
# 1. 生成shortnames.list文件
# ------遍历每个目录 ------
# 创建两个文件
yolo_dir = "yolo_desc" #描述文件的目录
train_filename = "train.list"
val_filename = "val.list"
labels_filename = "labels.list"
shortname_filename ="classnames.list"
# 判定目录是否存在,不存在就创建
if not os.path.exists(yolo_dir):
os.makedirs(yolo_dir)
# 在目录下创建两个文件,并后面循环中写入数据
train_filename = os.path.join(yolo_dir, train_filename)
val_filename = os.path.join(yolo_dir, val_filename)
fd_train = open(train_filename, 'w')
fd_val = open(val_filename, 'w')
# 2. 每个文件前的_name作为label.list的内容
# 3. 写图像清单到train.list与val.list(我们训练集作为验证集)
all_labels = [] # 保存内别标签
for sub in class_names:
# 构建图像的路径
sub_dir = os.path.join(dataset_dir, sub)
if os.path.exists(sub_dir):
# 列出文件(子目录不处理)
all_files = os.listdir(sub_dir)
for f in all_files:
full_filename = os.path.join(sub_dir, f)
# 保存文件名到描述文件
fd_train.write(full_filename + "\n")
fd_val.write(full_filename + "\n")
if os.path.isfile(full_filename):
# 解析文件名_前的标签
label_name = f.split("_")[0]
if not label_name in all_labels:
all_labels.append(label_name)
# 关闭清单文件
fd_train.close()
fd_val.close()
# 保存标签名与类别
labels_filename = os.path.join(yolo_dir, labels_filename)
shortname_filename = os.path.join(yolo_dir, shortname_filename)
fd_labels = open(labels_filename, 'w')
fd_shortnames = open(shortname_filename, 'w')
for label in all_labels:
fd_labels.write(label + "\n")
for short_name in class_names:
fd_shortnames.write(short_name + "\n")
fd_labels.close()
fd_shortnames.close()
- 创建的描述文件
- 最后生成data文件
- 文件名:
darknet_vgg16.data
- 文件名:
classes = 4
train = yolo_desc/train.list
valid = yolo_desc/val.list
backup = yolo_desc
labels = yolo_desc/labels.list
names = yolo_desc/classnames.list
top=1
分类训练
- 确保cfg文件冲参数与我们设置的参数一致:
- 注意:分类类别一定一致。
- 直接在命令行下执行命令
./darknet classifier train darknet_vgg16.data yolo_desc/vgg-16.cfg -topk
-
训练的批次最好保持合适的数字
- 建议64-128
-
技巧:
- 如果批次过大,可以考虑多次计算,然后累计误差计算梯度并更新。
使用分类训练集结果验证/分类
- 验证指令
darknet classifier valid darknet_vgg16.data yolo_desc/vgg-16.cfg yolo_desc/vgg-16_last.weights
- 预测指令
darknet classifier predict darknet_vgg16.data yolo_desc/vgg-16.cfg yolo_desc/vgg-16_last.weights imagenet2012\roll\n03887697_36.JPEG
- 数据应该打乱训练。
- 使用AlexNet网络训练,收敛的速度很快。
训练图像侦测
- 因为牵涉标注工具等的使用,我们单独用一个文档说明。
网友评论